fix(vercel-ignore): same-commit redeploy is always skipped, so env var changes cannot reach production
Summary
An environment variable added or rotated in Vercel cannot reach production on main by redeploying, because scripts/vercel-ignore.sh cancels every same-commit redeploy. The standard recovery for a credential change — "set the value, then redeploy" — silently does nothing.
This extended the #8208 outage. Checkout, customer-portal and notification-channels stayed down for ~45 minutes after the correct secret was in Vercel, across two redeploy attempts.
Reproduction
- Set or rotate any env var in Vercel production.
- Redeploy the current
maincommit (dashboard Redeploy, orvercel --prod). - The deployment is canceled after ~7s and production keeps serving the old build, which does not have the value.
Running "bash scripts/vercel-ignore.sh"
Skipping: no web-relevant changes on main
The deployment was canceled because the Ignored Build Step command returned exit code 0.
Observed on deployments worldmonitor-5z2wvbamw (02:29Z) and worldmonitor-jofyfh6f2 (02:51Z) on 2026-09-16.
Cause
scripts/vercel-ignore.sh:6-20 decides on a path diff:
WEB_CHANGES=$(git diff --name-only "$VERCEL_GIT_PREVIOUS_SHA" HEAD -- 'src/' 'api/' ...)
[ -z "$WEB_CHANGES" ] && echo "Skipping: no web-relevant changes on main" && exit 0
On a same-commit redeploy VERCEL_GIT_PREVIOUS_SHA is HEAD, so the diff is necessarily empty and the skip is unconditional. The check is correct for its actual purpose (don't rebuild for a docs-only merge) — it just has no notion of "the build inputs changed even though the code did not".
Two things make it expensive to diagnose:
- The deployment reports as
Canceled, which reads like a transient infra failure rather than a deliberate skip. Nothing distinguishes it from a real cancellation invercel ls. - Vercel binds env vars at build time, so the symptom is a config-missing branch (
api/create-checkout.ts:164→ 503) in code that looks correctly written.
Proposed fix
Options, roughly in order of preference:
- Escape hatch in the script. Honour an explicit override so a redeploy can force a build — e.g. build unconditionally when
VERCEL_GIT_PREVIOUS_SHA == HEAD(a same-commit redeploy is by definition a deliberate manual action, never a merge-train event). This makes the dashboard button work as everyone expects. - Document the real procedure in
docs/relay-credentials.mdand anywhere else that says "set the variable and redeploy": the working command isvercel --prod --force --scope eliewm(--forcebypasses the Ignored Build Step). - Make the skip legible — the current message says why it skipped but not that env changes will not land.
(1) and (2) are not exclusive; (2) is worth doing regardless since it is the recovery path under incident pressure.
Diagnostic worth keeping
Variable newer than the newest READY production build ⇒ production does not have it:
vercel env ls production --scope eliewm --project worldmonitor # prints each var's age
vercel ls worldmonitor --scope eliewm --prod # prints each deployment's age + status
Credential-free liveness probe for the gateway env (returns misconfigured if any required var is missing in the serving build, invalid_state if all are present):
curl -A "worldmonitor-ops-diagnostic/1.0" \
"https://www.worldmonitor.app/api/discord/oauth/callback?code=probe&state=nonexistent"
Note the project lives under the eliewm team and the repo has no .vercel/ link, so both CLI commands need explicit --scope/--project.
Context: #8208, and the validation comment https://github.com/koala73/worldmonitor/issues/8208#issuecomment-5691556926
Source: koala73/worldmonitor