From 2e3fe13b391560f7db8e910320fc2d368fda52d7 Mon Sep 17 00:00:00 2001 From: Ryan Westfall Date: Sun, 9 Aug 2026 04:36:51 -0700 Subject: [PATCH] Build profile-gated services so workers do not run stale images (#19) ## Summary The django deploy sets `COMPOSE_PROFILES` on the **start** step but not on the **build** step, so `docker compose build` skips profile-gated services. `up -d` then reuses whatever image already exists and the container silently keeps running old code. This adds `COMPOSE_PROFILES` to the build step so it matches the start step. Only affects hosts that set `host_apps.compose_profiles` (today: the `monica_site` dj-queue worker on adama). ## Symptom this fixes On adama the beta worker image was 20 hours stale while web was current: | Image | Built | Postgres driver | |---|---|---| | `monica_site_beta-web` | today | psycopg 3.3.4 | | `monica_site_beta-worker` | Aug 8 | psycopg2 2.9.12 | So the worker crash-looped on LISTEN/NOTIFY (`TypeError: 'list' object is not callable` in `dj_queue/runtime/notify.py`) long after `monica_site` had moved to psycopg3, because its image was never rebuilt. Branch is merged up with `master`, which already carries the worker auto-start from [#18](https://git.aimloperations.com/ai_ml_operations/server-infra/pulls/18); the diff here is just the build step. ## Test plan - [x] Manual `COMPOSE_PROFILES=worker docker compose build worker` on adama produced an image with psycopg 3.3.4 and the notify errors stopped. - [ ] Beta deploy from this branch recreates the worker with a fresh image, no manual rebuild. - [ ] Hosts without `compose_profiles` (roslin, ai-server-4080) still build/start web only.Reviewed-on: https://git.aimloperations.com/ai_ml_operations/server-infra/pulls/19 --- roles/app-deploy/tasks/django.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/app-deploy/tasks/django.yml b/roles/app-deploy/tasks/django.yml index 684bd19..24b3248 100644 --- a/roles/app-deploy/tasks/django.yml +++ b/roles/app-deploy/tasks/django.yml @@ -65,6 +65,8 @@ group: "{{ admin_user }}" mode: "0600" +# COMPOSE_PROFILES must match the start step below: without it, profile-gated +# services (e.g. the dj-queue worker) are skipped here and keep a stale image. - name: "django[{{ _project }}] build images" ansible.builtin.command: cmd: "docker compose -f {{ _spec.compose_file }} --env-file .env build" @@ -72,6 +74,7 @@ environment: COMPOSE_PROJECT_NAME: "{{ _project }}" WEB_PORT: "{{ app_item.port }}" + COMPOSE_PROFILES: "{{ (app_item.compose_profiles | default([])) | join(',') }}" become: true become_user: "{{ admin_user }}" changed_when: true