fix: restore trending scout tag after Docker prune - #109
Conversation
protostatis
left a comment
There was a problem hiding this comment.
Sky's Code Review
This patch fixes a real production bug: Docker prune removes the mutable :latest-style tag on the hourly trending-scout image even though the pin container retains the image ID. The fix splits the old verify_trending_scout_pin into an assert_trending_scout_pin helper (pin-container existence/state checks) and adds restore_trending_scout_tag, which re-tags the mutable image reference from the pinned immutable image ID. It then calls restore-before-verify after both the system prune and the post-deploy image prune. The refactor is logically sound: assert is idempotent and cheap, restore tags by ID (correct), and verify subsequently confirms the tag resolves to the protected ID. The regression test additions correctly assert the restore-before-verify ordering at both prune points. No security or production-breaking issues found; only minor style/robustness nits remain (redundant double-assert, unguarded docker tag, and a :latest/tag-pinning tension worth a clarifying comment).
Verdict: Comment
Comments
- The refactor cleanly separates concerns: assert (pin container validity) from verify (tag resolution). This is a good structure and makes the restore-before-verify ordering explicit and testable.
- Confirm
set -e(orset -euo pipefail) is active at the top of release.sh; the newrestore_trending_scout_tagrelies ondocker tagfailing loudly underset -e. Ifset -eis not present, the unguardeddocker tagbecomes a silent no-op failure that only surfaces inside verify's generic error.
Reviewed by Sky — Unchained Sky engineering agent
| fi | ||
| } | ||
|
|
||
| restore_trending_scout_tag() { |
There was a problem hiding this comment.
restore_trending_scout_tag calls assert_trending_scout_pin, and then verify_trending_scout_pin re-runs the same assert immediately after. This double-assert is harmless but slightly redundant; consider documenting why both are needed (restore needs the pin valid before re-tagging, verify confirms the end state). Alternatively keep it — the cheap re-check is defensible for safety.
| # Docker prune can remove a mutable tag even while the pin retains its image | ||
| # ID. Recreate the cron's tag from that protected immutable reference. | ||
| assert_trending_scout_pin | ||
| docker tag "$TRENDING_SCOUT_IMAGE_ID" "$TRENDING_SCOUT_IMAGE" |
There was a problem hiding this comment.
docker tag "$TRENDING_SCOUT_IMAGE_ID" "$TRENDING_SCOUT_IMAGE" is not guarded by || exit 1. A failed tag would be caught by the subsequent verify_trending_scout_pin, but consider adding an explicit error message here (mirroring the other ERROR blocks) so the failure mode is self-describing rather than surfacing as a generic 'tag does not resolve' later.
| # Docker prune can remove a mutable tag even while the pin retains its image | ||
| # ID. Recreate the cron's tag from that protected immutable reference. | ||
| assert_trending_scout_pin | ||
| docker tag "$TRENDING_SCOUT_IMAGE_ID" "$TRENDING_SCOUT_IMAGE" |
There was a problem hiding this comment.
Since the whole bug stems from a mutable tag being pruned, consider whether the cron should reference the immutable ID (or a distinct pinned tag) directly instead of relying on re-tagging after every prune. Re-tagging is a valid fix, but a short comment explaining why the mutable tag must be preserved (cron scheduler resolution) would help future maintainers avoid regressing this.
| assert "--label panicradar.role=trending-scout-image-pin" not in release_script | ||
| assert 'docker inspect --format \'{{.Image}}\' "$TRENDING_SCOUT_PIN_NAME"' in release_script | ||
| assert 'docker tag "$TRENDING_SCOUT_IMAGE_ID" "$TRENDING_SCOUT_IMAGE"' in release_script | ||
| assert "Trending scout pin container is missing" in release_script |
There was a problem hiding this comment.
The new assertion checks for the exact docker tag "$TRENDING_SCOUT_IMAGE_ID" "$TRENDING_SCOUT_IMAGE" string but does not assert it appears before the verify/tag-resolution logic in any ordering sense — that is only covered for the prune points below. Minor: this string-match is sufficient for now, but a dedicated unit test for restore_trending_scout_tag (e.g., asserting it calls assert before docker tag) would tighten coverage.
Summary
Incident context
The v1.37.2 deployment confirmed that Docker prune can remove
:latesteven while the pin retains the image ID. The release failed safely before replacing application containers; this patch recreates the tag from the pin immediately after each prune.Validation
./.venv/bin/pytest tests/test_deploy_workflow.py./.venv/bin/ruff check tests/test_deploy_workflow.pygit diff --checkbash -n deploy/release.sh