Files

10 KiB

summary
summary
Maintainer deploy checklist: Convex backend, Vercel web app and PR previews, CLI npm release, and API routing.

Deploy

This is a maintainer runbook for the ClawHub project. It is intentionally kept under specs/ so it does not publish into the user-facing ClawHub docs tab.

ClawHub is two deployables:

  • Web app (TanStack Start) -> typically Vercel.
  • Convex backend -> Convex deployment (serves /api/... routes).

1) Deploy Convex

From your local machine:

bunx convex env set APP_BUILD_SHA "$(git rev-parse HEAD)" --prod
bunx convex env set APP_DEPLOYED_AT "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" --prod
bunx convex deploy

Or use the GitHub Actions pipeline:

gh workflow run deploy.yml --repo openclaw/clawhub --ref main

Production deploy notes:

  • deploy.yml is manual-only (workflow_dispatch). Merging to main does not deploy.

  • The workflow must be started from main.

  • The catalog-taxonomy digest and high-/medium-confidence classification rollout migrations were one-time production operations and are no longer part of the deploy checklist.

  • While migrations:runCatalogMetadataCanonicalization exists, backend deploys that include it require an operator to dry-run, explicitly apply, and verify both tracked migrations before inferred-topic and inferred-category compatibility can be removed:

    bunx convex run migrations:runCatalogMetadataCanonicalization '{"dryRun":true}' --prod
    bunx convex run migrations:runCatalogMetadataCanonicalization \
      '{"dryRun":false,"confirm":"canonicalize-catalog-metadata"}' --prod
    bunx convex run --component migrations lib:getStatus --watch --prod
    
  • Deploy targets:

    • full: deploy Convex, verify contract, wait for the matching Vercel production deploy, then run smoke tests
    • backend: deploy Convex, verify contract, then run smoke tests against current production
    • frontend: wait for the Vercel production deploy for the selected main SHA, then run smoke tests
  • Ordinary backend deploys require both external-skill rollout modes to be missing or off. When either rollout is intentionally active, use a backend-only deploy and set active_rollout_deploy_confirm=pause-and-restore-active-rollouts. The workflow records the exact active modes, pauses them before deploying Convex, and restores and verifies them before production HTTP smoke. The restore steps run even when deployment or dark-state verification fails.

  • frontend does not call vercel deploy directly yet. It relies on the existing Vercel Git-based production deploy for that SHA.

  • The real deploy job uses the GitHub Production environment for deploy secrets, but it does not wait for a separate approval.

  • Required Production environment secret: CONVEX_DEPLOY_KEY.

  • Optional Production environment secret: PLAYWRIGHT_AUTH_STORAGE_STATE_JSON for authenticated smoke coverage.

CLI npm release

The clawhub CLI package is released separately from the app deploy. Only stable releases are supported here: vX.Y.Z.

Use the GitHub Actions workflow:

gh workflow run clawhub-cli-npm-release.yml \
  --repo openclaw/clawhub \
  --ref main \
  -f tag=v0.11.0 \
  -f preflight_only=true

Then rerun the same workflow from main with:

  • the same tag
  • preflight_only=false
  • preflight_run_id=<successful preflight run id>

CLI release notes:

  • Real publishes are manual-only and require the workflow to be started from main.
  • The publish job waits at the GitHub npm-release environment for approval.
  • npm auth is handled through npm trusted publishing, not an NPM_TOKEN.
  • npm trusted publisher must be configured for package clawhub with repository openclaw/clawhub, workflow clawhub-cli-npm-release.yml, and environment npm-release.
  • After a successful npm publish, the workflow creates or updates the matching GitHub Release from the CHANGELOG.md section and appends npm tarball/integrity proof.

If npm publish succeeds but GitHub Release creation needs repair, rerun the GitHub Release workflow without publishing to npm again:

gh workflow run clawhub-cli-github-release.yml \
  --repo openclaw/clawhub \
  --ref main \
  -f tag=v0.11.0 \
  -f preflight_run_id=<successful preflight run id> \
  -f update_existing=false

If the original publish workflow failed after npm publish while creating the GitHub Release, omit publish_run_id; the repair workflow accepts only successful proof run ids.

Use update_existing=true only when intentionally replacing the body for an existing GitHub Release.

That workflow assumes Vercel Git integration is enabled for this repo. It does not run vercel deploy directly; frontend-related steps wait for the GitHub commit status Vercel - clawhub for the selected SHA, then run smoke tests against production.

Ensure Convex env is set (auth + embeddings):

  • AUTH_GITHUB_ID
  • AUTH_GITHUB_SECRET
  • CONVEX_SITE_URL
  • JWT_PRIVATE_KEY
  • JWKS
  • OPENAI_API_KEY
  • RESEND_API_KEY for account-ban notification email
  • CLAWHUB_SECURITY_EMAIL_FROM for the outbound From header, defaulting to ClawHub Security <noreply@notifications.openclaw.ai> on the verified Resend domain
  • CLAWHUB_NOREPLY_FROM for guarded staff emails, defaulting to ClawHub <noreply@notifications.openclaw.ai> on the verified Resend domain
  • SITE_URL (your web app URL)
  • Optional webhook env (see docs/webhook.md)
  • Recommended GitHub App env for authenticated GitHub API reads used by publish gates:
    • GITHUB_APP_ID
    • GITHUB_APP_INSTALLATION_ID
    • GITHUB_APP_PRIVATE_KEY
  • Optional fallback: GITHUB_TOKEN (used when GitHub App auth is unavailable, and for arbitrary public repository lookups such as trusted-publisher setup)

Do not set TRUST_FORWARDED_IPS=true while the Convex *.convex.site HTTP origin remains publicly reachable. That flag makes rate limits and download metrics trust forwarded client IP headers, so it is only safe behind a header-sanitizing edge that prevents direct origin requests.

2) Deploy web app (Vercel)

Set env vars:

  • VITE_CONVEX_URL
  • VITE_CONVEX_SITE_URL (Convex "site" URL)
  • CONVEX_SITE_URL (same value; used by auth provider config)
  • SITE_URL (web app URL)
  • VITE_APP_BUILD_SHA (set to the same commit SHA stamped into Convex)

Deploy order:

  1. Convex
  2. contract verify
  3. wait for Vercel production deploy for the same Git SHA
  4. smoke

Disposable PR previews

Vercel Preview builds use bun run build:vercel. The build entrypoint requires a Convex Preview deploy key, recreates the branch's Convex preview with --preview-create, builds the frontend with that deployment's URL, and runs the same bun run seed pipeline used by local development against that preview name.

One-time setup:

  1. In the Convex project settings, generate a Preview deploy key.
  2. In the Vercel project, set CONVEX_DEPLOY_KEY to that key for the Preview environment only.
  3. In the Convex project default environment variables for Preview deployments, set:
    • CLAWHUB_PREVIEW=1
    • CLAWHUB_DISABLE_CRONS=1
  4. Do not copy production auth, email, webhook, scanner, worker, backup, or user-channel secrets into Preview defaults.
  5. Remove CONVEX_DEPLOY_KEY from the Vercel Production environment if it exists. Production Convex deploys remain manual-only through .github/workflows/deploy.yml.

The shared seed command fails closed unless its target is local or an explicit preview name selected with a Convex Preview deploy key. It installs the committed public corpus plus the same synthetic clean, suspicious, and malicious presentation states used locally. Staging remains snapshot-backed and production is never seeded.

Preview browser traffic is public and read-only. Nitro rejects non-GET/HEAD requests before proxying and adds X-ClawHub-Preview-Backend to proxied preview responses so smoke proof can record the paired non-secret deployment name. Authenticated write flows belong in the permanent test environment.

3) Route /api/* to Convex

Nitro handles /api/** and /v1/feeds/** through the environment-aware Convex proxy in server/convexProxy.ts. The target comes from the build's VITE_CONVEX_SITE_URL, or is derived from the paired VITE_CONVEX_URL. Those build-time values are compiled into the Nitro server output so stale Vercel runtime variables cannot redirect a Preview deployment to production.

Do not add a production deployment hostname back to vercel.json. Static rewrites would make Vercel previews query production even when their Convex client points at a disposable backend.

For self-hosting, set VITE_CONVEX_URL and optionally VITE_CONVEX_SITE_URL to the intended deployment before building.

4) Registry discovery

The CLI can discover the API base from:

  1. explicit CLI/env override
  2. configured registry URL
  3. site URL registry metadata

Keep production rewrites and discovery metadata aligned before release.

Hosted feeds

Refresh the OpenClaw hosted plugin and skill feeds after the production Convex deployment has the catalog projections:

gh workflow run publish-catalog-feed.yml --repo openclaw/clawhub --ref main

The workflow stores both current feed snapshots in Convex and serves them through /v1/feeds/plugins and /v1/feeds/skills with public edge-cache validators. The unversioned /feeds/plugins and /feeds/skills paths redirect to their versioned routes. Attach registry.openclaw.ai to the same Vercel project before configuring OpenClaw's default feed URLs.

Production backend deploys publish an initial promotions snapshot after Convex deploys. Active promotion changes then refresh the stored snapshot immediately, schedule refreshes at launch and expiry boundaries, and use a six-hour cron as an expiry backstop. The feed is served through /v1/feeds/promotions, with /feeds/promotions redirecting to the versioned route.

5) Post-deploy checks

Run the contract verifier and smoke tests against production after deploy:

bun run verify:convex-contract -- --prod
PLAYWRIGHT_BASE_URL=https://clawhub.ai bunx playwright test e2e/menu-smoke.pw.test.ts e2e/upload-auth-smoke.pw.test.ts