|
| 1 | +# Container image tagging |
| 2 | + |
| 3 | +Every successful CI deploy publishes one or more tags to the relevant |
| 4 | +ECR repository (`kcprofiles` / `kcprofiles-dev`, |
| 5 | +`kcprofiles-traefik` / `kcprofiles-traefik-dev`, and `kcprofiles-monitor` |
| 6 | +on `main`). This document describes which tags are pushed when, what |
| 7 | +each one means, and how to use them to roll back in an emergency. |
| 8 | + |
| 9 | +## Tags pushed on every deploy |
| 10 | + |
| 11 | +| Tag | Mutability | Pushed on | Purpose | |
| 12 | +| ------------------------- | ---------- | ----------- | ------------------------------------ | |
| 13 | +| `<git_sha>` | Immutable | main, dev | Exact commit identity (40-char SHA). | |
| 14 | +| `v<version>-<sha7>` | Immutable | main, dev | Human-readable, version-anchored, unique per build. **Use this for rollback names.** | |
| 15 | +| `v<version>` | Mutable | main only | Pointer to the latest build of a given release. | |
| 16 | +| `latest` | Mutable | main, dev | Pointer to the most recent build on the branch. | |
| 17 | + |
| 18 | +`<version>` is read from the `[project]` table of `pyproject.toml` at |
| 19 | +build time. `<sha7>` is the first 7 characters of the commit SHA. |
| 20 | + |
| 21 | +## Why the `-<sha7>` suffix? |
| 22 | + |
| 23 | +Disambiguation. On `dev`, commitizen never bumps the version (the |
| 24 | +`Bump version` workflow only runs on pushes to `main`), so every dev |
| 25 | +deploy would otherwise compete for the same `v<version>` tag and the |
| 26 | +previous build would be untaggable by name. Appending the short SHA |
| 27 | +gives every build its own immutable, version-anchored handle. |
| 28 | + |
| 29 | +On `main` the same suffix is still pushed for two reasons: |
| 30 | + |
| 31 | +1. Between a feature merge and the commitizen bump that follows, two |
| 32 | + commits can deploy with the same `v<version>` value, so the suffix |
| 33 | + keeps each build addressable. |
| 34 | +2. Symmetry: rollback procedures are the same on both environments. |
| 35 | + |
| 36 | +## Why `v<version>` is `main`-only |
| 37 | + |
| 38 | +`main` runs commitizen on every push and guarantees a fresh version per |
| 39 | +release, so `v<version>` is a stable name for "the build that |
| 40 | +corresponds to release X.Y.Z." On `dev` the same tag would change |
| 41 | +meaning every push, which is misleading — so we don't publish it there. |
| 42 | + |
| 43 | +## Example |
| 44 | + |
| 45 | +For commit `1cd0a566` deployed on `dev` while `pyproject.toml` has |
| 46 | +`version = "4.36.1"`, the dev ECR repository receives: |
| 47 | + |
| 48 | +- `kcprofiles-dev:1cd0a566fa...` (full SHA) |
| 49 | +- `kcprofiles-dev:v4.36.1-1cd0a56` |
| 50 | +- `kcprofiles-dev:latest` |
| 51 | + |
| 52 | +The same commit, if it were on `main`, would additionally produce: |
| 53 | + |
| 54 | +- `kcprofiles:v4.36.1` |
| 55 | + |
| 56 | +## Rolling back |
| 57 | + |
| 58 | +In an emergency, prefer the immutable, named tag: |
| 59 | + |
| 60 | +```bash |
| 61 | +aws ecs update-service \ |
| 62 | + --cluster kcprofiles \ |
| 63 | + --service kcprofiles-blue \ |
| 64 | + --task-definition $(aws ecs register-task-definition \ |
| 65 | + --family kcprofiles \ |
| 66 | + --container-definitions '[{"name":"django","image":"<account>.dkr.ecr.us-east-1.amazonaws.com/kcprofiles:v4.36.1-1cd0a56", ...}]' \ |
| 67 | + --query 'taskDefinition.taskDefinitionArn' --output text) \ |
| 68 | + --force-new-deployment |
| 69 | +``` |
| 70 | + |
| 71 | +In practice this is done by editing the task definition in the AWS |
| 72 | +console to point at the desired `v<version>-<sha7>` tag and then |
| 73 | +forcing a new deployment. |
| 74 | + |
| 75 | +If you only need to roll the current release back to its previous build |
| 76 | +on `main`, the plain `v<version>` tag is the simplest shorthand, but |
| 77 | +remember it tracks the **latest** build of that version — once a newer |
| 78 | +build is published it moves forward. |
| 79 | + |
| 80 | +## Where the tagging is configured |
| 81 | + |
| 82 | +`.github/workflows/ci.yml`, in the `deploy` job. The `Extract project |
| 83 | +version` step reads `pyproject.toml` via `tomllib`; subsequent build |
| 84 | +and push steps consume `steps.project_version.outputs.version` |
| 85 | +(`v<version>`) and `.build` (`v<version>-<sha7>`). |
0 commit comments