Skip to content

Commit e3db075

Browse files
committed
deploy(helm): couple migrator image tag to the backend tag
Default migrator.image.tag to backendGraphql.image.tag so the migration hook always tracks the app release without a separate per-env pin, and drop the now-redundant tag from the stg/prd overlays. Release does not auto-bump env values; coupling removes a manual step and its drift risk.
1 parent 42e1a7b commit e3db075

6 files changed

Lines changed: 13 additions & 8 deletions

File tree

deploy/charts/klicker-uzh-v3/templates/job-migrate.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ spec:
3434
{{- end }}
3535
containers:
3636
- name: migrate
37-
image: "{{ .Values.migrator.image.repository }}:{{ .Values.migrator.image.tag | default .Chart.AppVersion }}"
37+
# Tag defaults to the backend-graphql image tag so the migrator always
38+
# tracks the app release without a separate per-env pin; falls back to
39+
# the chart appVersion. Only the repository is pinned per env (the `-arm`
40+
# migrator image differs from the backend image).
41+
image: "{{ .Values.migrator.image.repository }}:{{ .Values.migrator.image.tag | default .Values.backendGraphql.image.tag | default .Chart.AppVersion }}"
3842
imagePullPolicy: {{ .Values.migrator.image.pullPolicy }}
3943
# DATABASE_URL comes from the externally-provisioned backend-graphql Secret.
4044
# Only the Secret is referenced (not the app ConfigMaps): a PreSync hook runs

deploy/env-uzh-prd/values.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,8 @@ assessment:
950950
limits:
951951
memory: 200Mi
952952

953-
# Migration hook image: pin to the SAME tag as backend-docker-arm above.
953+
# Migration hook image: only the repo is pinned; the tag auto-tracks the
954+
# backendGraphql image tag above (see chart job-migrate.yaml).
954955
migrator:
955956
image:
956957
repository: ghcr.io/uzh-bf/klicker-uzh/backend-docker-migrator-arm
957-
tag: v3.4.0-alpha.62

deploy/env-uzh-stg/values.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,8 @@ assessment:
899899
cpu: 200m
900900
memory: 200Mi
901901

902-
# Migration hook image: tracks the floating v3 tag alongside backend-docker-arm.
902+
# Migration hook image: only the repo is pinned; the tag auto-tracks the
903+
# backendGraphql image tag above (floating v3 on stg).
903904
migrator:
904905
image:
905906
repository: ghcr.io/uzh-bf/klicker-uzh/backend-docker-migrator-arm
906-
tag: v3

docs/adr/0001-automate-db-migrations-via-argocd-presync-hook.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Run `prisma migrate deploy` as an **ArgoCD-native `PreSync` hook Job** (`deploy/
2121
## Consequences
2222

2323
- Migrations run while the **previous** app version is still live → every migration must be **backward-compatible (expand-contract)**; destructive/renaming changes are split across releases.
24-
- The migrator image tag must be bumped in lockstep with the backend tag per release, and its pinned `prisma` version must track `packages/prisma`. Drift → engine/schema mismatch.
24+
- The migrator image **tag** auto-tracks the backend tag: `job-migrate.yaml` defaults `migrator.image.tag` to `.Values.backendGraphql.image.tag`, so each env pins only the migrator **repository** (`…-migrator-arm`) and never a separate tag. Nothing in the release procedure auto-bumps image tags in `deploy/env-uzh-*/values.yaml` (they are hand-edited), so coupling removes a manual step and the drift it invites.
25+
- The migrator's pinned `prisma` version must still track the `packages/prisma` devDependency. Drift → engine/schema mismatch.
2526
- A failed migration blocks the rollout by design; operators must watch the first releases.
2627
- Adds one image (arm + amd) to build and push per release.

docs/ci-and-deployment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Version bumps are **local and manual** via standard-version: `pnpm run release[:
4545

4646
## Deployment migrations
4747

48-
`prisma migrate deploy` runs automatically as an ArgoCD **`PreSync` hook Job** (`deploy/charts/klicker-uzh-v3/templates/job-migrate.yaml`) before each stg/prd rollout. It runs a dedicated `backend-docker-migrator` image (`packages/prisma/Dockerfile`), CI-built in lockstep with `backend-docker` (`v3_backend-docker-{stg,prd}.yml`), so the migrator tag always matches the app release tag. A failed hook aborts the whole sync, so app Deployments in the main wave never start against an unmigrated DB. The hook uses **ArgoCD-native** annotations (`argocd.argoproj.io/hook: PreSync`), not Helm chart hooks — the two must not be mixed, because a single ArgoCD hook annotation makes ArgoCD ignore _all_ Helm-native hooks on the chart. Full details: [Data & Migrations → Deployment migrations](./data-and-migrations.md#deployment-migrations). Manual `pnpm --filter @klicker-uzh/prisma prisma:deploy:prod` remains a break-glass fallback only.
48+
`prisma migrate deploy` runs automatically as an ArgoCD **`PreSync` hook Job** (`deploy/charts/klicker-uzh-v3/templates/job-migrate.yaml`) before each stg/prd rollout. It runs a dedicated `backend-docker-migrator` image (`packages/prisma/Dockerfile`), CI-built in lockstep with `backend-docker` (`v3_backend-docker-{stg,prd}.yml`); its tag auto-tracks the backend tag (the chart defaults `migrator.image.tag` to `backendGraphql.image.tag`), so it always matches the app release with no separate per-env pin. A failed hook aborts the whole sync, so app Deployments in the main wave never start against an unmigrated DB. The hook uses **ArgoCD-native** annotations (`argocd.argoproj.io/hook: PreSync`), not Helm chart hooks — the two must not be mixed, because a single ArgoCD hook annotation makes ArgoCD ignore _all_ Helm-native hooks on the chart. Full details: [Data & Migrations → Deployment migrations](./data-and-migrations.md#deployment-migrations). Manual `pnpm --filter @klicker-uzh/prisma prisma:deploy:prod` remains a break-glass fallback only.
4949

5050
Why this shape (ArgoCD-native hook, dedicated migrator image, manual demoted to break-glass): [ADR-0001](./adr/0001-automate-db-migrations-via-argocd-presync-hook.md).
5151

docs/data-and-migrations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The Python twin (`apps/analytics/prisma/schema/py.prisma`) uses `prisma-client-p
3535

3636
`prisma migrate deploy` runs **automatically** on every stg/prd rollout as an ArgoCD **`PreSync` hook Job** (`deploy/charts/klicker-uzh-v3/templates/job-migrate.yaml`), not by hand. Mechanics:
3737

38-
- A dedicated migrator image (`packages/prisma/Dockerfile`: `node:24.16.0-alpine` + global `prisma`, carrying the schema + `migrations/`) runs `prisma migrate deploy`. It exists because the backend runtime image installs `--prod --ignore-scripts` and so ships neither the Prisma CLI nor the migration engine. CI builds it as `backend-docker-migrator{-arm,-amd}` in lockstep with `backend-docker` (`v3_backend-docker-{stg,prd}.yml`); keep the migrator tag equal to the backend tag in `deploy/env-uzh-{stg,prd}/values.yaml`.
38+
- A dedicated migrator image (`packages/prisma/Dockerfile`: `node:24.16.0-alpine` + global `prisma`, carrying the schema + `migrations/`) runs `prisma migrate deploy`. It exists because the backend runtime image installs `--prod --ignore-scripts` and so ships neither the Prisma CLI nor the migration engine. CI builds it as `backend-docker-migrator{-arm,-amd}` in lockstep with `backend-docker` (`v3_backend-docker-{stg,prd}.yml`). Its image **tag** auto-tracks the backend tag the chart defaults `migrator.image.tag` to `backendGraphql.image.tag`, so each env pins only the migrator **repository** and never a separate tag.
3939
- The hook draws `DATABASE_URL` from the externally-provisioned `…-secret-backend-graphql` Secret only (a PreSync hook must not depend on Sync-phase ConfigMaps). Toggle with `migrator.enabled`.
4040
- A **failed** hook aborts the whole sync — app Deployments never roll onto an unmigrated DB. The Job runs while the **previous** app version is still live, so migrations must be **backward-compatible (expand-contract)**; a destructive/renaming migration must be split across releases.
4141
- **Break-glass only:** `pnpm --filter @klicker-uzh/prisma prisma:deploy:prod` (Infisical `--env prd`) still applies migrations manually from a workstation. Use it only when the hook is unavailable; `prisma:resolve:prod` resolves a failed/partial migration.

0 commit comments

Comments
 (0)