Deployment and releases

On this page

A change reaches people in three steps: a PR preview when you ask for one, staging when it is merged to main, and production with the next release tag. One workflow does all of it: .github/workflows/platform.yml. Its header comment is the source of truth, together with dembrane/infra/README.md.

The three environments

Environment How a change gets there
PR preview Add the label preview to a pull request.
Staging Deploys main: by hand, and on every push to main once the repository variable STAGING_DEPLOY_ON_MAIN is true.
Production A release tag vX.Y.Z on main, after approval in the prod GitHub environment.

So merging to main makes a change available on staging. Production gets it with the next release.

PR previews

Production

Checks on a pull request

The workflow runs on pull requests that touch dembrane/platform, dembrane/frontend, dembrane/infra, the workflow itself or .github/scripts. A run checks only the side that changed.

Job What it checks
10-check-server Biome lint and format, the type check, bun run config check, bun run packages check, that the schema matches the migrations, that the frontend’s generated API types are in sync, and bun test --parallel.
20-check-frontend Path case, pnpm lint, tsc, the translations, and the generated API types.
21-test-frontend vitest run.
40-build-images Builds the five images once, smoke tests them, and checks the portal’s first-load bundle size.

A separate workflow, .github/workflows/check-cla.yml, checks that the author is listed in contributors.yml.

Run the main checks yourself before you push:

cd dembrane/platform && bun run check
cd dembrane/frontend && pnpm lint && pnpm exec tsc && pnpm test

Three checks catch people out:

How a deploy runs

PR previews and staging run on Google Cloud Run in europe-west4. Each environment is its own cloud project with its own identities, so a preview cannot reach staging or production. Production runs on Kubernetes through a GitOps repository: the production job pushes the images and sets the image tag there, and Argo CD migrates, rolls out and smoke tests.

.github/scripts/build-images.sh --load builds the images into your local Docker daemon when you need to test one.

Migrations

Config per environment

Non-secret values for each environment are checked in: packages/config/environments/{local,test,preview,staging,prod}.ts. A secret may only come from the process environment. Setting one in an environment file fails the boot.

Two tests guard these files. A residency test fails when a model, embedding or email location leaves the EU. A capacity test fails when an environment’s database connections would not fit its server.

Feature switches are config keys too. bun run config show <env> prints the effective values for an environment, and bun run config diff <env> <env> compares two.

Related pages

Comments