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
devtriggers development image build and deployment - push to
stagingtriggers staging image build and deployment - push to
prodtriggers Release Please - merged release changes on
prodcreate tags - pushed tags trigger the production image build and publish flow
- production tags also trigger an automated backmerge from
prodtodev
Development Deployments¶
.github/workflows/cd-dev.yml handles development deployments.
Trigger:
- push to
dev - manual dispatch
Behavior:
- builds and pushes a
devDocker 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=trueto pass--deepto 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=trueto pass--deepto 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
prodandlatest - 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 prodand push tags - release validation has already passed, or you have intentionally accepted the release risk
From the repository root:
Use minor or major instead of patch only when the release semantics require it:
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:
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:
- create a
hotfix/branch - open a PR to the appropriate release branch
- validate with
pnpm checkand relevant tests - merge into
prod - allow the normal release/tag flow to publish production artifacts
- 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