fix(2): recipe_checkout force (-f) — fixes mumble upgrade-tier checkout collision with cc-ci overlay

git checkout <head_ref> aborted on the untracked install_steps-provided compose.host-ports.yml (which
head_ref tracks). Force-checkout yields the exact ref tree. Also fixes the mumble restore tier: backup
labels exist only in 1.0.0+, so backup/restore are meaningful only after the (now-working) upgrade moves
the app to head_ref. DECISIONS.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 20:03:41 +01:00
parent 191fa774ec
commit 1890cb58f3
2 changed files with 20 additions and 1 deletions

View File

@ -888,3 +888,16 @@ HTTP-readiness + on-host (cc-ci-run) test model, deploy it with the two upstream
file the recipe's backupbot hooks `.backup`/restore). ops.py seeds a `ci_marker` row there (using
`PRAGMA busy_timeout` to wait out the running murmur server's transient sqlite locks), backup, drop,
restore, assert the row survived.
## mumble (cont.): recipe_checkout uses `git checkout -f` + backup labels are 1.0.0+ only (2026-05-29)
Two follow-on fixes from the first full mumble run:
- **`abra.recipe_checkout` now force-checks-out (`-f`)**: the upgrade tier's `git checkout <head_ref>`
aborted ("untracked working tree files would be overwritten") because install_steps left an UNTRACKED
`compose.host-ports.yml` in the 0.2.0 base checkout that collides with the same path TRACKED in
head_ref (1.0.0+). The version-pinning checkout must yield the exact ref tree; force is correct and
robust to cc-ci-provided overlays. (General harness fix; benefits any recipe with a cc-ci overlay.)
- **mumble's backupbot labels exist only from version 1.0.0+** (0.2.0 has none — "Backups introduced"
was the 1.0.0 release). So backup/restore are only meaningful AFTER the upgrade tier moves the app to
head_ref (1.0.0+). With the upgrade fixed, backup/restore run against the backup-aware version and P4
(sqlite ci_marker survival) holds. The base (0.2.0) backup-unaware state is expected, not a defect.

View File

@ -80,7 +80,13 @@ def recipe_checkout(recipe: str, version: str) -> None:
import os
path = os.path.expanduser(f"~/.abra/recipes/{recipe}")
subprocess.run(["git", "-C", path, "checkout", "--quiet", version], check=True)
# -f (force): the version-pinning checkout must yield the EXACT ref tree. Without it, a cc-ci
# install_steps-provided overlay (e.g. mumble's compose.host-ports.yml, copied into a version that
# predates it) is an UNTRACKED file that collides with the same path TRACKED in a later ref, and
# `git checkout <ref>` aborts ("untracked working tree files would be overwritten"). Force resolves
# it by writing the ref's tracked version. Safe: we never want local recipe-tree state preserved
# across a version switch (and chaos deploys re-provide the overlay via install_steps when needed).
subprocess.run(["git", "-C", path, "checkout", "-f", "--quiet", version], check=True)
def has_lightweight_version_tags(recipe: str) -> bool: