Files
graphify/tests/test_wheel_packaging.py
T
Safi 6137cdba43 harden _always_on against missing blocks and pin skillgen baselines
R1: the 6 always-on blocks were read into module-level constants at import,
so a missing/corrupt always_on/*.md crashed `import graphify.__main__` and
bricked every CLI command, not just install. Make _always_on lazy + lru_cached,
raising a clear "reinstall" error only on the install path that needs the block;
a module __getattr__ keeps the legacy constant names importable for the tests.
Verified: deleting a block no longer crashes `graphify --version`.

skillgen baselines: the self-check guards pinned to the moving `origin/v8` ref,
which stops pointing at the pre-split state once the split lands on v8 (the
always-on-roundtrip guard then fails in CI and monolith-roundtrip goes vacuous).
Pin _v8_baseline_ref, ALWAYS_ON_BASELINE_REF, and the two monolith roundtrip_refs
to the immutable pre-split commit SHA, matching the stated "does not track HEAD"
intent; update the 4 tests that asserted the old ref string.

R2: add tests/test_wheel_packaging.py - build the wheel and assert every
references bundle and always-on block ships in it, so a package-data glob miss
can't pass the repo-tree guards yet hard-exit `graphify install` for real users.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 21:08:11 +01:00

72 lines
2.6 KiB
Python

"""Packaging guard (#1121 follow-up): the 5 skillgen guards check the *repo tree*,
not the *built wheel*. A host whose references bundle or always-on block fails to
match the `package-data` globs would pass `--check`/`--audit-coverage` yet make
`graphify install` hard-exit with "not found in package" for real users.
This builds the wheel once and asserts every committed skill artifact ships in it.
"""
from __future__ import annotations
import subprocess
import sys
import zipfile
from pathlib import Path
import pytest
REPO = Path(__file__).resolve().parents[1]
PKG = REPO / "graphify"
def _has_build() -> bool:
try:
subprocess.run(
[sys.executable, "-m", "build", "--version"],
check=True, capture_output=True,
)
return True
except (subprocess.CalledProcessError, FileNotFoundError):
return False
def _expected_artifacts() -> list[Path]:
"""Every committed references/*.md (per host) + always_on/*.md block."""
refs = sorted((PKG / "skills").glob("*/references/*.md"))
always = sorted((PKG / "always_on").glob("*.md"))
# Sanity: if these are empty the test wiring is broken, not the wheel.
assert refs, "no skills/*/references/*.md found in repo — packaging test mis-wired"
assert always, "no always_on/*.md found in repo — packaging test mis-wired"
return refs + always
@pytest.fixture(scope="module")
def wheel_namelist(tmp_path_factory) -> set[str]:
if not _has_build():
pytest.skip("`python -m build` unavailable (dev extra not installed)")
out = tmp_path_factory.mktemp("wheel")
proc = subprocess.run(
[sys.executable, "-m", "build", "--wheel", "--no-isolation",
"--outdir", str(out), str(REPO)],
capture_output=True, text=True,
)
if proc.returncode != 0:
pytest.skip(f"wheel build failed in this env:\n{proc.stderr[-800:]}")
wheels = list(out.glob("graphifyy-*.whl"))
assert wheels, "no wheel produced"
with zipfile.ZipFile(max(wheels, key=lambda p: p.stat().st_mtime)) as z:
return set(z.namelist())
@pytest.mark.parametrize(
"artifact",
_expected_artifacts(),
ids=lambda p: str(p.relative_to(PKG)),
)
def test_skill_artifact_ships_in_wheel(artifact: Path, wheel_namelist: set[str]) -> None:
rel = "graphify/" + artifact.relative_to(PKG).as_posix()
assert rel in wheel_namelist, (
f"{rel} is committed in the repo but NOT in the built wheel — "
f"`graphify install` would hard-exit for this host. Check the "
f"[tool.setuptools.package-data] globs in pyproject.toml."
)