Release Pipeline workflow must be triggered explicitly via workflow_dispatch from the main branch. A human approval step on the production GitHub Actions environment is required before any deployment runs.
Release pipeline overview
build-production-image and deploy-production jobs only run when the workflow is triggered via workflow_dispatch on main. Pushes to main only run validate-staging.
Triggering the pipeline
Confirm main is ready
Verify
main is clean and the latest commit has a green validate-staging run. Check that no open regressions exist.Dispatch the workflow
Go to Actions → Release Pipeline → Run workflow in the GitHub repository and select the
main branch. Alternatively, use the GitHub CLI:Wait for image build
The
build-production-image job runs validate-staging again, then builds and pushes the backend Docker image to:Approve the deployment
Once
build-production-image is green, GitHub will pause at deploy-production and wait for a reviewer with access to the production environment to approve. Navigate to the workflow run and click Review deployments → Approve.Running the deployment script locally
Thedeploy:production script can be run outside of CI if all required environment variables are set:
scripts/deploy-production.sh, which:
- Validates that all required variables are present.
- Writes a
backend.production.envfile locally from thePRODUCTION_*variables. - Runs
ssh-keyscanto collect the remote host’s key. - Copies the env file to the remote host over SCP.
- Over SSH: moves the env file into place, logs in to
ghcr.io, pulls the image, removes the existing container, and starts the new one.
uploads directory is bind-mounted from the host so user-uploaded files survive container replacements.
Docker image
The backend image is built frompackages/backend/Dockerfile using the full repository as the build context. The image is tagged with both the exact git SHA and production-latest:
IMAGE_REF passed to deploy-production.sh always uses the SHA tag for deterministic deploys.
Production secrets
These must be configured in theproduction GitHub Actions environment.
- Backend
- SSH host
- Optional variables
| Secret | Description |
|---|---|
PRODUCTION_DATABASE_URL | Full Prisma-compatible connection string |
PRODUCTION_DB_HOST | Database host (default: 127.0.0.1) |
PRODUCTION_DB_PORT | Database port (default: 5432) |
PRODUCTION_DB_NAME | Database name (default: fleet_management) |
PRODUCTION_DB_USER | Database user (default: postgres) |
PRODUCTION_DB_PASSWORD | Database password |
PRODUCTION_JWT_SECRET | Secret used to sign JWT tokens |
PRODUCTION_DEFAULT_LOGIN_PASSWORD | Initial admin password |
PRODUCTION_SMTP_HOST | SMTP server host (default: 127.0.0.1) |
PRODUCTION_SMTP_PORT | SMTP server port (default: 25) |
PRODUCTION_SMTP_SECURE | true for TLS, false otherwise (default: false) |
PRODUCTION_SMTP_USER | SMTP authentication user |
PRODUCTION_SMTP_PASS | SMTP authentication password |
PRODUCTION_EMAIL_FROM | Sender address for outgoing emails |
Remote host requirements
Before the first deployment, ensure the remote host meets these requirements:- Docker is installed and the SSH user can run
dockercommands. - The port defined by
PRODUCTION_APP_PORT(default3001) is open to incoming traffic. - The host has outbound access to
ghcr.ioto pull images. - The production database and SMTP server are reachable from the host.
Rollback
To roll back to a previous image:Identify the target commit
Find the git SHA of the last known-good deployment from the
production-release-<sha> artifact in GitHub Actions.Re-trigger the workflow
Run the
Release Pipeline workflow again on the target commit or re-tag main to that SHA. You can also run deploy:production locally with the specific IMAGE_REF: