Skip to content

deploy-staging.mjs

Deploys the true staging Cloudflare Worker with the spectator-testing environment: public signup on, the admin surface reachable, the home system packed at boot, and a 25x clock.

Operator toolingdeploy-staging.mjs

What it does

Builds the site, then deploys the worker grafted-wars-true-staging via wrangler deploy. Sets GW_PUBLIC_SIGNUP, ADMIN_ROUTES, GW_DENSE_SEED and GW_CLOCK_RATE so staging differs from the production-safe defaults wrangler.jsonc bakes in. Stamps a deploy-time version into src/server/version.mjs for the duration of the deploy and restores it afterward. Reads several further environment variables to choose which starting stocks a fresh colony gets, force a universe reset, or override the owner claim hash. None of them are its own command-line flags.

Usage

The minimal invocation, once Cloudflare credentials are set:

bash
npm run deploy:staging

Options

FlagValueWhat it doesDefault
--namegrafted-wars-true-stagingPassed by this script to the underlying wrangler deploy call, naming the Cloudflare Worker being deployed. Not read from this script's own command line.grafted-wars-true-staging (fixed)
--varNAME:VALUE, repeated once per environment variablePassed by this script to wrangler deploy, one occurrence per variable it sets on the deployed worker — see Inputs and outputs for the full list. Not read from this script's own command line; the names and values come from this script's own environment.Always includes GW_PUBLIC_SIGNUP:1, ADMIN_ROUTES:1, GW_DENSE_SEED:1, GW_CLOCK_RATE:25; the rest are conditional

Inputs and outputs

Reads, all optional unless noted:

  • CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID — required unless GW_DEPLOY_DRY=1; read from the environment or the repository's gitignored .env.
  • ADMIN_ROUTES, GW_DENSE_SEED, GW_CLOCK_RATE — override this script's spectator-testing defaults (1, 1, 25). Set to an empty string to fall back to wrangler.jsonc's production-safe value for that one variable instead of dropping it entirely.
  • ADMIN_CLAIM_HASH — resolved the same way as in deploy-prod.mjs: the local token at ~/.grafted-wars/owner-token, or a 64-character hex override.
  • GW_STAGING_RESET — any non-empty value, sets RESET_TOKEN on the worker. The universe wipes every user-state table on its next boot if that value differs from the one already stored, so a reset needs a new value each time.
  • GW_STAGING_STOCK_PRESET (or the older GW_STAGING_STOCK_ARM) — chooses which starting stocks a fresh colony gets. An unrecognized name stops the script before it builds.

Writes src/server/version.mjs, stamped then restored, the same as deploy-prod.mjs. Calls wrangler deploy only — unlike deploy-prod.mjs, this script makes no domain-binding calls; staging serves only its workers.dev address. Every --var this script sets is printed in its dry-run and live logs except ADMIN_CLAIM_HASH and RESET_TOKEN, whose values are replaced with <set, value withheld>.

Exit codeMeaning
0Deployed — or, with GW_DEPLOY_DRY=1, printed what it would have done without touching anything
1An unrecognized GW_STAGING_STOCK_PRESET/GW_STAGING_STOCK_ARM, a failed npm run build, or a failed wrangler deploy
2CLOUDFLARE_API_TOKEN or CLOUDFLARE_ACCOUNT_ID is missing

Examples

Deploy staging with its default spectator-testing settings:

bash
npm run deploy:staging

Deploy while forcing a wipe of every account, colony and mission staging holds, by setting GW_STAGING_RESET to a value it has never used before:

bash
GW_STAGING_RESET=$(date +%s) npm run deploy:staging

Preview the exact wrangler invocation without deploying or needing Cloudflare credentials:

bash
GW_DEPLOY_DRY=1 npm run deploy:staging

Notes

ADMIN_EMAIL is a secret, not a --var, set independently with npx wrangler secret put ADMIN_EMAIL --name grafted-wars-true-staging; this script never sets it, and a worker without it refuses every request. This is a separate secret from production's — see deploy-prod.mjs, whose worker is confusingly named grafted-wars-staging, the reverse of this one's grafted-wars-true-staging.

ADMIN_CLAIM_HASH, if supplied as an environment override rather than left to the on-disk owner token, must be a 64-character hex digest. Unlike deploy-prod.mjs, this script resolves it at module load — before the credential check and before npm run build run, and whether or not GW_DEPLOY_DRY=1 is set. A malformed value crashes the process with an uncaught exception instead of this script's own RED:-prefixed error, and nothing is built or deployed.

A densely seeded, 25x-clocked staging universe under sustained bot load can exceed the Durable Objects free-tier row-read quota. That is a Cloudflare plan limit this script cannot avoid, not a defect in the deploy.

There is no rollback command in this tooling. Undoing a bad deploy means checking out a known-good commit and running this script again. Because this script never touches domain bindings, a failed or partial deploy never leaves DNS state behind — only the worker itself, at whatever version wrangler deploy last completed.

Source

scripts/deploy-staging.mjs — part of Operator tooling