Files
cc-ci/machine-docs/STATUS-samever.md
autonomic-bot c5a0d204c1
All checks were successful
continuous-integration/drone/push Build is passing
claim(M1): samever resolver step-back implemented + unit-tested (13 pass)
WHAT/HOW/EXPECTED/WHERE in STATUS-samever.md. Adversary: cold pytest
tests/unit/test_upgrade_base.py → 13 passed; canonical==head steps back to a
strictly-older base, canonical!=head unchanged, no-older→declared skip.
2026-06-17 04:25:16 +00:00

80 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# STATUS — phase `samever` (step-back to older base when canonical == head version)
SSOT: `/srv/cc-ci/cc-ci-plan/plan-phase-samever-older-base-fallback.md`.
State files: this + BACKLOG-samever.md, REVIEW-samever.md (Adversary), JOURNAL-samever.md. DECISIONS.md shared.
## Phase
Started 2026-06-17. Gates: **M1** (implemented + unit-tested), **M2** (proven in real CI).
## Current status
**Gate: M1 CLAIMED, awaiting Adversary** @2026-06-17T04:24Z
## M1 — WHAT is claimed
`resolve_upgrade_base` now reads the head's published version and steps back to a genuinely older
published base when the last-green warm-canonical version equals the head version — never a
same-version no-op, never a needless skip when an older base exists.
Resolution chain (override / EXPECTED_NA / upgrade∉stages short-circuits unchanged):
1. explicit `UPGRADE_BASE_VERSION` override → unchanged.
2. last-green canonical **IF its version ≠ head version**`kind="version"` (canonical), unchanged from prevb.
3. last-green canonical **== head version** → **step back**: `newest published version strictly older
than head` → `kind="version"` (the older tag). Reason starts `"step-back: …"`.
4. canonical == head **and no older published tag** → `kind="skip"`, reason
`"base == head (<v>) and no older published predecessor"`.
5. no canonical → main-tip ref / skip paths unchanged.
`head_version is None` (compose unreadable) → comparison is False → canonical stays primary (prevb behavior).
## M1 — WHERE (commit + paths)
- Implementation commit: **b29bb3f** (feat(samever): …), on `main`.
- `runner/run_recipe_ci.py` — `resolve_upgrade_base(..., head_version=None)` new chain (canonical
block ~lines 147180); call site `main()` reads `head_version = abra.head_compose_version(recipe)`
(~line 1023) and passes it.
- `runner/harness/abra.py` — `head_compose_version(recipe)` (regex `coop-cloud\.[^.\s]*\.version=([^\s"']+)`
over the head checkout's `compose.yml`; matches quoted + unquoted labels; does NOT match `.chaos-version`).
- `runner/warm_reconcile.py` — `version_key(tag)` (lifted from sort_versions; single ordering source)
+ `newest_older_version(tags, version)` (newest tag with `version_key < target`; None if none / version None).
- `tests/unit/test_upgrade_base.py` — 5 new tests (13 total).
## M1 — HOW to verify (cold, from a clean clone)
1. Unit suite (the gate):
```
nix shell nixpkgs#python311Packages.pytest -c pytest tests/unit/test_upgrade_base.py -v
```
**EXPECTED: 13 passed.** New tests:
- `test_canonical_equals_head_steps_back_to_newest_older` — canonical==head==`10.8.0+26.6.3`,
tags `[10.6.0+26.5.0, 10.8.0+26.6.3, 10.7.1+26.6.2, 10.7.0+26.6.0, not-a-version]` →
`plan.version == "10.7.1+26.6.2"` (strictly older; asserts `version_key(plan.version) < version_key(head)`),
`kind=="version"`, reason contains `"step-back"`. main never consulted.
- `test_canonical_differs_from_head_uses_canonical_unchanged` — canonical `10.7.1+26.6.2` ≠ head
`10.8.0+26.6.3` → `version==10.7.1+26.6.2`, reason `"last-green"`; recipe_tags NOT consulted.
- `test_canonical_equals_head_no_older_published_skips` — canonical==head==`1.0.0+3.5.3`, tags
`[1.0.0+3.5.3]` only → `kind=="skip"`, reason contains `"no older published predecessor"`.
- `test_no_head_version_preserves_canonical_primary` — head_version omitted → canonical primary, no step-back.
- `test_newest_older_version_ordering` — ordering helper picks correct strictly-older tag, excludes equal, None-safe.
The 8 prior tests (override / EXPECTED_NA / main-tip / head==main-tip skip / no-predecessor skip /
other-rung) are UNCHANGED and still pass — proving override/ref/skip paths untouched.
2. Teeth (canonical==head MUST NOT yield a same-version base): in
`test_canonical_equals_head_steps_back_to_newest_older`, `plan.version != head_version` and the
`version_key(plan.version) < version_key(head)` assertion fails loudly if the resolver ever returns
the same version or a newer one.
3. Compose-label parse (the head-version reader): the regex extracts `10.8.0+26.6.3` from a quoted
label and `3.5.3+1.24.2-rootless` from an unquoted one, and returns no match for a `.chaos-version`
label (verified — see JOURNAL). Real labels confirmed on cc-ci: keycloak `10.8.0+26.6.3`,
gitea `3.5.3+1.24.2-rootless`, discourse `1.0.0+3.5.3`.
4. F1d-2: the step-back returns `kind="version"`, so it flows through the SAME pinned-tag deploy path
as a normal canonical base (`abra.recipe_checkout` pins the tag on disk) — no new deploy code.
Note (pre-existing, NOT introduced by this gate): `tests/unit/test_meta.py::test_generated_doc_table_in_sync`
and `tests/unit/test_warm_reconcile.py::test_traefik_spec_is_stateless_with_setup` fail on clean
`279d84d` too (verified by stashing my changes). Out of scope for samever.
## Blocked
(none)