mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-25 19:54:15 +00:00
test/e2e: only reset the DB when moving backward through the stack
Migrations are forward-only and the appview applies whatever is missing on boot, so moving to the next batch does not need a reset at all — Air rebuilds into the new code and the live DB migrates in place. Verified moving onto val/04-oauth: 0031 appeared in schema_migrations on its own, on top of a level-27 database, with the appview healthy afterwards. That matters more than it sounds. ui.db holds the OAuth sessions and the appview's signing keys, so the old wipe-on-every-switch cost an interactive `docker-credential-atcr login` per batch, which is most of what made the stack awkward to hand to an agent. Validating in stack order is all forward motion, so in the normal case there is now no login at all. A reset is still done when the live DB carries migrations the branch's code has never heard of, which is what going backward means, and the per-set snapshot is still banked so that case can restore rather than start empty. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c1604b9a04
commit
724e22a978
+37
-20
@@ -53,16 +53,16 @@ else
|
||||
git restore --staged docker-compose.yml
|
||||
fi
|
||||
|
||||
# The appview DB only has to match the branch's MIGRATION LEVEL, not the
|
||||
# branch. Across the whole stack there are five distinct levels (27 for batches
|
||||
# 00-08, 28 for 09-11, 29 for 12-13, 32 for 14, 34 for 15), so a per-level
|
||||
# snapshot is reused instead of re-migrating from empty every time.
|
||||
# Resetting the DB matters because ui.db holds the OAuth sessions AND the
|
||||
# appview's oauth_p256/jwt_rsa keys, so wiping it logs out the registry
|
||||
# credential helper and costs an interactive `docker-credential-atcr login`.
|
||||
#
|
||||
# Going FORWARD (the normal case — batches are validated in stack order) needs
|
||||
# no reset at all: migrations are forward-only and the appview applies whatever
|
||||
# is missing on boot, so Air rebuilding into the next branch migrates the live
|
||||
# DB in place and the session survives. Only going BACKWARD needs a reset, since
|
||||
# the DB then carries migrations the branch's code has never heard of.
|
||||
#
|
||||
# This matters because ui.db holds the OAuth sessions AND the appview's
|
||||
# oauth_p256/jwt_rsa keys. Nuking it logs out the registry credential helper, so
|
||||
# a naive wipe-per-switch costs an interactive `docker-credential-atcr login` on
|
||||
# every batch. Restoring a snapshot keeps the session alive across every batch
|
||||
# that shares a level.
|
||||
# Key the snapshot on the FULL SET of migrations present, not the highest one.
|
||||
# Batching reorders migrations: val/04 carries e75b2e2, whose migration is 0031,
|
||||
# while 0028-0030 arrive later in batches 09, 12 and 14. So val/04 holds
|
||||
@@ -77,21 +77,38 @@ FINGERPRINT=$(printf '%s\n' "$MIGS" | md5sum | cut -c1-8)
|
||||
SNAP="$SNAPDIR/ui.level-${LEVEL}-${FINGERPRINT}.db"
|
||||
echo "==> branch migrations: max ${LEVEL}, set ${FINGERPRINT} ($(printf '%s\n' "$MIGS" | wc -l) files)"
|
||||
|
||||
echo "==> tearing down appview"
|
||||
docker compose rm -sf atcr-appview
|
||||
# Which migrations does the live DB already carry that this branch does not know?
|
||||
APPLIED=$(docker exec atcr-appview sh -c \
|
||||
'sqlite3 /var/lib/atcr/ui.db "select version from schema_migrations"' 2>/dev/null || true)
|
||||
EXTRA=$(python3 -c '
|
||||
import sys
|
||||
applied = {v.strip().lstrip("0") or "0" for v in sys.argv[1].split() if v.strip()}
|
||||
branch = {v.strip().lstrip("0") or "0" for v in sys.argv[2].split() if v.strip()}
|
||||
print(" ".join(sorted(applied - branch, key=int)))
|
||||
' "$APPLIED" "$MIGS" 2>/dev/null || echo "")
|
||||
|
||||
if [ -f "$SNAP" ]; then
|
||||
echo "==> restoring DB snapshot for level ${LEVEL} (keeps OAuth sessions alive)"
|
||||
docker run --rm -v "${UI_VOLUME}:/v" -v "$SNAPDIR:/s:ro" alpine sh -c \
|
||||
'rm -f /v/ui.db /v/ui.db-wal /v/ui.db-shm && cp /s/'"$(basename "$SNAP")"' /v/ui.db'
|
||||
if [ -z "$APPLIED" ]; then
|
||||
echo "==> no live DB; starting fresh"
|
||||
docker compose rm -sf atcr-appview
|
||||
docker volume rm "$UI_VOLUME" 2>/dev/null || true
|
||||
docker compose up -d atcr-appview
|
||||
elif [ -z "$EXTRA" ]; then
|
||||
echo "==> moving forward; leaving the DB alone (Air migrates it in place, session survives)"
|
||||
docker compose up -d atcr-appview >/dev/null 2>&1 || true
|
||||
else
|
||||
echo "==> no snapshot for level ${LEVEL}; starting from an empty DB"
|
||||
docker volume rm "$UI_VOLUME" 2>/dev/null || echo " (volume already gone)"
|
||||
echo "==> moving BACKWARD; the DB carries migrations this branch lacks: ${EXTRA}"
|
||||
docker compose rm -sf atcr-appview
|
||||
if [ -f "$SNAP" ]; then
|
||||
echo " restoring snapshot ${LEVEL}-${FINGERPRINT} (keeps OAuth sessions alive)"
|
||||
docker run --rm -v "${UI_VOLUME}:/v" -v "$SNAPDIR:/s:ro" alpine sh -c \
|
||||
'rm -f /v/ui.db /v/ui.db-wal /v/ui.db-shm && cp /s/'"$(basename "$SNAP")"' /v/ui.db'
|
||||
else
|
||||
echo " no snapshot for this migration set; starting from an empty DB (expect a re-login)"
|
||||
docker volume rm "$UI_VOLUME" 2>/dev/null || true
|
||||
fi
|
||||
docker compose up -d atcr-appview
|
||||
fi
|
||||
|
||||
echo "==> starting appview"
|
||||
docker compose up -d atcr-appview
|
||||
|
||||
echo "==> waiting for appview to answer on 127.0.0.1:5000"
|
||||
for i in $(seq 1 90); do
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:5000/v2/ || true)
|
||||
|
||||
Reference in New Issue
Block a user