Skip to main content

Environments

develop is the integration branch and the repository’s default branch. main is the release branch: only develop → main integration PRs land there, cut as a frozen release/YYYY-MM-DD snapshot by a workflow a human dispatches. There is no scheduled daily integration.
Never open a develop → main PR by hand, and never re-point the snapshot ref of an open integration PR. Pushes to develop land in the next cut.

The pipeline

A push to main builds and deploys:
1

Build and test

The full gate runs in CI on the same major Node version the application ships on — kept in sync between the CI workflow, the deploy workflows and package.json engines.
2

Container image

Built and published to the GitHub Container Registry.
3

Migrations

prisma migrate deploy applies committed migration files. It never generates one — a schema change without a committed migration simply does not reach production.
4

Deploy

The App Service pulls the new image.
5

Health check

The pipeline waits for the health endpoint to report healthy before considering the deploy complete.
Production deployments are serialised — a concurrency group prevents two from overlapping, and a running deploy is not cancelled by a newer push. Documentation-only changes are excluded from the production deploy trigger: pushes touching only markdown, docs/ or .gitignore do not rebuild the image.

Infrastructure

Terraform, with per-environment configurations and remote state. The CI service principal needs role-assignment permissions; a roleAssignments/write or /delete 403 on apply has its own playbook.

Secrets

Production secrets live in Key Vault, not in App Service configuration. The App Service managed identity holds Key Vault Secrets User on the vault, and the application bootstraps the field-encryption key from it at start-up. There is a documented migration path for moving an installation from App Service environment variables to Key Vault.

Database migrations in practice

Rolling back

A bad deploy in production has its own playbook — see Runbooks. The short version: redeploy the previous image, and treat a database migration as forward-only. Rolling a migration back is a restore, not a redeploy.

Post-launch checks

The docs/operations/ playbooks cover what to verify after a release: the health endpoint, the scheduled jobs, a real sign-in on both surfaces, and one mail send. The smoke tests are automated; the sign-in is worth doing by hand on a release that touched authentication.

New customer environments

Standing up an installation for a new customer — Azure resources, Entra registration, mailbox, branding, seed data, first administrator — has a dedicated onboarding checklist. See Runbooks.