fix(canon): promote the TESTED release version, not a re-derived latest tag
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Closes the head_version-vs-latest_version divergence: should_promote gates on head_version (code under test) but promote_canonical recorded latest_version(recipe_tags). In a manual RECIPE=<r> run whose main checkout sits on a tag OLDER than the newest published tag, the gate would pass on the older tag yet promote the newer (never-tested) one. promote_canonical now takes the tested `version` (head_version, guaranteed a release tag by the tagged-gate) and records exactly that. Sweep path unaffected (head==tag by construction). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -921,30 +921,36 @@ def should_promote_canonical(
|
||||
return canonical.is_enrolled(recipe) and overall == 0 and not quick and not ref and tagged
|
||||
|
||||
|
||||
def promote_canonical(recipe: str, head_ref: str | None) -> None:
|
||||
"""WC5: (re)seed the canonical at the green-verified LATEST. Deploy `warm-<recipe>` at latest
|
||||
(reattaching the retained canonical volume if one exists — an in-place version bump — else a fresh
|
||||
install), wait healthy, undeploy, snapshot + record the registry (atomic replace of the
|
||||
last-known-good). The OLD known-good is replaced ONLY here, after green (never lost on a red run)."""
|
||||
def promote_canonical(recipe: str, head_ref: str | None, version: str | None) -> None:
|
||||
"""canon §2.A / WC5: (re)seed the canonical at the GREEN-VERIFIED TESTED RELEASE `version` — the
|
||||
exact version under test (head_version), which the should_promote tagged-gate guarantees is a
|
||||
published release tag. Deploy `warm-<recipe>` at that version (reattaching the retained canonical
|
||||
volume if one exists — an in-place version bump — else a fresh install), wait healthy, undeploy,
|
||||
snapshot + record the registry (atomic replace of the last-known-good).
|
||||
|
||||
Promotes EXACTLY the tested version — it no longer re-derives `latest_version(recipe_tags)`, which
|
||||
could differ from the version actually exercised by the run (e.g. a manual `RECIPE=<r>` run whose
|
||||
`main` checkout sits on a tag older than the newest published tag): the canonical must record the
|
||||
version the tier suite proved green, not a never-tested newer tag. The OLD known-good is replaced
|
||||
ONLY here, after green (never lost on a red run)."""
|
||||
import warm_reconcile as wr
|
||||
|
||||
domain = canonical.canonical_domain(recipe)
|
||||
wr.fetch_recipe(recipe)
|
||||
latest = wr.latest_version(wr.recipe_tags(recipe))
|
||||
if not latest:
|
||||
print(f"WC5 promote: no version tags for {recipe} — skip", flush=True)
|
||||
if not version:
|
||||
print(f"WC5 promote: no tested release version for {recipe} — skip", flush=True)
|
||||
return
|
||||
wr.fetch_recipe(recipe) # ensure the release tag is present locally for the pinned checkout
|
||||
meta = meta_mod.load(recipe)
|
||||
# The cold run's deploy-count was already asserted + the countfile removed; don't perturb it.
|
||||
os.environ.pop("CCCI_DEPLOY_COUNT_FILE", None)
|
||||
print(
|
||||
f"\n===== WC5 promote-on-green-cold: (re)seed canonical {recipe} @ {latest} =====",
|
||||
f"\n===== WC5 promote-on-green-cold: (re)seed canonical {recipe} @ {version} =====",
|
||||
flush=True,
|
||||
)
|
||||
lifecycle.deploy_app(
|
||||
recipe,
|
||||
domain,
|
||||
version=latest,
|
||||
version=version,
|
||||
secrets=True,
|
||||
deploy_timeout=int(meta.DEPLOY_TIMEOUT),
|
||||
meta=meta,
|
||||
@ -958,9 +964,9 @@ def promote_canonical(recipe: str, head_ref: str | None) -> None:
|
||||
)
|
||||
abra.undeploy(domain)
|
||||
_wait_undeployed(domain)
|
||||
canonical.seed_canonical(recipe, latest, commit=head_ref)
|
||||
canonical.seed_canonical(recipe, version, commit=head_ref)
|
||||
print(
|
||||
f"WC5 promote: canonical {recipe} advanced to known-good {latest} (idle, volume retained)",
|
||||
f"WC5 promote: canonical {recipe} advanced to known-good {version} (idle, volume retained)",
|
||||
flush=True,
|
||||
)
|
||||
|
||||
@ -1494,7 +1500,7 @@ def main() -> int:
|
||||
tagged = warm_reconcile.is_released_version(recipe, head_version)
|
||||
if should_promote_canonical(recipe, ref, overall, quick=False, tagged=tagged):
|
||||
try:
|
||||
promote_canonical(recipe, head_ref)
|
||||
promote_canonical(recipe, head_ref, head_version)
|
||||
except Exception as e: # noqa: BLE001 — promote is a post-green bonus; never fail a green run
|
||||
print(
|
||||
f"!! WC5 promote failed (non-fatal; known-good unchanged): {_scrub(str(e))}",
|
||||
|
||||
Reference in New Issue
Block a user