A domestic cat named Emmy lying on a PC keyboard

Wrangler deploy dry-run in CI before merging to main


I have merged PRs where npm run build passed and production still broke five minutes later. Astro finished, TypeScript looked fine, and then Wrangler complained about a missing asset binding or a worker bundle that no longer matched wrangler.json.

That gap is why I treat wrangler deploy --dry-run as part of CI—not as a deploy step, but as a final packaging check before anything hits main.

What a dry-run actually validates

astro build proves the site compiles. wrangler deploy --dry-run proves Wrangler can assemble and upload the Worker bundle without touching production.

On this repo, a successful dry-run prints something like:

Total Upload: 611 KiB / gzip: 151 KiB
Your Worker has access to the following bindings:
Binding            Resource
env.SESSION        KV Namespace
env.ASSETS         Assets

--dry-run: exiting now.

That short output is doing real work. It catches problems I have actually hit:

  • main or assets.directory points at the wrong path after a refactor
  • Missing or renamed bindings in wrangler.json
  • Worker bundle size regressions from a new dependency or accidental server import
  • Invalid Wrangler config that only surfaces at deploy time

Dry-run does not replace an end-to-end production test. It will not prove Turnstile, Resend, or dashboard secrets are set. It will not send mail or verify DNS. It just keeps the deploy path honest before merge.

The one script I run locally and in CI

This site already wires the full gate into package.json:

"check": "npm run blog:check-heroes && astro build && tsc && wrangler deploy --dry-run"

That order matters to me:

  1. blog:check-heroes — fast content guardrails when posts change
  2. astro build — produces dist/ and the Worker entry Wrangler expects
  3. tsc — catches type errors the build might not surface the same way
  4. wrangler deploy --dry-run — validates the Cloudflare packaging step

Locally and in CI, I run the same command:

npm run check

On mayfield.io, GitHub Actions mirrors that:

  • Site build (every push/PR to main) — npm ci + npm run check with NASA_API_KEY (heroes, astro build, tsc, wrangler deploy --dry-run)
  • Blog PR checksnpm run blog:check-heroes only when src/content/blog/** changes (fast duplicate-hero signal without waiting for a full build)

Dry-run does not need Cloudflare deploy credentials; Wrangler validates the bundle locally and exits before upload. Production deploy stays manual on main.

The workflow lives in .github/workflows/site-build.yml:

- name: Check (heroes, build, tsc, wrangler dry-run)
  env:
    NASA_API_KEY: ${{ secrets.NASA_API_KEY }}
  run: npm run check

What I still check outside CI

Dry-run will not save you from missing production secrets. Before I ship anything that touches /api/contact or other server routes, I still walk the human checklist:

  • required secrets exist in the Cloudflare dashboard, not just in .dev.vars
  • one happy-path and one failure-path request against the real endpoint
  • logs show the route I expect (not just the home page)

Those steps belong in the pre-ship habit, not in every PR—but they complement CI instead of replacing it.

When the dry-run fails

Read the Wrangler error literally. Common fixes on this stack:

SymptomLikely cause
Cannot resolve main in wrangler.jsonBuild did not run, or main is stale (Astro 6 expects @astrojs/cloudflare/entrypoints/server)
Unknown bindingwrangler.json out of sync with Astro adapter output
Upload size jumpedAccidental client import in a server route, or a heavy dependency pulled into the Worker

Fix, rerun npm run check, then merge. The goal is never to learn about these on a Friday deploy.

Why I bother on a personal site

mayfield.io is small, but the stack is real: Astro 6, @astrojs/cloudflare v13, Workers assets, Turnstile, Resend. A broken deploy is still a broken site, even without a staging cluster.

Dry-run in CI is cheap insurance. It takes a minute on GitHub’s runners and saves the awkward “revert main” commit when Wrangler and Astro disagree.

For the broader pre-launch habit, see Checklist before shipping a small personal site. For the secrets side dry-run cannot cover, Local .dev.vars vs production secrets for Astro on Workers is the companion read.


Hero photo: Katze okkupiert PC-Tastatur by Mattes, CC BY-SA 2.0.