fix: Docker Scan & Promote never moves latest back to an older commit

Merged
HA
10d ago
+25-1

Summary

Found while working on #317. Docker Scan & Promote copies each finished CI run's sha- images to latest with no ordering check, so the run that finishes last wins even when its commit is older. On 2026-10-22, run 39783092976 promoted sha-5907c4d (#444) at 13:00 UTC, then run 39784413692 moved latest back to sha-b58229c (#445) at 13:09. The nightly release takes whatever latest is, so it would have deployed b58229c and rolled back #444.

Changes

The promote job checks out main and walks the commits after the candidate. When latest already holds the image of one of them, it leaves latest alone and says so in the step summary; the Summary job runs only after a real promote. A concurrency group keeps two promotes from racing between the check and the copy.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • CI/CD or tooling changes

Test Plan

  • Backend unit tests pass (cd backend && uv run pytest tests/unit)
  • Frontend unit tests pass (cd frontend && npm run test)
  • Backend E2E tests pass (docker compose exec -T backend sh -c 'uv sync --group test --no-dev --frozen --no-install-project --no-build && pytest tests/e2e')
  • Frontend E2E tests pass (cd frontend && npm run test:e2e)
  • API spec and client regenerated if routes or schemas changed (./deploy.sh openapi, then ./deploy.sh types), never edited by hand
  • Manual testing performed

Validation: the check replayed with real registry digests skips b58229c while latest is 5907c4d, and promotes 5907c4d over b58229c. A bad SHA stops the step under set -e. actionlint reports the same 14 findings as on main, all in the Summary step.

Checklist

  • My code follows the project's style guidelines
  • I have run pre-commit run --all-files and all checks pass
  • I have added tests that prove my fix/feature works
  • I have updated documentation if needed
  • My changes don't introduce new warnings

Summary by cubic

Fixes Docker Scan & Promote so latest never gets moved back to an older commit. CI runs finish in any order, so the last-finishing run previously won even when its commit was older.

The promote job now checks out main, verifies whether latest already holds the image of any newer commit, and leaves it alone when it does. A concurrency group serializes promotes, and the Summary job runs only after a real promote.