Skip to content

ci: gate the CDN purge on the real Railway deployment status - #1193

Draft
vivek7405 wants to merge 2 commits into
mainfrom
ci/purge-gate-on-railway-status
Draft

ci: gate the CDN purge on the real Railway deployment status#1193
vivek7405 wants to merge 2 commits into
mainfrom
ci/purge-gate-on-railway-status

Conversation

@vivek7405

Copy link
Copy Markdown
Collaborator

Summary

The purge workflow from #1189 inferred the deploy from the origin's /__webjs/version uptime, assuming every push to main produces a Railway deploy. It doesn't. Railway marked #1189's own merge commit SKIPPED (it touched only .github and a .md), so no restart happened, the wait burned its full 15 minutes, and the job failed. Left as-is it red-Xes every docs-only and CI-only commit.

Now it asks Railway directly. The GraphQL API returns per-deployment status plus meta.commitHash, so the job resolves the deployment for github.sha and branches on the real status:

Status Action
SUCCESS purge
SKIPPED no purge, notice, exit 0 (was a hard failure)
FAILED / CRASHED / REMOVED no purge, warning, exit 0
in progress / no record yet keep polling
nothing terminal in 15 min no purge, warning, run stays green

Why a separate workflow, not release.yml

release.yml fires only on pushes touching changelog/** (an npm package release). None of the four website merges on 2026-07-30 touched changelog/, so a purge living there would have fired for none of them, including the SVG mask fix that is still stale at the edge.

Test plan

  • YAML parses; all three run blocks pass bash -n
  • Extraction + branching exercised against the real response shape for both known commits: 93883bbc resolves to SKIPPED (the commit that broke v1, now a clean no-op) and 086b3c75 to SUCCESS
  • Every terminal and non-terminal status verified to take the intended branch
  • set -e guard verified: a non-JSON body (Cloudflare's error code: 1010 page) does not abort the step
  • framework-dev.md updated: heuristic description replaced, RAILWAY_TOKEN documented with token type and header, repository-vs-environment secret gotcha called out
  • End-to-end on a real merge, verifiable only once this is on main

Notes

  • Railway sits behind Cloudflare, which returns error code: 1010 to automated-looking user agents (python urllib is blocked outright, curl is fine).
  • A GraphQL error arrives with HTTP 200 and an errors array, so the status code alone proves nothing; the check asserts .errors == null.
  • Project tokens use Project-Access-Token, account tokens use Authorization: Bearer. Which applies depends on the token created, so both are tried.

Closes #1192

The first version inferred the deploy by watching the origin's
/__webjs/version uptime for a restart, on the assumption that every push
to main produces a Railway deploy. It does not. Railway marked #1189's
own merge commit SKIPPED (it touched only .github and a .md), so no
restart ever happened, the wait ran its full 15 minute budget, and the
job failed. Left alone it would red-X every docs-only and CI-only
commit, and a job that cries wolf on routine commits stops being read.

Ask Railway instead of guessing. Its GraphQL API returns, per
deployment, both a status and the originating meta.commitHash, so the
job now resolves the deployment for github.sha and branches on the real
status: SUCCESS purges, SKIPPED exits 0 with a notice (nothing was
deployed, so nothing is stale), FAILED / CRASHED / REMOVED exit 0 with a
warning (no new content reached the origin), anything in progress keeps
polling. An unresolved deployment now warns and leaves the run GREEN
rather than failing, which is the whole point.

The purge and verify steps become conditional on that outcome, and
workflow_dispatch still purges immediately with no wait.

Two API details worth keeping: Railway sits behind Cloudflare, which
answers `error code: 1010` to automated-looking user agents (python
urllib is blocked outright, curl is fine), and a GraphQL error arrives
with HTTP 200 plus an `errors` array, so the status code alone proves
nothing. Token type is not knowable ahead of time either, since a
project token uses Project-Access-Token and an account token uses
Authorization: Bearer, so both are tried.

Verified by exercising the extraction and branching against the real
response shape for both known commits: 93883bb resolves to SKIPPED (the
commit that broke the previous version, now a clean no-op) and 086b3c7
to SUCCESS.

Closes #1192
Review of the new gating step found two defects of the same class: both
turned a misconfiguration into a GREEN run that silently never purges,
which is precisely the failure the workflow exists to catch.

1. `meta` may arrive as an object or as a JSON-encoded string, and this
   was not verifiable against the live API beforehand. Indexing a string
   with `.commitHash` is a jq ERROR rather than a null, so the unguarded
   filter would have swallowed every response, polled to the deadline and
   reported green without ever purging. Normalize both shapes, and leave
   a null `meta` resolving to empty so it keeps polling instead of
   crashing.

2. A wrong, expired, or mis-scoped RAILWAY_TOKEN produced an auth error
   on every poll, which read as "no deployment yet" and ended in the same
   green no-op. Track whether ANY clean response ever arrived: none means
   the credential or endpoint is wrong, so exit 1 and print the server's
   own error body (never the token). "Answered fine but the sha never
   reached a terminal status" stays a warning and stays green, which is
   the case #1192 was about.

Also dump the deployments actually seen on the timeout path, so a
field-name or response-shape mismatch is diagnosable in the log instead
of looking identical to "the deploy never happened".

Verified: object, string, and null `meta` all resolve without a jq crash,
and the bad-token path exits 1 carrying the API's message.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: gate the CDN purge on the real Railway deployment status

1 participant