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
masterin every repo. Nodevelop, no long-livedreleasebranches — those are retired. - Feature branches are named
feature/TI-XXX-*(orfix/TI-XXX-*) and live hours to a day. Incomplete work still merges to trunk — gated behind a feature flag (default off) in platform config. masteris protected: changes land via PR with required CI gates (lint, typecheck, tests, build). No direct pushes.- Every merge to
masterauto-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:
- 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).
- CI gates pass on the trunk commit — lint, typecheck, tests, build.
- Migrations applied first if the release needs them (see below) — schema before code, with a verify step between.
- Move the pointer — push the
vX.Y.Ztag (backend) or fast-forwardproduction(frontend). - 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).
- 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
| Dev | Production | |
|---|---|---|
| Trigger | Merge to master | Tag vX.Y.Z (backend) / fast-forward production (frontend) |
| Who | Automatic | Deliberate, human-initiated |
| Rollback | Revert/fix-forward on trunk | Redeploy previous tag / re-point production / flag off |
| Migrations | Applied manually, before code | Applied manually, before code |