Skip to content

Runbook: Local Delivery Fallback

Purpose: Deliver without GitHub Actions — run the CI gate, cut the release, and publish the docs site from a workstation, using the same entry points the workflows use When to use: Actions is unavailable (billing cap hit, spending limit, outage — e.g. #1648) and delivery must not stall Prerequisites: A clean checkout of the repo on its main branch; node >= 22, npm, jq, make, and gh authenticated (gh auth status); Cloudflare credentials for the docs deploy only Estimated time: 10–20 minutes for all three

The three Actions workflows and their local equivalents. Each local path runs the same underlying entry point as the workflow — there is no parallel logic to drift:

Workflow What it does Local equivalent
ci.yml checks + tests + doc-drift gate make ci (step 1)
auto-release.yml version bump, CHANGELOG, tag, GitHub Release bob-release (step 2)
docs-deploy.yml build + verify + publish the docs site npm run docs:deploy (step 3)

Run them in this order: gate first, then release, then docs.

make ci is exactly what Actions runs (checks + full test suite + docs gates):

Terminal window
BOB_ALLOW_NONPROJECT=1 make ci
  • BOB_ALLOW_NONPROJECT=1 is required: test-prune builds fixtures in temp dirs that the #707 project guard otherwise refuses (CI sets the same flag).
  • The full suite takes several minutes; test-state-machine alone runs 2–3 min.
  • Do not trust a piped exit code (make ci | tail reports the pipe’s status, not make’s) — run it bare, or capture to a file and check $? directly.

Verify: the run ends with All tests passed. and exit code 0. A red suite blocks the release cut — fix first, exactly as a red CI check would block a merge.

Known flaky tests (pass on isolated re-run — re-run before treating as real): test-state-machine.js (execSync timeout under load), test-checks.sh check-fleet grep (#1621), test-dev-up-docs (port race under suite load).

Terminal window
bob-release # or: make release-local

This is auto-release.yml verbatim: npm run release (commit-and-tag-version) bumps from Conventional Commits, rewrites CHANGELOG.md, commits chore(release): X.Y.Z, tags vX.Y.Z, pushes commit + tag atomically (3-attempt rebase retry), and publishes a GitHub Release from the new changelog section.

  • Preview first with bob-release --dry-run; force a bump type with --release-as patch|minor|major (parity with the workflow’s manual dispatch).
  • It refuses on: tracked working-tree changes (stash first — untracked files only warn), a branch other than main, or HEAD != origin/<main>.
  • It is idempotent: re-running when up to date is a no-op, and re-running after a partial failure (bump landed, push or Release didn’t) resumes the unfinished half instead of double-bumping.

Verify:

Terminal window
git describe --tags # the new vX.Y.Z, on HEAD
gh release view "$(git describe --tags --abbrev=0)" --json tagName,url

Both must show the new version. If the Release is missing, re-run bob-release (the resume path publishes it).

Terminal window
export CLOUDFLARE_API_TOKEN=... # token with Pages:Edit
export CLOUDFLARE_ACCOUNT_ID=... # account UUID
npm run docs:deploy # primary engine (vitepress) -> bigbrain-docs

Same engine the workflow drives: builds via scripts/docs-site/build.sh, then wrangler pages deploy, then fetches the published site back (#1446) — a green upload alone is not evidence of publication. A comparison engine deploys with npm run docs:deploy -- --engine starlight (lands at <project>-starlight). An interactive wrangler login session works in place of the env vars.

Verify: the deploy script’s own post-deploy fetch must pass (it fails the run if the site doesn’t answer). Spot-check a page that this delivery changed — “done” for docs means live and verified, not uploaded.

  • If Actions is down for billing (#1648-class), leave the tracking todo open — this runbook is the bridge, not the fix.
  • Nothing else to reconcile: the release commit is loop-guarded (chore(release) prefix), so when Actions comes back the next push resumes auto-release cleanly on top of whatever was cut locally.
  • Versioning how-to — how auto-release works and how it’s provisioned
  • .github/workflows/auto-release.yml, ci.yml, docs-deploy.yml — the workflows this substitutes for
  • Incident response runbook — when something is broken rather than unavailable
  • Self-hosted Actions runner — the structural fix for minute caps: CI on fleet hardware bills zero minutes, so this fallback is needed less often