diff --git a/.github/scripts/lib/comment.ts b/.github/scripts/lib/comment.ts index ab970f49..27fb2ce9 100644 --- a/.github/scripts/lib/comment.ts +++ b/.github/scripts/lib/comment.ts @@ -10,6 +10,7 @@ export interface BuildTarget { name: string; status: BuildStatus; error?: string; + downloadUrl?: string; // Artifact 直接下载链接 } // ============== 辅助函数 ============== @@ -70,8 +71,8 @@ export function generateResultComment ( runId: string, repository: string ): string { - const artifactUrl = `https://github.com/${repository}/actions/runs/${runId}/artifacts`; - const logUrl = `https://github.com/${repository}/actions/runs/${runId}`; + // 链接到 run 详情页,页面底部有 Artifacts 下载区域 + const runUrl = `https://github.com/${repository}/actions/runs/${runId}`; const allSuccess = targets.every(t => t.status === 'success'); const anyCancelled = targets.some(t => t.status === 'cancelled'); @@ -82,8 +83,14 @@ export function generateResultComment ( ? '⚪ 构建已取消' : '❌ 构建失败'; - const downloadLink = (status: BuildStatus) => - status === 'success' ? `[📦 下载](${artifactUrl})` : '—'; + const downloadLink = (target: BuildTarget) => { + if (target.status !== 'success') return '—'; + if (target.downloadUrl) { + return `[📦 下载](${target.downloadUrl})`; + } + // 回退到 run 详情页 + return `[📦 下载](${runUrl}#artifacts)`; + }; const lines: string[] = [ COMMENT_MARKER, @@ -91,12 +98,12 @@ export function generateResultComment ( '', '| 构建目标 | 状态 | 下载 |', '| :--- | :--- | :--- |', - ...targets.map(t => `| ${t.name} | ${getStatusIcon(t.status)} | ${downloadLink(t.status)} |`), + ...targets.map(t => `| ${t.name} | ${getStatusIcon(t.status)} | ${downloadLink(t)} |`), '', '---', '', `📝 **提交**: \`${formatSha(prSha)}\``, - `🔗 **构建日志**: [查看详情](${logUrl})`, + `🔗 **构建日志**: [查看详情](${runUrl})`, ]; // 添加错误详情 diff --git a/.github/scripts/lib/github.ts b/.github/scripts/lib/github.ts index c0e82be9..652a7f01 100644 --- a/.github/scripts/lib/github.ts +++ b/.github/scripts/lib/github.ts @@ -24,7 +24,14 @@ export interface Repository { }; } -// ============== GitHub API Client ============== +export interface Artifact { + id: number; + name: string; + size_in_bytes: number; + archive_download_url: string; +} + +// ============== GitHub API Client ========================== export class GitHubAPI { private token: string; @@ -76,6 +83,13 @@ export class GitHubAPI { } } + async getRunArtifacts (owner: string, repo: string, runId: string): Promise { + const data = await this.request<{ artifacts: Artifact[]; }>( + `/repos/${owner}/${repo}/actions/runs/${runId}/artifacts` + ); + return data.artifacts; + } + async createComment (owner: string, repo: string, issueNumber: number, body: string): Promise { await this.request(`/repos/${owner}/${repo}/issues/${issueNumber}/comments`, { method: 'POST', diff --git a/.github/scripts/pr-build-result.ts b/.github/scripts/pr-build-result.ts index 23db2437..c8308fe1 100644 --- a/.github/scripts/pr-build-result.ts +++ b/.github/scripts/pr-build-result.ts @@ -43,13 +43,39 @@ async function main (): Promise { console.log(`Framework: ${frameworkStatus}${frameworkError ? ` (${frameworkError})` : ''}`); console.log(`Shell: ${shellStatus}${shellError ? ` (${shellError})` : ''}\n`); - const targets: BuildTarget[] = [ - { name: 'NapCat.Framework', status: frameworkStatus, error: frameworkError }, - { name: 'NapCat.Shell', status: shellStatus, error: shellError }, - ]; - const github = new GitHubAPI(token); const repository = `${owner}/${repo}`; + + // 获取 artifacts 列表,生成直接下载链接 + const artifactMap: Record = {}; + try { + const artifacts = await github.getRunArtifacts(owner, repo, runId); + console.log(`Found ${artifacts.length} artifacts`); + for (const artifact of artifacts) { + // 生成直接下载链接:https://github.com/{owner}/{repo}/actions/runs/{run_id}/artifacts/{artifact_id} + const downloadUrl = `https://github.com/${repository}/actions/runs/${runId}/artifacts/${artifact.id}`; + artifactMap[artifact.name] = downloadUrl; + console.log(` - ${artifact.name}: ${downloadUrl}`); + } + } catch (e) { + console.log(`Warning: Failed to get artifacts: ${(e as Error).message}`); + } + + const targets: BuildTarget[] = [ + { + name: 'NapCat.Framework', + status: frameworkStatus, + error: frameworkError, + downloadUrl: artifactMap['NapCat.Framework'], + }, + { + name: 'NapCat.Shell', + status: shellStatus, + error: shellError, + downloadUrl: artifactMap['NapCat.Shell'], + }, + ]; + const comment = generateResultComment(targets, prSha, runId, repository); await github.createOrUpdateComment(owner, repo, prNumber, comment, COMMENT_MARKER);