Skip to content

Release Flow

Overview

This repository uses branch-based deployment workflows for development and staging, and tag-driven releases for production.

High-level flow:

  • push to dev triggers development image build and deployment
  • push to staging triggers staging image build and deployment
  • push to prod triggers Release Please
  • merged release changes on prod create tags
  • pushed tags trigger the production image build and publish flow
  • production tags also trigger an automated backmerge from prod to dev

Development Deployments

.github/workflows/cd-dev.yml handles development deployments.

Trigger:

  • push to dev
  • manual dispatch

Behavior:

  • builds and pushes a dev Docker image
  • deploys to the development environment over SSH
  • runs development seed data after migrations when DEV_SEED_ON_DEPLOY=true
  • uses DEV_SEED_DEEP_ON_DEPLOY=true to pass --deep to the development seeder
  • supports skipping deployment with [skip-deploy] in the commit message

Staging Deployments

.github/workflows/cd-staging.yml handles staging deployments.

Trigger:

  • push to staging
  • manual dispatch

Behavior:

  • builds and publishes separate immutable application and migration images
  • uploads a content-addressed deployment bundle to S3
  • deploys to the staging EC2 host through AWS Systems Manager
  • starts host-local Docker PostgreSQL, applies migrations, and health-gates the application rollout
  • connects the application and BullMQ to the external Aiven Redis service configured in .env.staging
  • runs staging seed data after migrations when STAGING_SEED_ON_DEPLOY=true
  • uses STAGING_SEED_DEEP_ON_DEPLOY=true to pass --deep to the staging seeder
  • supports skipping deployment with [skip-deploy] in the commit message

Staging setup and required GitHub environment values are documented in environments.md.

Production Release Preparation

.github/workflows/release-please.yml runs on prod.

Trigger:

  • push to prod
  • manual dispatch with semver selection

Behavior:

  • opens or updates a Release Please PR
  • updates versioning/changelog metadata
  • prepares the production release path after merge

Production Publishing

.github/workflows/prod-release.yml runs when a tag is pushed.

Behavior:

  • builds the production Docker image
  • publishes to GHCR
  • tags images with SHA, semantic version, and stable aliases such as prod and latest
  • runs production seed data after migrations when PROD_SEED_ON_DEPLOY=true

This is the main production image publication path.

Manual Production Release Script

scripts/prod-release.sh is a local helper for manually creating and pushing a production version tag from prod. This is not part of the normal production release flow. Prefer the Release Please PR flow above for routine releases, and use this script only as a manual fallback when you intentionally need to cut the release tag yourself, such as when Release Please is unavailable, blocked, or inappropriate for an urgent hotfix.

Prerequisites:

  • the exact commit you want to deploy is already on prod
  • the working tree is clean
  • local credentials can push to origin prod and push tags
  • release validation has already passed, or you have intentionally accepted the release risk

From the repository root:

git checkout prod
git pull origin prod
./scripts/prod-release.sh patch

Use minor or major instead of patch only when the release semantics require it:

./scripts/prod-release.sh minor
./scripts/prod-release.sh major

The script verifies the branch and clean working tree, pulls latest origin prod, runs pnpm version <patch|minor|major> to create the release commit and vX.Y.Z tag, prompts for confirmation, then pushes prod with --follow-tags. The pushed tag triggers .github/workflows/prod-release.yml, which builds and deploys immutable image digests.

Backmerge

.github/workflows/backmerge.yml runs on tag pushes and creates a PR from prod back into dev.

This helps keep production fixes and release-state changes from drifting away from active development.

CI Before Release

The main CI workflow lives in ci.yml.

Before merging release-related changes, the important validation commands are:

pnpm check
pnpm test:coverage
pnpm build:ci

Sentry Source Maps

Application release image builds explicitly set SENTRY_UPLOAD=true. After the complete build, including tsc-alias, the Docker builder injects Sentry debug IDs, validates and uploads the generated JavaScript and source maps, and then removes .map files before assembling the runtime image.

Local, migration, and security-scan image builds leave SENTRY_UPLOAD at its default value of false, so they do not publish Sentry artifacts. When upload is enabled, missing or invalid Sentry credentials fail the image build instead of silently producing a release without source maps.

Hotfix Guidance

For urgent production fixes:

  1. create a hotfix/ branch
  2. open a PR to the appropriate release branch
  3. validate with pnpm check and relevant tests
  4. merge into prod
  5. allow the normal release/tag flow to publish production artifacts
  6. confirm the automated backmerge PR is created and merged as needed

Notes

  • deployment workflows rely on GitHub secrets and environment configuration
  • image publishing uses GHCR
  • release versioning and changelog generation are automated rather than maintained manually