From 3365211507b013e1690eed25c59d992a55ae9fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=97=B6=E7=91=BE?= <74231782+sj817@users.noreply.github.com> Date: Mon, 29 Dec 2025 03:14:17 +0800 Subject: [PATCH] =?UTF-8?q?ci:=20=E6=B7=BB=E5=8A=A0=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E8=AF=84=E8=AE=BA=E4=B8=AD=E7=9A=84=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E9=93=BE=E6=8E=A5=E5=92=8C=E8=8E=B7=E5=8F=96=20artifa?= =?UTF-8?q?cts=20=E5=88=97=E8=A1=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/scripts/lib/comment.ts | 19 +++++++++++----- .github/scripts/lib/github.ts | 16 ++++++++++++- .github/scripts/pr-build-result.ts | 36 +++++++++++++++++++++++++----- 3 files changed, 59 insertions(+), 12 deletions(-) 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);