deploy-gate
Run the full local deploy gate — type check, all unit tests, static build, SEO validation, plus the CI-only bundle/logo/worker checks — after EVERY code, data, style, or config change, before saying the change is done, showing before/after screenshots, or asking to ship. Use it whenever you finish editing anything under client/, server/, shared/, scripts/, cloudflare/, data/, content/, or package/config files, even for a one-line change.
- Source file
.claude/skills/deploy-gate/SKILL.md
Deploy gate after every change
The owner wants every change checked the way the deploy will check it, so a push never fails in CI. Run this after each change, not only before shipping.
Run it
npx tsx scripts/gate.ts # gates the current change
npx tsx scripts/gate.ts --full # forces every step (ship-to-production uses this)
scripts/gate.ts mirrors .github/workflows/deploy-cloudflare.yml and runs
three lanes in parallel (about 80 s):
| Lane | Steps |
|---|---|
| typecheck | pnpm check |
| tests | npx vitest run (all of them) |
| build | logo assets → Vite build → generate-static.ts → validate-public-seo-build.mjs → bundle privacy → bundle budget → worker esbuild |
It finds Pillow on PATH or installs it once into
node_modules/.cache/gate-venv, writes each step's log to
node_modules/.cache/gate-logs/, prints a ✓/✗ line per step and the last 40
lines of anything that failed, and exits 1 on failure.
Be smart about it
- Scope is automatic. The change is everything that differs from
origin/main(unpushed commits, edits, untracked files). If all of it is docs, skills, or agent config (*.md,.claude/,docs/), the script reports "Nothing to gate" and exits 0. Anything else gets the full gate. - While iterating on a failure, rerun only the step that failed (its
command is in the table above, or
npx vitest run <file>/npx vitest related <changed files>for tests), then run the whole gate once more before calling the change done. - Fix, don't report around it. When a step fails, read the log, fix the
cause, and rerun. If the failure is not from this change (e.g. it also fails
on a clean
origin/main, or comes from another session's uncommitted files), say so plainly with the log tail and don't hide it. - Shared checkout. Other sessions use this folder. The build lane rewrites
dist/cloudflare, which a runningwrangler pages devserves, so don't run two gates at once, and rebuild before takingui-before-afterscreenshots from the static build. - Run the gate before
ui-before-afterscreenshots and before asking to ship. When reporting, give one line:Gate passed (80s): types, 420 tests, 762 routes validated— or the failing step and why.