fix(playbooks): compare image IDs, not the created-from tag; make the repin idempotent
Two defects the worldtree-pinned case exposed in the guard written an hour ago. 1. The guard compared the container's .Config.Image STRING against the tag being pinned. That string is only the tag the container was CREATED from, which can differ from what it actually runs: worldtree-pinned was created from `:latest` back when that tag pointed at 446e5807, and `:latest` has since moved to b19afd71d7cc. So the guard refused an instance whose pinning was correct and necessary. Now it resolves the target tag to an image ID and compares that against the running image ID -- asserting the thing actually cared about, that this tag names the bytes now running. It also fails closed when no such local tag exists. 2. The sed step reported CHANGED unconditionally, so a re-run on an already-pinned instance claimed work it had not done. Gated behind a `when:` that skips when the line is already correct; a second run on demo now reports "2 ok, 0 changed, 2 skipped / overall: OK". Applied to worldtree-pinned under worldtree-dev authorization. That instance needed a `docker tag` first -- its image was DANGLING (no repo tags, kept alive only by the running container), so the fleet's frozen reference was one `docker rm` from garbage collection. Tagged as :446e5807bf43, then pinned. All three instances now render a SHA with no floating tag anywhere: worldtree -> :ae88a057c0ed worldtree-personal -> :f63529168c13 worldtree-pinned -> :446e5807bf43 Nothing restarted -- pinned still Up 3 months, its start time unchanged.
This commit is contained in:
@@ -46,16 +46,27 @@ steps:
|
|||||||
shell: test -n "{{ expect_sha }}"
|
shell: test -n "{{ expect_sha }}"
|
||||||
changed_when: "false"
|
changed_when: "false"
|
||||||
|
|
||||||
- name: Confirm the container is actually running the SHA we are about to pin
|
- name: Confirm the tag we are about to pin resolves to the running image
|
||||||
# Guards against a deploy landing between the operator reading the SHA
|
# Guards against a deploy landing between reading the SHA and writing it —
|
||||||
# and this playbook writing it — pinning a SHA that is NOT running would
|
# pinning a SHA that is NOT running would arm the exact hazard we are
|
||||||
# arm the exact hazard we are disarming, just with a different image.
|
# disarming, just with a different image.
|
||||||
|
#
|
||||||
|
# Compares IMAGE IDs, not the container's .Config.Image string. The string
|
||||||
|
# is only the tag the container was CREATED from, which can differ from
|
||||||
|
# what it actually runs: worldtree-pinned was created from `:latest` back
|
||||||
|
# when that tag pointed at 446e5807, and `:latest` has since moved. A
|
||||||
|
# string compare rejects that instance even though pinning it is correct;
|
||||||
|
# an ID compare asserts the thing we actually care about — that this tag
|
||||||
|
# names the bytes currently running.
|
||||||
shell: |
|
shell: |
|
||||||
running=$(docker inspect {{ api_container }} --format '{{.Config.Image}}')
|
running=$(docker inspect {{ api_container }} --format '{{.Image}}')
|
||||||
test "$running" = "{{ registry }}:{{ expect_sha }}" || {
|
tagged=$(docker image inspect {{ registry }}:{{ expect_sha }} --format '{{.Id}}' 2>/dev/null) || {
|
||||||
echo "REFUSING: {{ api_container }} runs $running, not {{ registry }}:{{ expect_sha }}"
|
echo "REFUSING: no local image tagged {{ registry }}:{{ expect_sha }} — tag it first"
|
||||||
exit 1; }
|
exit 1; }
|
||||||
echo "confirmed: $running"
|
test "$running" = "$tagged" || {
|
||||||
|
echo "REFUSING: {{ api_container }} runs $running but {{ registry }}:{{ expect_sha }} is $tagged"
|
||||||
|
exit 1; }
|
||||||
|
echo "confirmed: {{ registry }}:{{ expect_sha }} == running image $running"
|
||||||
changed_when: "false"
|
changed_when: "false"
|
||||||
|
|
||||||
- name: Back up .env
|
- name: Back up .env
|
||||||
@@ -65,6 +76,10 @@ steps:
|
|||||||
|
|
||||||
- name: Re-pin WORLDTREE_IMAGE to the running SHA
|
- name: Re-pin WORLDTREE_IMAGE to the running SHA
|
||||||
sudo: true
|
sudo: true
|
||||||
|
# Skipped when already correct, so a re-run reports OK rather than a
|
||||||
|
# phantom CHANGED — a playbook that always claims to have changed
|
||||||
|
# something trains you to stop reading the summary.
|
||||||
|
when: "! sudo grep -q '^WORLDTREE_IMAGE={{ registry }}:{{ expect_sha }}$' {{ instance_dir }}/.env"
|
||||||
# `|` delimiter because the image reference contains slashes.
|
# `|` delimiter because the image reference contains slashes.
|
||||||
shell: |
|
shell: |
|
||||||
grep -q '^WORLDTREE_IMAGE=' {{ instance_dir }}/.env || {
|
grep -q '^WORLDTREE_IMAGE=' {{ instance_dir }}/.env || {
|
||||||
|
|||||||
Reference in New Issue
Block a user