feat(canon): §2.G strip UPGRADE_BASE_VERSION entirely (plausible verified dynamic-base green)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Gate satisfied — live: with the pin removed, plausible's upgrade tier resolves base 3.0.1+v2.0.0 via the same-version step-back (canonical 3.1.0 == head 3.1.0 → newest-older = 3.0.1, NOT the broken 3.0.0) and passes install+upgrade green (level 5/5). The pin is redundant, so removed everywhere: - meta.py KEYS entry (RecipeMeta field auto-drops; 15→14 keys). - run_recipe_ci.resolve_upgrade_base override branch + docstrings. - tests/unit/test_meta.py (count 15→14, dropped None-assert), test_upgrade_base.py (override test). - docs/recipe-customization.md (regenerated table + mentions), docs/testing.md. - tests/plausible/recipe_meta.py (pin removed), tests/bluesky-pds (re-enable note → dynamic base). 294 unit tests pass; lint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -13,12 +13,13 @@ HTTP_TIMEOUT = 600
|
||||
# as an upgrade base anymore: the base crash-loops MODULE_NOT_FOUND before the PR head is ever
|
||||
# exercised (phase bsky root cause; cc-ci-plan/upstream/bluesky-pds.md). Declared intentional
|
||||
# until a fixed exact-pinned version (0.3.0+v0.4.219, mirror PR #2) is merged AND published —
|
||||
# then DROP this and set UPGRADE_BASE_VERSION = "0.3.0+v0.4.219" so the upgrade rung is
|
||||
# exercised again from the first deployable base.
|
||||
# then DROP this EXPECTED_NA and the upgrade rung resolves its base DYNAMICALLY (phase prevb:
|
||||
# last-green warm canonical → same-version step-back → main tip), no explicit pin needed
|
||||
# (UPGRADE_BASE_VERSION was removed in phase canon §2.G).
|
||||
EXPECTED_NA = {
|
||||
"upgrade": "no deployable upgrade base: every published version pins the moving tag "
|
||||
"pds:0.4, which upstream republished with incompatible main builds (index.js removed) — "
|
||||
"re-enable via UPGRADE_BASE_VERSION once a fixed version is published post-merge",
|
||||
"drop this once a fixed version is published post-merge (dynamic base then resolves it)",
|
||||
}
|
||||
|
||||
# canon §2.B: enroll as a DATA-WARM canonical (all recipes enrolled — operator 2026-06-17).
|
||||
|
||||
@ -58,7 +58,6 @@ def test_missing_meta_yields_spec_baseline(tmp_path):
|
||||
assert meta.BACKUP_CAPABLE is None # None = auto-detect (tri-state, not False)
|
||||
assert meta.EXPECTED_NA is None
|
||||
assert meta.READY_PROBE is None
|
||||
assert meta.UPGRADE_BASE_VERSION is None
|
||||
assert meta.BACKUP_VERIFY is None
|
||||
assert meta.UPGRADE_EXTRA_ENV is None
|
||||
assert meta.EXTRA_ENV == {}
|
||||
@ -74,9 +73,9 @@ def test_registry_field_set_matches_dataclass():
|
||||
import dataclasses
|
||||
|
||||
assert [f.name for f in dataclasses.fields(RecipeMeta)] == [k.name for k in KEYS]
|
||||
# the 15 final keys, no more (the 3 P2-deleted legacy keys are gone from the registry,
|
||||
# so any recipe_meta still setting them hard-fails the typo gate)
|
||||
assert len(KEYS) == 15
|
||||
# 14 final keys (UPGRADE_BASE_VERSION removed in phase canon §2.G; the 3 P2-deleted legacy keys
|
||||
# are gone too — any recipe_meta still setting a removed key hard-fails the typo gate)
|
||||
assert len(KEYS) == 14
|
||||
assert not [k for k in KEYS if k.deprecated]
|
||||
for gone in ("CHAOS_BASE_DEPLOY", "OIDC_AT_INSTALL", "SKIP_GENERIC"):
|
||||
assert gone not in {k.name for k in KEYS}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
"""Unit tests for `run_recipe_ci.resolve_upgrade_base` — the DYNAMIC upgrade-base decision (phase prevb).
|
||||
|
||||
Resolution order: upgrade∉stages / EXPECTED_NA[upgrade] (declared skip) → explicit UPGRADE_BASE_VERSION
|
||||
override → last-green (warm canonical) → target-branch (`main`) tip → skip (no predecessor). The result
|
||||
is a `BasePlan(kind, version, ref, reason)`: kind ∈ {"version", "ref", "skip"}; `.runs` is True for
|
||||
version/ref (the upgrade tier runs). Replaces the old static `recipe_versions[-2]` default.
|
||||
Resolution order: upgrade∉stages / EXPECTED_NA[upgrade] (declared skip) → last-green (warm canonical,
|
||||
with same-version step-back) → target-branch (`main`) tip → skip (no predecessor). The result is a
|
||||
`BasePlan(kind, version, ref, reason)`: kind ∈ {"version", "ref", "skip"}; `.runs` is True for
|
||||
version/ref (the upgrade tier runs). Replaces the old static `recipe_versions[-2]` default; the old
|
||||
explicit `UPGRADE_BASE_VERSION` override knob was removed in phase canon (§2.G).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@ -22,8 +23,8 @@ HEAD = "aaaa1111head"
|
||||
MAIN = "bbbb2222main"
|
||||
|
||||
|
||||
def _meta(expected_na=None, upgrade_base_version=None):
|
||||
return SimpleNamespace(EXPECTED_NA=expected_na, UPGRADE_BASE_VERSION=upgrade_base_version)
|
||||
def _meta(expected_na=None):
|
||||
return SimpleNamespace(EXPECTED_NA=expected_na)
|
||||
|
||||
|
||||
def _no_canonical(monkeypatch):
|
||||
@ -43,33 +44,16 @@ def test_upgrade_not_in_stages_skip(monkeypatch):
|
||||
assert plan.kind == "skip" and not plan.runs
|
||||
|
||||
|
||||
def test_expected_na_upgrade_skip_even_with_canonical_and_override(monkeypatch):
|
||||
# EXPECTED_NA[upgrade] is the strongest, declared fact — short-circuits before override/canonical.
|
||||
def test_expected_na_upgrade_skip_even_with_canonical(monkeypatch):
|
||||
# EXPECTED_NA[upgrade] is the strongest, declared fact — short-circuits before canonical.
|
||||
monkeypatch.setattr(
|
||||
canonical, "read_registry", lambda r: {"version": "9.9.9", "status": "warm"}
|
||||
)
|
||||
declared = {"upgrade": "no deployable upgrade base (moving tag republished)"}
|
||||
plan = run_recipe_ci.resolve_upgrade_base(
|
||||
ALL, _meta(expected_na=declared, upgrade_base_version="0.2.0+v0.4"), "bluesky-pds"
|
||||
)
|
||||
plan = run_recipe_ci.resolve_upgrade_base(ALL, _meta(expected_na=declared), "bluesky-pds")
|
||||
assert plan.kind == "skip" and "EXPECTED_NA" in plan.reason
|
||||
|
||||
|
||||
def test_explicit_override_wins_over_canonical(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
canonical, "read_registry", lambda r: {"version": "9.9.9", "status": "warm"}
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
lifecycle,
|
||||
"recipe_branch_commit",
|
||||
lambda r, b="main": (_ for _ in ()).throw(AssertionError("not consulted")),
|
||||
)
|
||||
plan = run_recipe_ci.resolve_upgrade_base(
|
||||
ALL, _meta(upgrade_base_version="0.7.0+3.3.1"), "discourse"
|
||||
)
|
||||
assert plan.kind == "version" and plan.version == "0.7.0+3.3.1" and plan.runs
|
||||
|
||||
|
||||
def test_last_green_warm_canonical_is_primary(monkeypatch):
|
||||
# no override → last-green (warm canonical version) is the PRIMARY base; main is not consulted.
|
||||
monkeypatch.setattr(
|
||||
|
||||
Reference in New Issue
Block a user