GitShow/vercel/wait-for-deployment-action
vercel

wait-for-deployment-action

GitHub Action that waits for a Vercel deployment to be ready in CI by polling GitHub's Deployments API.

by vercel
Star on GitHubForknpm

TypeScript

5 stars1 forks1 contributorActive · 1w agoSince 2026MIT

Meet the team

See all 1 on GitHub →
TooTallNate
TooTallNate5 contributions

Languages

View on GitHub →
TypeScript100%

Commit activity

Last 12 weeks · 5 commits

Full graph →

Community health

2 of 6 standards met

Community profile →
62
✓README✓License○Contributing○Code of Conduct○Issue Template○PR Template

Recent PRs & issues

Active · 2 in progress · Last activity 1w ago
See all on GitHub →
pranaygp
fix: resolve deployment-id from the same deployment as deployment-url, verify environmentOpenPR

The incident On 2026-07-30, CI called this action with , , for commit . It emitted: A mismatched pair. had been force-pushed to exactly 's HEAD, so Vercel built that one commit twice — production from , a preview from the branch. Downstream, workflow runs were enqueued against the preview deployment while attributed to the production environment, forking runs across environments. Why the two outputs can disagree The two things Vercel's GitHub integration publishes have different granularity: The action took the URL from the first and the ID from the second. The commit status is overwritten by whichever deployment of the SHA finishes last, so any commit deployed to multiple environments can pair a URL and an ID from different deployments. Verified on the incident data — one status for the SHA, 20:41:18, naming the preview, while the production deployment had finished at 20:40:28: Because the GitHub Deployment's is empty, GitHub-only data cannot produce an ID that is consistent with the URL. Resolving it needs Vercel. The fix Two parts, and the tokenless one is the default and recommended path: without any credentials, the action now detects the ambiguity and reports it at a severity that tracks whether it is live (details below). That check alone would have surfaced this incident immediately. This action is deliberately designed not to require a Vercel token, and the incident's root cause is being removed at the source in vercel/workflow#3243 (no more same-SHA deployments), so most consumers — including CI — should stay tokenless. For consumers who already hold a Vercel access token for other reasons, (+ ) is an optional escape hatch. When set, the ID is resolved by looking the URL's host up against , which accepts a deployment host in place of an ID. The ID and the URL then describe the same deployment by construction, and the returned is checked against . The first commit here is @NathanColosimo's from #5, which introduced that lookup. This PR adds the guard that turns the original silent failure into a loud one, plus the error paths: Environment verification. Fails when the resolved deployment isn't in the requested environment. The API spells preview as (the enum is , no ), so the production side is exact and the preview side only requires "not production" — and custom environments keep working. Skipped when is overridden, since no Vercel target can be derived from a hand-written name. A mismatch is fatal even under , because it means isn't the environment that was asked for either — not just the ID. No fallback to the commit status when the Vercel lookup fails. Falling back would silently restore the mismatched pair. Actionable errors. A team-owned deployment answers , not , when the request isn't scoped to its team — the likeliest misconfiguration. An unscoped 404 now points at ; 401/403 points at the token. The token never appears in an error message (covered by a test). Credentials are read from the inputs only* — deliberately no ambient / env fallback. A token switches resolution modes, and is a common job-level env var in Vercel-adjacent CI; switching modes should be a visible choice at the call site ( if that is what you want). Without a token — the default Unchanged resolution, so no existing workflow breaks. There's no cheap way to correct* the ID without Vercel — it simply isn't in GitHub's environment-scoped data — so the action reports the hazard instead, at a severity that tracks whether it's actually live. The status is only ambiguous when the commit spans environments, which costs one extra GitHub call to check (list deployments for the SHA in the counterpart environment) and never fails the run: The durable fix for the warning is upstream, not a token: stop deploying one commit to two environments of the same project (usually two branches pointing at the same SHA). The ambiguity advice in the log now leads with that. Backward compatibility No behavior change for callers that pass no token: same resolution, same outputs, plus an annotation when the commit really is ambiguous. New inputs default to empty, and ambient / env vars are ignored — a job that happens to carry them cannot switch resolution modes (or start 404ing on an unscoped team lookup) on a pin bump. The only new failure mode is behind , and it fires exactly where the old code would have emitted a wrong ID. One tightening worth flagging: an environment mismatch ignores . That's deliberate (the URL is suspect too), and documented in and the README. Also corrected while here (pre-existing, from the initial commit): documented as the way to "skip deployment-id resolution entirely". It never did — it downgrades a failed resolution to a warning, and the lookup still runs and still emits an ID. Adding a real skip switch would silently drop the output for anyone reading it opportunistically, so the docs and the startup log now say what actually happens. Verification , , (75 tests, up from 39), . rebuilt on Node 24, byte-identical to a Node 22 build. New drives against a fixture reproducing the incident — a SHA deployed to both environments, whose commit status names the preview — and asserts the production URL yields the production ID, that the commit status isn't consulted on the token path, and that a mismatch fails. I also replayed the real recorded API responses for both incident deployments through the resolution path and confirmed the production host yields while the ID the action actually emitted is rejected for . Endpoint behavior confirmed live against the incident's project rather than assumed: hosts resolve, is for the preview and for the production deployment, and an unscoped request 404s. Vercel sets to the unique deployment host for both environments, so this resolution is exact rather than alias-dependent. Follow-up Per review, stays an optional escape hatch and will not be wired into CI: vercel/workflow#3243 removes the same-SHA ambiguity at the source there, so the tokenless path with the ambiguity check is sufficient. If an authoritative, guaranteed-consistent resolution is ever wanted without static secrets, the direction is OIDC-based auth to the Vercel API — future work, not this PR. #5 can be closed in favor of this PR — its commit is included here. 🤖 Generated with Claude Code

pranaygp · 1w ago
NathanColosimo
fix: resolve deployment ID from the matching deployment statusOpenPR

Summary and previously came from GitHub records with different environment scope, so one commit deployed more than once could produce a mismatched pair. Read the app URL from and the deployment ID from the same status's Vercel dashboard . Do not fall back to the shared commit status; a missing or malformed deployment-status field now fails clearly instead of returning an unverified ID. Validation

NathanColosimo · 1w ago

Recent fixes

View closed PRs →
TooTallNate
fix(config): drop broken explicit-empty status-context opt-outMergedPR

⚠️ Draft — do not merge until consumer CI verifies This PR fixes the broken heuristic that disabled deployment-id resolution for every consumer. Holding open until:* [ ] vercel/workflow-server#427 CI passes the E2E flow with this SHA [ ] vercel/workflow#2065 CI passes the E2E flow with this SHA Bug checked whether was set in the env, intending to distinguish: not passed → auto-compose default passed as empty* → opt out of deployment-id resolution But GitHub Actions always injects env vars for every input declared in , using the value when the consumer doesn't pass it. With , is always set to . So every consumer hits the 'opt-out' branch and gets empty . Reproduced in vercel/workflow E2E: Fix Drop the heuristic and the explicit-empty opt-out semantics. New override behavior is plain: empty → auto-compose from ; non-empty → use as-is. Consumers that don't want deployment-id resolution should set and ignore the output. Also updates action.yml input description and tests.

TooTallNate · 2mo ago
TooTallNate
fix(action.yml): remove literal ${{ github.token }} from input descriptionMergedPR

Summary The GitHub Actions runner evaluates expressions inside input descriptions too, not just in values. Pinning to 92eb2be / 170090a in vercel/workflow-server CI gave: Fix Reword the description to plain prose. The line still uses the expression form (which is valid there), so behavior is unchanged for consumers that omit .

TooTallNate · 2mo ago
TooTallNate
fix(action.yml): use double quotes for description containing apostropheMergedPR

Summary The previous value was shell-escaped () rather than YAML-escaped, leaving a literal backslash-and-quote in the YAML. The GitHub Actions runner fails to parse the action at all: This blocked every consumer of the action — I caught it via the workflow-server CI run after pinning to the post-merge SHA. Fix Switch to a double-quoted YAML scalar so the apostrophe in needs no escaping. Drop the trailing "instead of the Vercel API" while I'm in here — that's a why-this-exists detail, not a what-it-does one, and it already appears in the README.

TooTallNate · 2mo ago
Structured data for AI agents

Repository: vercel/wait-for-deployment-action. Description: GitHub Action that waits for a Vercel deployment to be ready in CI by polling GitHub's Deployments API. Stars: 5, Forks: 1. Primary language: TypeScript. Languages: TypeScript (100%). License: MIT. Open PRs: 2, open issues: 0. Last activity: 1w ago. Community health: 62%. Top contributors: TooTallNate.

·@ofershap

Replace github.com with gitshow.dev