fix(ci): pass the Sentry token as a secret-file, not a literal string #143
No reviewers
Labels
No labels
dependencies
major
security-pin
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
trails-cool/trails!143
Loading…
Reference in a new issue
No description provided.
Delete branch "fix-sentry-secret-files"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes the 401 in #5. The token was never wrong.
Root cause
docker/build-push-actionhas two different inputs:secrets:— takes literal values (MY_TOKEN=abc123)secret-files:— takes paths (MY_TOKEN=./token.txt)Both CD workflows used the first with a path:
So the build received the 17-character string
/tmp/sentry_tokenas the token. The Dockerfilecats it back out of/run/secrets/,sentry-clisends it as the credential, and Sentry answersInvalid token (http status: 401)— correctly. The decrypted token never entered the build.The build log shows the signature:
That
srcis an action-generated temp file holding the literal value. Withsecret-files:,srcpoints at/tmp/sentry_tokenitself.Why this took three theories to find
The 401 is indistinguishable from a bad credential, so every hypothesis was about the credential. Each was eliminated by measurement:
de.sentry.io; the 401 did not changegrepconcatenating two keyssecrets.app.envmatchessentry.ioandde.sentry.io; the stored value is a well-formed 71 characters with no quotesWith the credential proven good and the 401 still happening, the only place left was the transport.
Changes
secrets:→secret-files:incd-apps.ymlandcd-staging.yml, with a comment recording the distinction.vite.config.tsfiles. That PR claimed the region was the cause. It was not, and the next reader should not believe it. Theurlpin itself stays — our org is in the EU, the pin is harmless, and it is now labelled as defensive rather than curative.Verification
pnpm typecheck,pnpm lintandpnpm testpass. Both workflow files parse, and thewith:block resolves tosecret-fileswithsecretsabsent.I did not run
pnpm test:e2elocally — it needs the full Docker stack, and nothing here can reach it. CI runs it.The real check is this PR's own staging build:
cd-stagingruns the PR branch's workflow file, so the preview build exercises the fix. A build log with noInvalid tokenline, and a release appearing in Sentry for the preview SHA, confirms it. I will watch the run and report.Still open in #5
A failed upload still does not fail the build — run 1459 finished green with two 401s in its log. That follow-up keeps #5 open, and it is what stops this class of silent rot.
🤖 Generated with Claude Code
`docker/build-push-action`'s `secrets:` input takes literal VALUES; `secret-files:` takes PATHS. Both CD workflows used `secrets:` with a path: secrets: | SENTRY_AUTH_TOKEN=/tmp/sentry_token So the build received the 17-character string "/tmp/sentry_token" as the token itself. The Dockerfile cat'd it back out, sentry-cli sent it as the credential, and Sentry answered `Invalid token (http status: 401)` — correctly. The real token never reached the build. This accounts for every observation in #5 at once: a token that returns 200 against both sentry.io and de.sentry.io, a well-formed 71-char value in secrets.app.env, a clean grep/cut extraction, and a 401 that no rotation and no region setting could have fixed. It has been broken since this plumbing was written, which is why there was never a working upload to compare with. Also corrects the comment #140 left behind: the EU region pin is defensive, not the fix. Refs #5 — the issue stays open for its follow-up: a failed upload must fail the build, so this cannot rot silently again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>