Skip to main content
Current runtime policy: Docker setup and Docker-backed E2E/image CI are paused; the Docker cron runner is retired. Rust and TanStack Start are not in use and must not be run, tested, or updated until further notice. Retained Docker and migration sections below are historical procedures. Current hosted Next.js, package, Worker, database, and mobile workflows retain their own gates. See the active runtime map.
This page explains how Tuturuuu moves from code to running environments.

Generated Release Formatting

Release Please initially pushes generated manifests, then amends that commit with Biome formatting before approval. Biome cancels superseded runs per Git ref so the intermediate unformatted commit cannot keep running beside its replacement. Inspect the run for the current release PR head when diagnosing a failure. Cancelled or skipped runs do not publish PR reports. Generated release branches use the release workflow’s formatter rather than separate automatic formatting PRs; their final commits still receive the normal format and lint checks. After formatting, scripts/ci/normalize-release-description.js also consolidates identical bullets in each component section of the generated PR description. It preserves source references, distinct wording, component summaries, and review bot content. This runs even when generated files need no formatting changes. Before formatting, scripts/ci/normalize-release-notes.js combines repeated descriptions within each new release section, retaining every distinct commit and PR link. It excludes narrowly identified integration-only merge commits. The existing production release heading marks the immutable published boundary; if that boundary is missing, normalization fails instead of rewriting history. The generated release commit is amended using the existing exact-SHA lease. No package version, dependency resolution or published changelog is rewritten.

Branch-to-Environment Map

Hosted Web Release Flow

Preview

  • Preview workflows are named vercel-preview-<app>.yaml.
  • Most preview workflows are manual-only from main with a required preview_ref; vercel-preview-platform.yaml also triggers on protected main pushes so the staging database workflow receives a same-SHA platform build signal.
  • e2e-tests.yaml also runs only on non-production pushes; production promotion relies on the already-green validation before the branch is promoted plus the production build-validation gates below.
  • Production workflows cancel superseded per-app runs only when a newer production push arrives; main commits and manual recovery runs leave an active production deployment untouched.
  • Each deploy job is bound to a vercel-preview-<app> GitHub Environment and introduces Vercel credentials only after dependency installation.
  • Platform preview is build validation only; on-premise machines own the actual apps/web runtime deployment.
  • Satellite preview deploys remain the normal Vercel validation surface for branch work and merged main changes.
  • Platform preview can reuse a successful same-SHA production platform build marker to avoid redundant preview builds. Production does not reuse preview markers because it must build and deploy the prebuilt production artifacts.

Staging Database

  • supabase-staging.yaml is tied to the Vercel Platform Preview Deployment workflow on main.
  • The staging migration runs only when the triggering platform preview build concludes successfully, or when manually dispatched.
  • The staging deploy step runs supabase db push --include-all after linking the staging Supabase project, so staging can converge after main migration history changes.
  • This means main is where app preview and staging schema advancement are meant to stay aligned.
  • If a production commit was promoted before the same-SHA staging migration run existed, manually dispatch supabase-staging.yaml from main; production migration re-evaluates after that staging run succeeds.

Production

  • Satellite production web deploys run through vercel-production-<app>.yaml.
  • A production push first runs vercel-production.yaml, which computes affected Vercel and Cloudflare apps in one runner and calls only the necessary per-app workflows. Each target uses its own last successful deployment marker, so an app skipped on an earlier commit still receives any undeployed changes.
  • Hosted apps/web production deploys run through vercel-production-platform.yaml; self-hosted machines still use the Docker release flow below for their own runtime deployment.
  • apps/apps production deploys are handled by vercel-production-apps.yaml.
  • apps/qr production deploys are handled by vercel-production-qr.yaml.
  • Each production app uses a workflow-and-branch concurrency group whose cancel-in-progress predicate matches only production push events, so the newest production SHA remains deployable without letting main commits or manual recovery runs cancel it.
  • Production deploy jobs are bound to vercel-production-<app> GitHub Environments and reject manual dispatches unless the selected branch is production.

Hosted Calendar schedules

Infrastructure owns the hosted Calendar provider-sync (every 15 minutes) and smart-scheduling (every six hours) schedules in its vercel.json and cron.config.json. Requests enter /api/cron/calendar/:job, authenticate with CRON_SECRET, and use the encrypted gateway credential to reach Calendar. Calendar must not keep a second direct Vercel schedule: direct scheduler requests do not carry the private hosting header. The retired Docker configuration retains these jobs in apps/web/cron.config.json with vercel: false. That flag excludes them from generated Web Vercel schedules; it does not activate a Docker runner. The Infrastructure hosted schedules are the active Calendar owners. After deployment, verify a fresh provider sync timestamp with all Calendar clients closed; a READY deployment alone is insufficient.

Browser App Version Metadata

  • Browser apps share one platform version from packages/utils/src/platform-release.ts; do not read visible app versions from individual app package.json files.
  • The shared browser app version is the TUTURUUU_PLATFORM_VERSION constant exported from packages/utils/src/platform-release.ts. Release Please owns that value (it carries the x-release-please-version annotation), so do not pin a literal version in docs or bump it by hand. Read the constant directly when you need the current value.
  • Every Vercel browser app workflow runs bun run --silent scripts/ci/generate-build-metadata.ts before vercel build. The generated metadata includes the commit hash, short hash, commit message, ref, environment, deployment URL, deployment stamp, and build timestamp.
  • The account-scoped version badge uses public.user_configs key SHOW_VERSION_BADGE. It is hidden by default and only exact @tuturuuu.com accounts may enable a truthy value.
  • Exact-domain enforcement happens on the server through isExactTuturuuuDotComEmail; subdomains such as @xwf.tuturuuu.com are not eligible, and client cookies cannot make the badge render for ineligible users.

Production Database

supabase-production.yaml is stricter than staging:
  1. It re-evaluates automatically after either Vercel Production Deployment Planner completes its selected production deploys on production or Supabase Staging Migration completes on main.
  2. The production planner for the target commit must have concluded successfully on production, and the selected platform deployment must have recorded the successful vercel-production-platform deployment marker for the same SHA. A workflow run that skipped because package releases were still publishing is not enough.
  3. The main staging migration for the same target commit must have completed with a success conclusion.
  4. A manual dispatch can still be used when an operator explicitly wants to run it, but the dispatch must select the production branch and still satisfy the same production-deployment and staging-migration SHA checks.
The staging-triggered path is an automatic retry for the case where production production deploy finishes before staging migration does. The production migration job still checks out the verified target commit explicitly before running supabase db push --include-all. This keeps production schema changes behind application deployment, staging validation, and branch promotion for the same commit.

Self-Hosted Web Release Flow

If a server receives code through git pull, use the Docker production commands from the checked-out commit:
  • bun serve:web:docker for in-place replacement
  • bun serve:web:docker:bg for blue/green rebuild-before-cutover deployment
Blue/green is the safer path when uptime matters because the new image is built and health-checked before the proxy is reloaded.

Inactive migration and retained Docker tooling

apps/tanstack-web and apps/backend are not in use. Their source and runbooks are retained for a possible future resumption; they are not release dependencies for the live Next.js apps. Migration-specific builds, workers, Docker comparisons, and cutover gates must not be required for ordinary Next.js delivery. Keep source tracking required by repository policy without claiming a runtime cutover. Docker setup is also outside the current supported path, and the Docker cron runner is retired. The earlier self-hosted commands in this page are retained reference procedures. Hosted Vercel/Cloudflare delivery and the owning scheduler configuration establish active release behavior. See the active runtime map.

Team Release Checklist

  1. Merge the change set with green CI.
  2. Docker setup is inactive; do not require or run docker-setup-check.yaml until explicitly resumed.
  3. If database migrations changed, confirm the main-driven staging path first. Check that app code remains usable against the old production schema: the production Vercel planner deploys apps before the production migration job runs, and the job may wait in the Actions queue.
  4. Promote to production only after preview and staging behavior is understood.
  5. Confirm that the follow-up Supabase workflow’s Migrate production database job actually ran and applied the expected migration. A successful prerequisite job can leave the migration job skipped.
  6. For schema-dependent app releases, test the new deployment’s authenticated read path against production after the migration and confirm the public alias points to that tested deployment.
  7. For self-hosted rollout, deploy from the intended commit and prefer bun serve:web:docker:bg.

Rollback Guidance

  • Vercel-hosted rollback: for satellite apps, redeploy the previous known-good commit or use Vercel rollback tooling.
  • If an app reads a production column that has not migrated yet, roll back only that app to a tested deployment. Keep the migration workflow running, then test the newer deployment directly against the migrated database before promoting its alias again. Verify the public URL after both changes.
  • Supabase rollback: use a corrective migration instead of editing applied migration history.
  • Self-hosted Docker rollback: checkout the previous known-good commit and rerun bun serve:web:docker:bg.

What Not To Do

  • Do not push production schema changes directly from a laptop as the normal path.
  • Do not assume staging and production migrations are interchangeable; they are gated differently.
  • Do not manually dispatch production Supabase migration from main; the only valid main path is the automatic staging-migration re-evaluation, and the production gate still requires the same commit to have both a successful production platform deployment and a completed successful main staging migration.
  • Do not use the in-place Docker path when you specifically need rebuild-before-restart semantics.

Migrated Supabase CI baseline

E2E jobs share a pristine database-volume snapshot, in addition to the existing Supabase service image cache. The exact fingerprint includes migration contents, seed files, local configuration, setup code, CLI/service versions, and runner architecture. A UTC-day seed epoch bounds time-relative fixture staleness and stays fixed throughout a job. There are no partial restore keys. Only trusted main runs publish a snapshot, before tests create users or other mutable fixtures. The setup action refuses an existing database volume. It verifies archive integrity, the Postgres image digest, and migration history before using a restored database; a mismatch or corrupt snapshot rebuilds from migrations. Snapshots are copied only after PostgreSQL stops cleanly. Each job gets its own volume. Gateway model metadata is refreshed after restoring, so it is not frozen into the baseline. Production and staging database deployments do not use these local test snapshots. Keep an uncached migration run in validation when changing migrations or the cache format. Compare cold and warm setup times before claiming a performance gain. The helper refuses execution outside a fresh Linux GitHub Actions runner and must never be used to archive a developer or production database. The Supabase baseline fingerprint includes the configured image registry as well as the image version. CI honors SUPABASE_INTERNAL_IMAGE_REGISTRY for restore integrity checks. Its contract also transfers the pristine snapshot to a separate runner and requires a verified restore, so a safe cold fallback cannot hide a broken cross-runner cache. Restore failures report only their phase, without printing credential-bearing child-process output.