Skip to content

The deploy pipeline has no verification layer — it does not wait for CI, never checks the site, and fails silently #269

Description

@os-project-manager

Filed by the repo:objectos seat (objectstack#9831) 2026-09-04T13:20Z, on maintainer instruction (「同意,先修ci」) after the outage recorded on #261. This is the card the lane freeze is waiting on.

The four defects, all in the same layer

CI in this repo is heavy — build, Node floor (17+24+18 cases), check-locale-surface, check-translations, check-translation-output (29 rules), check-translation-ownership, gen-zh-hant --check (73 files), half-states self-test (1551 cases). None of it ever touches the website.

  1. deploy-docs.yml does not wait for CI. No needs:, no workflow_run — it hangs off push: branches: [main] exactly as ci.yml does, so the two run in parallel. A commit that fails build still deploys.
  2. What deploys is never what was tested. The deploy job does its own pnpm install and its own pnpm run deploy (opennextjs-cloudflare build && … deploy). CI builds, throws it away; the deploy builds a second time and publishes that. The published artifact is unverified by construction.
  3. Nothing checks the site after deploying. On 2026-09-04 a deploy succeeded, the site broke, and the maintainer found it — no check anywhere would have.
  4. A failed deploy is silent. 36 consecutive red runs (2026-08-25 → 09-04) across two PM tenures produced no card, no alert, nothing. A red run nobody reads is not a signal.

Shape of the fix (design agreed with the maintainer; details are the dev's)

PR  ── CI (existing gates)
main ── CI passes ──→ deploy ──→ smoke-check the LIVE site
                        │            └─ fails → roll back + file an issue
                        └─ fails → file an issue
  • Gate the deploy on CI. Preferred: move the deploy into ci.yml as a job with needs: on the existing jobs and if: restricted to a push on main. A workflow_run trigger also works but is easy to get subtly wrong (it fires on failure too, and the conclusion must be checked explicitly).
  • Ideally build once and deploy the artifact CI tested (upload/download artifact). If that turns out to be disproportionate, say so with the reason and keep the needs: gating — a measured "not worth it" is a fine outcome, an unexplained skip is not.
  • Smoke-check the live site after deploying. At minimum /, /en/docs, and one deep page. ⚠️ A 200 is not enough — a page that renders to an empty shell still returns 200. Assert something structural (an <h1>, expected body text).
  • On smoke failure, roll back. rollback-docs.yml (ci(docs): add a manual Cloudflare rollback workflow #267) already does the Cloudflare-side rollback and needs no extra credentials; reuse it rather than reimplementing.
  • On any deploy failure, file or update a GitHub issue. This lane reads the board every round; a card is a signal, a red run is not. One card that gets updated, not a new one per failure.

⚠️ Verification requirements — this lane's own rules apply to the checks themselves

  • The smoke check must be demonstrated able to fail. Point it at a path that does not render and show it going red. A check that cannot fail is indistinguishable from one that passed, and this repo has been bitten by that three times in one day.
  • Make it independently runnable (workflow_dispatch, or a script CI calls). Right now deploys are rejected, so a smoke step wired only after a successful deploy can never execute — you must be able to exercise it against the currently-live site to prove it works at all.
  • Do not use the deploy's own exit code as evidence of anything. The failure mode this whole card exists for is that "rejected" and "succeeded" look identical from outside the step. Assert on a new version id where you can.

Why now is the safe window

main currently builds a Worker over Cloudflare's 64 MiB limit, so every deploy is rejected and cannot displace the serving version (69c79ee3-…, 2026-08-25). Nothing you do here can break the live site. Once #261's size fix re-lands that stops being true — which is why this lands first.

⚠️ Merging anything that touches deploy-docs.yml triggers a deploy, and that deploy will fail. Expected, harmless, and worth stating in the PR body so nobody reads it as a regression.

Re-check

git show origin/main:.github/workflows/deploy-docs.yml   # no needs:, no workflow_run
git show origin/main:.github/workflows/ci.yml | head -10 # same push trigger
gh run list --workflow=deploy-docs.yml --branch=main --limit=5

Related: #261 (the outage), #262 (the bundle budget — deliberately a separate card), #265 (pre-merge rendering verification), #266 (the human gate), #267 (rollback tooling), objectstack#15364.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions