Deployment
Applications
Section titled “Applications”API and document builder
Section titled “API and document builder”A push to main on ba-api or ba-document-builder-service runs that repository’s .github/workflows/deploy.yml (it can also be started by hand with Run workflow). The job runs in the GitHub environment ba-staging and:
- Signs in to Azure with OIDC (
azure/login), thenaz acr login. - Builds the image and pushes it to
acrbastagingassha-<short commit>andmain-latest. - Runs
az containerapp update --revision-suffix sha-<short commit>on the app, so the revision name says which commit it runs. - Posts the result to Microsoft Teams.
ba-apialso runs a Snyk image scan that reports but does not block.
The API runs its database migrations at boot (RUN_MIGRATIONS_ON_START=1). Watch the first minute of the new revision’s console log after a deploy that includes a migration.
To roll back, rerun the workflow on the last good commit, or point the app at the previous tag:
az containerapp update -n ca-ba-staging-api -g rg-ba-staging \ --subscription ba-staging \ --image acrbastaging.azurecr.io/ba-api:sha-<previous> \ --revision-suffix sha-<previous>-rbWeb client
Section titled “Web client”Cloudflare Pages builds ba-client from main (production) and from every pull request (preview). There is no GitHub workflow for the deploy; pr-cloudflare-notification.yml only waits for the Pages build and records a GitHub deployment. Environment variables for the build are in wrangler.toml (env.production and env.preview). Previews use the mock-header login against the staging API, which the API refuses in production mode, so the preview’s “Use real authentication” box is the way in.
Infrastructure
Section titled “Infrastructure”Every change to ba-infrastructure goes through a pull request:
- CI runs lint, validate, Checkov, Trivy and
terragrunt run-all plan, and posts a per-layer plan table as a PR comment. - A reviewer approves. The
mainruleset requires one review, resolved threads and a squash merge. The PR title is the commit message, in Conventional Commits form (feat(compute): BAM-4 …). - On merge, the apply workflow runs in the
infrastructure-productionenvironment.
Applying from a laptop
Section titled “Applying from a laptop”Needed when a change must be applied before it is merged, or when an import or a hostname bind cannot run in CI. From the repository root, signed in with az login as yourself:
export ARM_USE_OIDC=false ARM_USE_CLI=trueexport ARM_TENANT_ID="$(az account show --query tenantId -o tsv)"export TF_VAR_azure_subscription_id="$(az account show \ --subscription ba-staging --query id -o tsv)"source <(scripts/fetch-kv-secrets.sh kv-ba-staging-tf)
# The security layer reads the dek-master key and the database layer# reads mongo-url, so a run-all needs both vault roles active.scripts/kv-access.sh kv-ba-staging-app --roles both \ --reason "BAM-<n>: apply <what>"
# Only if the aws layer has changes.aws sso login --profile sii-admin
cd environments/stagingterragrunt run-all init # once per clone; CI does the sameterragrunt run-all apply --terragrunt-exclude-dir awsThree things that go wrong without the lines above:
- “state file is encrypted and can not be read”:
run-all initwas skipped. - 403 ForbiddenByRbac on
dek-masterormongo-url: the PIM roles are not active. - Cloudflare “Authentication error (10000)”:
TF_VAR_cloudflare_api_tokenis empty or stale; re-source the vault script.
Anything already in the Cloudflare zone is an import, not a create. The old record must be imported with terragrunt import before the plan is applied, or the apply fails on it.