Skip to content

Deployment Pipeline

Deployment Pipeline

This page is the developer-facing summary of how code moves from the repo into AWS. Use the Terraform reference pages for the full infrastructure layout:

Workflow

The release flow is:

  1. Make and test your code changes locally.
  2. Build the container image for the service you changed.
  3. Tag the image with an immutable SHA-based tag.
  4. Push the image to the staging ECR.
  5. Update the staging Terraform image tag map.
  6. Run terraform apply for staging.
  7. After staging is validated, copy the staging tag map into production, mirror the promoted images into prod ECR, and apply prod.

If you prefer a shorter command path, the repo also provides a thin Makefile wrapper:

  • make staging-build
  • make staging-plan
  • make staging-apply
  • make staging-deploy
  • make prod-promote
  • make prod-deploy

Those are the normal promotion targets.

Direct production operations are still available when needed:

  • make prod-build
  • make prod-plan
  • make prod-apply

Those targets still call the same build scripts and Terraform commands under the hood, but they are not the default release path.

Build And Tag

From the repository root, use make staging-build to build the staging images with the current git SHA and push them to the staging ECR:

make staging-build TARGETS="api"

The script behind the target:

  • logs in to the staging ECR registry when --push is set
  • runs docker buildx bake against docker-bake.hcl
  • writes infra/envs/staging/image-tags.auto.tfvars.json unless --no-tfvars is used
  • accepts --target so you can build only the image you changed

If you need the direct script invocation, the staging flow is:

python scripts/build_staging_images.py \
  --push \
  --aws-profile glimpse-staging \
  --target api

That writes infra/envs/staging/image-tags.auto.tfvars.json unless --no-tfvars is used.

When you promote to production, make prod-promote copies the staged Terraform tag map and mirrors the promoted SHA tags into the production ECR.

The bake file builds the standard set of images:

  • tracker-api
  • tracker-frontend
  • tracker-admin
  • tracker-services

If you only need one image, pass --target api, --target admin, and so on to the script.

Deploy With Terraform

After pushing the images, the script already updates the staging environment tag map. Apply Terraform to roll the staging image tags out:

terraform -chdir=infra/envs/staging apply -auto-approve

Terraform updates the ECS task definitions to point at the new immutable image tags and rolls the services forward.

Once staging is validated, promote the exact same tag map to production:

make prod-promote
terraform -chdir=infra/envs/prod apply -auto-approve

This keeps production on the same commit-tested image set as staging without rebuilding.

First Deploy

On a brand-new environment, start with the bootstrap tag so Terraform can create valid task definitions before any real images exist in ECR.

Use sha-bootstrap for the initial image_tags map, run the first terraform apply, then build and push real images and re-apply with the final SHA tags.

Rollback

To roll back, change the relevant image tag in image-tags.auto.tfvars.json to a previous immutable tag and re-apply Terraform in the target environment.

Because ECR tags are immutable in this project, the old image remains available for rollbacks.

Versioning & Releases

The repo carries one version (VERSION at the repo root, currently semver X.Y.Z) across the backend, both Svelte apps, and services together, since they already build and deploy as one set of images. CHANGELOG.md records one entry per version, including the exact git commit it was built from.

A version is only cut when preparing a prod push, not on every merge to main. Cut it first, before staging-build, so the release commit itself is what gets SHA-tagged and tested in staging - prod-promote then mirrors that exact tested image into prod rather than rebuilding, same as it always has.

make release                       # bumps VERSION, adds a CHANGELOG.md entry, commits, tags v X.Y.Z
git push && git push origin vX.Y.Z # after reviewing the commit/tag
make staging-build RELEASE_TAG="v$(cat VERSION)"
make staging-apply
# validate in staging
make prod-promote RELEASE_TAG="v$(cat VERSION)"
make prod-apply

make release (scripts/cut_release.py) looks at commits since the last vX.Y.Z tag and infers the bump:

  • major - only with an explicit make release RELEASE_ARGS="--bump major", never inferred
  • minor - any [feat] commit since the last release
  • patch - everything else ([fix], [docs], [chore], ...)

RELEASE_TAG is a separate, opt-in Makefile variable from the always-on immutable sha-<commit> tag - passing it to staging-build/prod-build/ prod-promote pushes/mirrors a second tag (e.g. v2.1.0) alongside the SHA tag on the same image, purely for human/changelog traceability. Terraform still pins deployments by the SHA tag either way.