diff --git a/docs/deployment.md b/docs/deployment.md index 90bd5904..1b2c7c60 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -41,9 +41,19 @@ cd pediatric-ai-scribe-v3 cp .env.example .env # edit .env — required: APP_URL, JWT_SECRET, DATA_ENCRYPTION_KEY, DB_PASSWORD, an AI provider ./scripts/build-image.sh +sed -i "s|^PED_AI_IMAGE=.*|PED_AI_IMAGE=ped-ai-local:$(git rev-parse HEAD)|" .env docker compose up -d --no-build +curl -fsS http://127.0.0.1:3552/api/build # must equal `git rev-parse HEAD` ``` +**Building does not change what `up` starts.** `docker compose` takes the image +from `PED_AI_IMAGE` in `.env`, and `build-image.sh` deliberately does not move +that pin — naming a revision is also how a rollback is done. A pin left from an +earlier deploy therefore starts the older image, and nothing short of +`/api/build` shows it: the build succeeds, `up` reports the container started, +and `/api/health` returns `{ok:true}` from the wrong revision. `build-image.sh` +warns when the pin does not match what it just built. + The build uses Node 24 LTS and `npm ci --omit=dev` from the root lockfile. `./scripts/build-image.sh` resolves the full checkout Git commit (including worktrees/packed refs) and passes `GIT_REVISION` through Compose. It only builds; diff --git a/docs/developer-guide.md b/docs/developer-guide.md index 0045493e..6677618f 100644 --- a/docs/developer-guide.md +++ b/docs/developer-guide.md @@ -451,14 +451,31 @@ If a dynamic value enters an HTML string, escape it at the point of insertion. I ## Deployment checks -After deployment: +After deployment, check *which revision* is running, not only that something is: ```bash +curl -fsS http://127.0.0.1:3552/api/build # must equal `git rev-parse HEAD` curl -fsS http://127.0.0.1:3552/api/health docker compose ps pediatric-scribe ``` -If the browser still shows old frontend behavior, force-refresh or check the injected `BUILD_ID` asset query string. +`/api/health` passing proves a container is up, not that it is the one you +built. `docker compose up` starts whatever `PED_AI_IMAGE` in `.env` names, and +that pin does not move when you build — so a pin left from an earlier deploy +silently starts the older image, and every signal short of `/api/build` looks +fine. `scripts/build-image.sh` warns when the pin does not match the revision it +just built; the fix is to update the pin: + +```bash +sed -i "s|^PED_AI_IMAGE=.*|PED_AI_IMAGE=ped-ai-local:$(git rev-parse HEAD)|" .env +docker compose up -d --no-build +``` + +The pin is not updated for you, because naming a revision is also how a +deliberate rollback is done. + +If the browser still shows old frontend behavior after the revision checks out, +force-refresh or check the injected `BUILD_ID` asset query string. ## Documentation expectations diff --git a/scripts/build-image.sh b/scripts/build-image.sh index 29cee869..1239ba50 100755 --- a/scripts/build-image.sh +++ b/scripts/build-image.sh @@ -37,3 +37,33 @@ if [ "$GIT_REVISION" != unknown ]; then else echo 'Built ped-ai-local:latest with no recorded revision' >&2 fi + +# A deploy runs `docker compose up`, which reads PED_AI_IMAGE from .env — not +# the tag just built. A pin left behind from an earlier deploy therefore starts +# that older image, and `up` reports success either way: the build looks done, +# the health check passes, and the running app is silently an older revision. +# That has already cost a session — it rolled the app back far enough to remove +# a feature, and the missing feature was read as a new bug. +# +# Not corrected automatically: the pin is how a deploy names a revision on +# purpose, including a deliberate rollback. Said loudly instead. +if [ "$GIT_REVISION" != unknown ] && [ -f .env ]; then + PINNED=$(sed -n 's/^PED_AI_IMAGE=//p' .env | tail -1) + case "$PINNED" in + '') ;; + *"$GIT_REVISION") ;; + *) + echo >&2 + echo "WARNING: .env pins PED_AI_IMAGE=$PINNED" >&2 + echo " which is NOT the image just built." >&2 + echo " 'docker compose up -d --no-build' will start the pinned image," >&2 + echo " not this build. To deploy what was just built:" >&2 + echo >&2 + echo " sed -i 's|^PED_AI_IMAGE=.*|PED_AI_IMAGE=ped-ai-local:$GIT_REVISION|' .env" >&2 + echo >&2 + echo " Then confirm after starting it:" >&2 + echo " curl -fsS http://127.0.0.1:3552/api/build" >&2 + echo >&2 + ;; + esac +fi