diff --git a/.github/workflows/artifacts.yml b/.github/workflows/artifacts.yml new file mode 100644 index 0000000..33ec94c --- /dev/null +++ b/.github/workflows/artifacts.yml @@ -0,0 +1,106 @@ +name: Post build artifact links + +# Runs in the context of the base (upstream) repo after the build workflow +# completes — this gives the GITHUB_TOKEN write access to PRs even when +# the build was triggered by a fork PR. +on: + workflow_run: + workflows: ["C/C++ CI"] + types: [completed] + +permissions: + actions: read + pull-requests: write + +jobs: + post-artifacts: + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + steps: + - name: Comment artifact links on PR + uses: actions/github-script@v7 + with: + script: | + const run = context.payload.workflow_run; + const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${run.id}`; + + // Find associated PR number from the triggering workflow run + const prs = run.pull_requests; + if (!prs || prs.length === 0) { + // Fallback: search for open PR matching the head branch/SHA + const { data: pulls } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + head: `${run.head_repository.owner.login}:${run.head_branch}`, + }); + if (pulls.length === 0) { + console.log('No associated PR found, skipping.'); + return; + } + prs.push(pulls[0]); + } + const prNumber = prs[0].number; + + // Fetch artifacts from the completed workflow run + const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: run.id, + }); + + let rows = ''; + for (const a of artifacts) { + const dlUrl = `${runUrl}/artifacts/${a.id}`; + rows += `| ${a.name} | [${a.name}](${dlUrl}) | ${(a.size_in_bytes / 1024).toFixed(0)} KB |\n`; + } + + if (!rows) { + rows = `| - | No artifacts found | - |\n`; + } + + // Check for existing comment to update (upsert pattern) + const comments = await github.paginate( + github.rest.issues.listComments, + { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + per_page: 100, + } + ); + const marker = ''; + const existing = comments.find(c => c.body.includes(marker)); + + const body = [ + marker, + '### Build Artifacts', + '', + '| Platform | Download | Size |', + '|----------|----------|------|', + rows.trim(), + '', + `> [Full workflow run](${runUrl})`, + '', + `Updated by CI at ${new Date().toISOString()}`, + ].join('\n'); + + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + console.log(`Updated comment ${existing.id} on PR #${prNumber}`); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body, + }); + console.log(`Created new comment on PR #${prNumber}`); + } diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 081a53c..85f4a91 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -6,11 +6,6 @@ on: pull_request: branches: [ master ] -permissions: - actions: read - contents: read - pull-requests: write - jobs: build: strategy: @@ -80,73 +75,3 @@ jobs: name: ${{ matrix.config.displayTargetName }} path: ${{ matrix.config.artifact }} if-no-files-found: error - - post-artifacts: - if: github.event_name == 'pull_request' - needs: build - runs-on: ubuntu-latest - steps: - - name: Comment artifact links on PR - continue-on-error: true - uses: actions/github-script@v7 - with: - script: | - const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; - - // Fetch actual artifact list from this workflow run - const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.runId, - }); - - let rows = ''; - for (const a of artifacts) { - const dlUrl = `${runUrl}/artifacts/${a.id}`; - rows += `| ${a.name} | [${a.name}](${dlUrl}) | ${(a.size_in_bytes / 1024).toFixed(0)} KB |\n`; - } - - if (!rows) { - rows = `| - | No artifacts found | - |\n`; - } - - const comments = await github.paginate( - github.rest.issues.listComments, - { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - per_page: 100, - } - ); - const marker = ''; - const existing = comments.find(c => c.body.includes(marker)); - - const body = [ - marker, - '### Build Artifacts', - '', - '| Platform | Download | Size |', - '|----------|----------|------|', - rows.trim(), - '', - `> [Full workflow run](${runUrl})`, - '', - `Updated by CI at ${new Date().toISOString()}`, - ].join('\n'); - - if (existing) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existing.id, - body, - }); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body, - }); - }