From 0e3932cad03c1a38b45e77a7ce27b004fa69adab Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Thu, 4 Jun 2026 14:11:31 -0400 Subject: [PATCH] Run bundle analysis comment as a separate workflow to allow forked PRs to work --- .github/workflows/bundle-analysis-comment.yml | 57 +++++++++++++++++++ .github/workflows/bundle-analysis.yml | 31 +++++----- 2 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/bundle-analysis-comment.yml diff --git a/.github/workflows/bundle-analysis-comment.yml b/.github/workflows/bundle-analysis-comment.yml new file mode 100644 index 000000000..be52eea10 --- /dev/null +++ b/.github/workflows/bundle-analysis-comment.yml @@ -0,0 +1,57 @@ +name: Bundle Analysis Comment + +# Runs after "Bundle Analysis" completes. Because `workflow_run` always executes +# in the context of the base repository's default branch, it receives a token +# with the permissions declared below — even when the triggering run came from a +# fork PR (which only gets a read-only token). This job never checks out or runs +# PR code; it only downloads the already-rendered comment artifact and posts it, +# so handing it a write token is safe. +on: + workflow_run: + workflows: ["Bundle Analysis"] + types: [completed] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }} + cancel-in-progress: true + +jobs: + comment: + name: Post Bundle Size Comment + runs-on: ubuntu-latest + # Only act on successful PR runs (the artifact won't exist otherwise). + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' + + permissions: + pull-requests: write + + steps: + - name: Download comment artifact + uses: actions/download-artifact@v4 + with: + name: bundle-analysis-comment + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + path: ./comment-data + + - name: Read PR number + id: pr + run: echo "number=$(cat ./comment-data/pr-number.txt)" >> "$GITHUB_OUTPUT" + + - name: Find existing comment + uses: peter-evans/find-comment@v3 + id: existing-comment + with: + issue-number: ${{ steps.pr.outputs.number }} + comment-author: "github-actions[bot]" + body-includes: "## Bundle Size Analysis" + + - name: Update or create comment + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ steps.existing-comment.outputs.comment-id }} + issue-number: ${{ steps.pr.outputs.number }} + body-path: ./comment-data/comment.md + edit-mode: replace diff --git a/.github/workflows/bundle-analysis.yml b/.github/workflows/bundle-analysis.yml index 6256d8b6f..6b386a139 100644 --- a/.github/workflows/bundle-analysis.yml +++ b/.github/workflows/bundle-analysis.yml @@ -16,9 +16,12 @@ jobs: name: Bundle Size Analysis runs-on: ubuntu-latest + # No write permissions needed here: this job runs untrusted PR code (build + + # analyze) and only produces an artifact. The comment is posted by the + # separate `bundle-analysis-comment.yml` workflow, which runs in the base-repo + # context and gets a write token. This is what makes fork PRs work securely. permissions: contents: read - pull-requests: write steps: - uses: actions/checkout@v4 @@ -76,18 +79,18 @@ jobs: /tmp/bundle-analysis/pr-current.json \ /tmp/bundle-analysis/target-baseline.json - - name: Find existing comment - uses: peter-evans/find-comment@v3 - id: existing-comment - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: "github-actions[bot]" - body-includes: "## Bundle Size Analysis" + - name: Save PR number + run: echo "${{ github.event.pull_request.number }}" > /tmp/bundle-analysis/pr-number.txt - - name: Update or create comment - uses: peter-evans/create-or-update-comment@v4 + # The comment markdown + PR number are handed off to the + # `bundle-analysis-comment.yml` workflow, which posts the comment with a + # write token. We can't post here because fork PRs only get a read-only token. + - name: Upload comment artifact + uses: actions/upload-artifact@v4 with: - comment-id: ${{ steps.existing-comment.outputs.comment-id }} - issue-number: ${{ github.event.pull_request.number }} - body-path: /tmp/bundle-analysis/comment.md - edit-mode: replace + name: bundle-analysis-comment + path: | + /tmp/bundle-analysis/comment.md + /tmp/bundle-analysis/pr-number.txt + if-no-files-found: error + retention-days: 1