Skip to main content

Deploy & Release

We run trunk-based development across every repo. There is exactly one long-lived branch — master (the trunk) — and everything else is short-lived.

The flow at a glance

The rules

  • Trunk is master in every repo. No develop, no long-lived release branches — those are retired.
  • Feature branches are named feature/TI-XXX-* (or fix/TI-XXX-*) and live hours to a day. Incomplete work still merges to trunk — gated behind a feature flag (default off) in platform config.
  • master is protected: changes land via PR with required CI gates (lint, typecheck, tests, build). No direct pushes.
  • Every merge to master auto-deploys to DEV. The dev environment always reflects the tip of trunk.
  • Production promotion is a deliberate, separate act — it never happens just because something merged.

How production promotion works

Backend services (user-management, video-streaming-server, bot-backend)

These deploy to a cloud app environment. Promotion = pushing an annotated semver tag on a trunk commit:

git tag -a vX.Y.Z -m "Release vX.Y.Z" <trunk-commit>
git push origin vX.Y.Z

The CI pipeline is keyed on v* tags — the tag push triggers the production build and deploy. The tag itself is the release; bump the manifest version in the PR that precedes the tag.

Frontend apps (interviews-ui, smart-interview-ui)

The frontend hosting service builds per connected branch, not per tag. So production apps are connected to a thin production deploy-pointer branch. Promotion = fast-forwarding production to the trunk commit you're releasing:

git checkout production
git merge --ff-only <trunk-commit>
git push origin production

production is a deploy ref, not a parallel line of development — it only ever fast-forwards to commits already on master.

Promotion checklist

Run through this every time, no exceptions:

  1. DEV is green — the candidate commit has been deployed to DEV and verified (health checks passing, the change observed working at https://develop.theinterviews.ai).
  2. CI gates pass on the trunk commit — lint, typecheck, tests, build.
  3. Migrations applied first if the release needs them (see below) — schema before code, with a verify step between.
  4. Move the pointer — push the vX.Y.Z tag (backend) or fast-forward production (frontend).
  5. Post-deploy smoke check — environment reports healthy, https://www.theinterviews.ai returns 200, and you exercise the critical path the release touched (e.g. log in, start an interview).
  6. State the rollback path before you promote, per surface. If you can't state it, you're not ready.

Rollback

Backend

Redeploy the previous tag. The prior release tag still points at a known-good trunk commit — re-trigger the production deploy from it (or push a new tag on that commit). A bad tag can also be removed:

git push origin :refs/tags/vX.Y.Z

Frontend

Re-point production at the previous known-good commit (or use the hosting service's option to redeploy/promote the previous successful build). Because production only ever contains commits already proven on trunk, rolling back is a pointer move, not a code change.

Code-level

For changes shipped behind a feature flag, the fastest rollback is flipping the flag off — no deploy at all. Prefer flags for anything risky.

Database migrations

Migrations are applied deliberately by a human, never automatically. The schema-migration framework's auto-apply is intentionally disabled in the backend — the app validates the schema at boot but never changes it.

  • Migration-first ordering. Apply the migration to an environment before deploying code that needs it. Migrations are additive/append-only forward, so old code keeps running safely against the new schema. The reverse order causes boot failures: the backend refuses to start if any entity references a column that doesn't exist.
  • Show migration + rollback before applying. Every migration ships with a rollback script, reviewed together.
  • Destructive SQL is wrapped in a transaction:
BEGIN;
-- destructive statements here
COMMIT;

so a mistake can be rolled back before commit.

  • Never edit a shipped migration file. Write a new timestamped migration instead.
  • Verify schema parity between dev and prod before promoting a backend release — a column present in dev but missing in prod will fail the production boot.

Summary

DevProduction
TriggerMerge to masterTag vX.Y.Z (backend) / fast-forward production (frontend)
WhoAutomaticDeliberate, human-initiated
RollbackRevert/fix-forward on trunkRedeploy previous tag / re-point production / flag off
MigrationsApplied manually, before codeApplied manually, before code