Skip to content

Make the production deploy manual only - #97

Closed
davidtaing wants to merge 1 commit into
mainfrom
ci/manual-deploy
Closed

Make the production deploy manual only#97
davidtaing wants to merge 1 commit into
mainfrom
ci/manual-deploy

Conversation

@davidtaing

Copy link
Copy Markdown
Collaborator

Summary

Deploying to production is now a deliberate act rather than a consequence of merging. Vercel Deploy loses its workflow_run: [CI] trigger and keeps workflow_dispatch as the only way in, so landing on main ships nothing until someone runs the workflow — gh workflow run "Vercel Deploy" --ref main, or the Run workflow button.

Landing on main says the code is good; deploying says now is the moment to ship it. Firing on CI success fused the two and made every merge a release, which left disabling the workflow by hand as the only brake. That is worse than it sounds: a push received while a workflow is off creates no run at all rather than a queued one, so re-enabling it afterwards leaves main ahead of production with nothing to re-run and no way back except an empty commit. It happened on 15 August 2026 when the #63#66 stack merged, and workflow_dispatch was added then precisely to reconcile the two. This makes the brake the absence of a click instead of a repository setting nothing in the tree records.

The gate that has to be rebuilt

workflow_run was doing a second job: a red commit could not ship because no run was created for one. A dispatch has no such interlock, so the job's first step asserts it directly — read the CI run for the dispatched commit and refuse anything that did not conclude success, or that has no run at all.

Deliberately with no bypass input. A commit whose CI is red is one to fix, not one to ship past a toggle, and a second state on this check is exactly the accumulation AGENTS.md warns about. It needs actions: read alongside contents: read, which is why the permissions block now names two scopes.

Smaller consequences

  • The job condition still pins the ref to main. This matters more now that dispatch is the only trigger: every step passes --prod, so any branch chosen in the dropdown would otherwise go to production.
  • The checkout drops its explicit ref. Its only purpose was pinning workflow_run.head_sha against a second merge landing mid-run; a dispatch checks out what it was dispatched against, which is the commit the gate just checked.

Related issue

None — this was not cut as a ticket.

Checklist

  • Opened as a draft pull request
  • pnpm lint — not applicable; the diff is one workflow file and Markdown prose, and the worktree has no node_modules
  • pnpm test:e2e — not applicable, same reason
  • Commit messages have no Co-Authored-By, Generated with, or tool-attribution trailers
  • Linked the closing issue — there is none

What was verified

The YAML parses, the gate script passes bash -n, and the gh run list query was run against this repository for real: it returns success for main's tip (3be37ca) and empty — so the step fails — for a SHA with no run.

After merge

The workflow file is read from the default branch, so this only takes effect once it is on main. Vercel Deploy is currently disabled_manually; re-enabling it (gh workflow enable "Vercel Deploy") is safe once this lands, since enabling no longer means merges start shipping. That is the director's call, not this PR's.

The Vercel Deploy workflow fired on a successful CI run on `main`, which fused
two decisions that are not the same one: landing says the code is good, shipping
says now is the moment. Fusing them made every merge a release, and left
disabling the workflow by hand as the only brake — which is worse than it
sounds, because a push received while a workflow is off creates no run at all,
so re-enabling it leaves `main` ahead of production with nothing to re-run.

`workflow_dispatch` was already there for exactly that reconciliation case. This
removes the `workflow_run` trigger and leaves dispatch as the only way in, so the
brake is the absence of a click rather than a repository setting nothing in the
tree records.

The `workflow_run` trigger was also the CI gate — a red commit could not ship
because no run existed for one. A dispatch has no such interlock, so the job's
first step asserts it directly: read the CI run for the dispatched commit and
refuse anything that did not conclude `success`. Deliberately with no bypass
input, since a commit whose CI is red is one to fix rather than one to ship past
a toggle. That needs `actions: read` alongside `contents: read`.

The job condition still pins the ref to `main`, which matters more now that
dispatch is the only trigger: every step passes `--prod`, so any branch chosen in
the dropdown would otherwise go to production. The checkout no longer needs an
explicit `ref` — a dispatch checks out what it was dispatched against, which is
the same commit the gate just checked.
@davidtaing

Copy link
Copy Markdown
Collaborator Author

Closing: this was a misread. workflow_dispatch was already on the workflow — manual triggering on top of the merge-to-main deploy is what main does today, so there was nothing to add. This PR removed the automatic trigger, which is the opposite of what was wanted.

@davidtaing davidtaing closed this Aug 20, 2026
@davidtaing
davidtaing deleted the ci/manual-deploy branch August 20, 2026 20:03
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.

1 participant