From 6ebca8fa6cca6af0d11cfca0508d8a893ee93899 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 22 Apr 2026 11:14:06 +0000 Subject: [PATCH 1/3] ci: unblock fork PRs with SENTRY_CLIENT_ID fallback + fork-safe checkout - build-binary/build-npm: fall back to a dummy SENTRY_CLIENT_ID when vars.SENTRY_CLIENT_ID isn't available (fork PRs). The resulting binary is only smoke-tested (--help) and never shipped, so any non-empty value works; tests already tolerate the dummy via test/preload.ts. - check-generated: fork PRs leave `ref` empty so checkout uses GITHUB_REF (PR merge SHA) instead of requesting a branch that only exists on the fork. Same-repo PRs still check out the branch head so auto-commit can push back. Fixes the three failures on PR #806. --- .github/workflows/ci.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f230fd50..d3a438131 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,7 +112,11 @@ jobs: - uses: actions/checkout@v6 with: token: ${{ steps.token.outputs.token || github.token }} - ref: ${{ github.head_ref || github.ref_name }} + # Same-repo PRs (token step succeeded): check out the branch head so + # the auto-commit step can push regenerated docs back. Fork PRs leave + # `ref` empty so checkout defaults to GITHUB_REF (the pull_request + # merge SHA, always fetchable from the base repo with github.token). + ref: ${{ steps.token.outcome == 'success' && (github.head_ref || github.ref_name) || '' }} - uses: oven-sh/setup-bun@v2 - uses: actions/cache@v5 id: cache @@ -257,7 +261,10 @@ jobs: mv package.json.tmp package.json - name: Build env: - SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} + # Fork PRs can't read repo vars (getsentry org policy); fall back to + # a dummy. The resulting binary is only smoke-tested (`--help`) and + # never shipped, so any non-empty value works. + SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID || 'ci-fork-pr-dummy' }} # Sourcemap upload to Sentry (non-fatal, skipped when token is absent) SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} # Set on main/release branches so build.ts runs binpunch + creates .gz @@ -670,7 +677,10 @@ jobs: run: bun install --frozen-lockfile - name: Bundle env: - SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} + # Fork PRs can't read repo vars (getsentry org policy); fall back to + # a dummy. The resulting bundle is only smoke-tested (`--help`) and + # never shipped, so any non-empty value works. + SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID || 'ci-fork-pr-dummy' }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} run: bun run bundle - name: Smoke test (Node.js) From 343bff7145a6ab705ec500e92bf2d24793cd698b Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 22 Apr 2026 11:17:57 +0000 Subject: [PATCH 2/3] ci: hoist SENTRY_CLIENT_ID and SENTRY_AUTH_TOKEN to workflow-level env Both values are referenced in multiple jobs/steps (build-binary, build-npm, build-docs). Moving them to the workflow-level `env:` block eliminates repetition and keeps the fork-PR fallback in one place. --- .github/workflows/ci.yml | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3a438131..457b30bee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,14 @@ env: # Commit timestamp used for deterministic nightly version strings. # Defined at workflow level so build-binary and publish-nightly always agree. COMMIT_TIMESTAMP: ${{ github.event.head_commit.timestamp }} + # SENTRY_CLIENT_ID is baked into the binary at build time. Fork PRs can't + # read repo vars (getsentry org policy); fall back to a dummy. The resulting + # binary is only smoke-tested (--help) and never shipped, so any non-empty + # value works; tests tolerate the dummy via test/preload.ts. + SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID || 'ci-fork-pr-dummy' }} + # Sourcemap upload to Sentry (non-fatal, skipped when token is absent). + # Empty on fork PRs and non-production branches. + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} jobs: changes: @@ -261,12 +269,6 @@ jobs: mv package.json.tmp package.json - name: Build env: - # Fork PRs can't read repo vars (getsentry org policy); fall back to - # a dummy. The resulting binary is only smoke-tested (`--help`) and - # never shipped, so any non-empty value works. - SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID || 'ci-fork-pr-dummy' }} - # Sourcemap upload to Sentry (non-fatal, skipped when token is absent) - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} # Set on main/release branches so build.ts runs binpunch + creates .gz RELEASE_BUILD: ${{ github.event_name != 'pull_request' && '1' || '' }} run: bun run build --target ${{ matrix.target }} @@ -676,12 +678,6 @@ jobs: - if: steps.cache.outputs.cache-hit != 'true' run: bun install --frozen-lockfile - name: Bundle - env: - # Fork PRs can't read repo vars (getsentry org policy); fall back to - # a dummy. The resulting bundle is only smoke-tested (`--help`) and - # never shipped, so any non-empty value works. - SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID || 'ci-fork-pr-dummy' }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} run: bun run bundle - name: Smoke test (Node.js) run: node dist/bin.cjs --help @@ -737,7 +733,6 @@ jobs: - name: Inject debug IDs and upload sourcemaps if: github.event_name == 'push' && env.SENTRY_AUTH_TOKEN != '' env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_ORG: sentry SENTRY_PROJECT: cli-website run: | From b0b1d2d121c7f10c79495dcd1dda84ad4040ef6f Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 22 Apr 2026 11:28:35 +0000 Subject: [PATCH 3/3] ci: keep SENTRY_AUTH_TOKEN at job/step level (environment-scoped) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cursor Bugbot caught that SENTRY_AUTH_TOKEN is scoped to the production GitHub environment. Workflow-level env is evaluated before a job's environment: is applied, so hoisting it there would resolve the secret against repo-level secrets only — silently breaking sourcemap uploads. - build-binary / build-npm: re-add SENTRY_AUTH_TOKEN at step level. - build-docs: declare at job level so the `if: env.SENTRY_AUTH_TOKEN != ''` guard on the sourcemap-upload step can see it (job-level env is resolved after environment: is applied). SENTRY_CLIENT_ID stays at workflow level since it's a repo-level var, not environment-scoped. --- .github/workflows/ci.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 457b30bee..3e99b3aaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,9 +26,6 @@ env: # binary is only smoke-tested (--help) and never shipped, so any non-empty # value works; tests tolerate the dummy via test/preload.ts. SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID || 'ci-fork-pr-dummy' }} - # Sourcemap upload to Sentry (non-fatal, skipped when token is absent). - # Empty on fork PRs and non-production branches. - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} jobs: changes: @@ -269,6 +266,10 @@ jobs: mv package.json.tmp package.json - name: Build env: + # Environment-scoped (production) — must be set at step level to + # resolve correctly; workflow-level env evaluates before the job's + # environment: is applied. + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} # Set on main/release branches so build.ts runs binpunch + creates .gz RELEASE_BUILD: ${{ github.event_name != 'pull_request' && '1' || '' }} run: bun run build --target ${{ matrix.target }} @@ -678,6 +679,9 @@ jobs: - if: steps.cache.outputs.cache-hit != 'true' run: bun install --frozen-lockfile - name: Bundle + env: + # Environment-scoped (production) — see note in build-binary. + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} run: bun run bundle - name: Smoke test (Node.js) run: node dist/bin.cjs --help @@ -696,6 +700,12 @@ jobs: # SENTRY_AUTH_TOKEN is scoped to the production environment. Needed by # the "Inject debug IDs and upload sourcemaps" step below. environment: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && 'production' || '' }} + # Hoisted to job level (not step) so the `if: env.SENTRY_AUTH_TOKEN != ''` + # guard on the sourcemap-upload step can see it. Job-level env is resolved + # after `environment:` is applied, so the production-scoped secret resolves + # correctly. + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2