From db1ac648ae9fd7e28cebee6999a6f50436d75cfb Mon Sep 17 00:00:00 2001 From: Federico Zarantonello Date: Wed, 20 May 2026 18:12:46 +0200 Subject: [PATCH] fix(ci): inject Sentry debug IDs before upload-artifact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sourcemap deobfuscation wasn't resolving for events emitted from the released bundle. Root cause: getsentry/action-release@v1 (sentry-cli 2.x) uploads as an *artifact bundle*, which Sentry matches against runtime stack frames using debug IDs — not filename + release-files fallback. Our bundle had no debug ID, so the matcher had nothing to match on. Fix: run `sentry-cli sourcemaps inject` against the built bundle in the `build` job *before* upload-artifact. Both downstream jobs download the same artifact: - sentry-release uploads the injected bundle + sourcemap with the debug ID embedded in both; - publish-dist commits the injected JS to dist/ — so the code the consumer actually runs at runtime carries the same debug ID, and the Sentry SDK reports it in stack frames. Doing the inject inside sentry-release alone would NOT fix this: publish-dist downloads its own copy of the (un-injected) artifact, so runtime bundles would still ship without debug IDs. Also sets `inject: false` on the sentry-release action explicitly, so it doesn't re-inject (generating new IDs that wouldn't match what publish-dist published). Verified locally: `sentry-cli sourcemaps inject` adds a `//# debugId=` pragma to the JS and a matching `"debugId"` field to the .map, with the same UUID on both. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 14b3b57..0ee1221 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -131,6 +131,38 @@ jobs: fi echo "OK: RELEASE_TAG baked into $BUNDLE" + # Inject Sentry debug IDs into the bundle + sourcemap so the artifact + # that downstream jobs (sentry-release, publish-dist) consume already + # carries them. The dist branch consumers will run *this* JS at + # runtime, so the debug ID baked here is what Sentry's SDK reports + # in stack frames and what enables source-map deobfuscation against + # the artifact bundle uploaded in the next job. + # + # Why here and not in sentry-release: that job downloads its own + # copy of the artifact, injects in its own workspace, uploads — + # but publish-dist downloads the *un-injected* artifact and pushes + # that to dist/, so runtime bundles would lack debug IDs + # and Sentry would only ever see minified frames. + - name: Install Sentry CLI + run: curl -sL https://sentry.io/get-cli/ | INSTALL_DIR=/usr/local/bin bash + + - name: Inject Sentry debug IDs into bundle + sourcemap + env: + ACTION: ${{ inputs.action }} + run: | + sentry-cli sourcemaps inject "${ACTION}/dist" + # Sanity check: the JS should now carry a debugId pragma, and + # the .map should have a debugId field. Fail fast if not. + if ! grep -F "//# debugId=" "${ACTION}/dist/index.js" > /dev/null; then + echo "ERROR: sentry-cli inject did not add a debugId pragma to ${ACTION}/dist/index.js" + exit 1 + fi + if ! grep -F "\"debugId\":" "${ACTION}/dist/index.js.map" > /dev/null; then + echo "ERROR: sentry-cli inject did not add a debugId to ${ACTION}/dist/index.js.map" + exit 1 + fi + echo "OK: debug IDs injected into ${ACTION}/dist/{index.js,index.js.map}" + - name: Upload bundle artifact uses: actions/upload-artifact@v4 with: @@ -187,9 +219,18 @@ jobs: SENTRY_ORG: buildwithfern SENTRY_PROJECT: automations-actions with: + # Must match the RELEASE_TAG baked into the bundle so source-map + # deobfuscation resolves. Uses `@` (not the git-tag `/` format) + # because Sentry rejects slashes in release identifiers. version: ${{ inputs.action }}@${{ inputs.version }} sourcemaps: ${{ inputs.action }}/dist url_prefix: "~/" + # Debug IDs were injected upstream in the `build` job before + # upload-artifact, so both the artifact this job uploads *and* + # the one publish-dist pushes to the dist branch carry the same + # debug IDs. Re-injecting here would generate new IDs and break + # matching against what the consumer actually runs. + inject: false # --------------------------------------------------------------------------- # Publish to the orphan branch dist/ and tag the commit.