Files
2026-07-13 13:12:33 +08:00

142 lines
4.7 KiB
Python

"""Verify migrations are packaged into the wheel and discoverable post-install.
Critical (C1): without this, default-enabled persistence would silently
boot on an out-of-date schema after fresh install.
"""
from __future__ import annotations
import os
import shutil
import subprocess
import zipfile
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parents[2]
@pytest.mark.skipif(shutil.which("uv") is None, reason="uv not on PATH")
def test_wheel_contains_v010_migration(tmp_path: Path) -> None:
"""`uv build --wheel` packages migrations/ as opensquilla/_migrations/."""
result = subprocess.run(
["uv", "build", "--wheel", "--out-dir", str(tmp_path)],
cwd=REPO_ROOT,
capture_output=True,
text=True,
timeout=180,
)
assert result.returncode == 0, f"uv build failed: {result.stderr}"
wheels = list(tmp_path.glob("opensquilla-*.whl"))
assert len(wheels) == 1, f"Expected 1 wheel, got {wheels}"
with zipfile.ZipFile(wheels[0]) as wheel:
names = wheel.namelist()
assert any(
n.endswith("opensquilla/_migrations/V010__meta_skill_runs.py") for n in names
), f"V010 missing from wheel; found: {[n for n in names if '_migrations' in n]}"
@pytest.mark.skipif(shutil.which("uv") is None, reason="uv not on PATH")
def test_installed_wheel_resolves_migrations(tmp_path: Path) -> None:
"""After pip-installing into a fresh venv, _resolve_migrations_dir() finds V010."""
venv_dir = tmp_path / "venv"
subprocess.run(
["uv", "venv", "--seed", str(venv_dir)],
cwd=REPO_ROOT,
check=True,
capture_output=True,
timeout=120,
)
pip = venv_dir / ("Scripts" if os.name == "nt" else "bin") / "pip"
py = venv_dir / ("Scripts" if os.name == "nt" else "bin") / "python"
wheel_dir = tmp_path / "dist"
subprocess.run(
["uv", "build", "--wheel", "--out-dir", str(wheel_dir)],
cwd=REPO_ROOT,
check=True,
capture_output=True,
timeout=180,
)
wheels = list(wheel_dir.glob("opensquilla-*.whl"))
# 120s was tight enough that Windows CI runners began timing out as
# the base dependency list grew (each transitive wheel adds I/O the
# Defender real-time scanner has to walk through). Ubuntu still
# completes in ~30s; Windows now needs ~90-150s. Bumping the budget
# rather than skipping preserves the test's intent — verify the
# built wheel installs cleanly into a fresh venv and the migration
# resolver finds V010 afterwards.
subprocess.run(
[str(pip), "install", str(wheels[0])],
check=True,
capture_output=True,
timeout=300,
)
result = subprocess.run(
[
str(py),
"-c",
(
"from opensquilla.gateway.boot import _resolve_migrations_dir;"
" d = _resolve_migrations_dir();"
" assert (d / 'V010__meta_skill_runs.py').exists(),"
" f'V010 missing in {d}';"
" print('OK', d)"
),
],
capture_output=True,
text=True,
timeout=60,
)
assert result.returncode == 0, f"resolver failed: {result.stderr}"
assert "OK" in result.stdout
@pytest.mark.skipif(shutil.which("docker") is None, reason="docker not on PATH")
@pytest.mark.skipif(os.name == "nt", reason="docker smoke uses Linux container images")
@pytest.mark.skipif(
os.environ.get("OPENSQUILLA_SKIP_DOCKER_SMOKE") == "1",
reason="docker smoke disabled via env",
)
@pytest.mark.skipif(
os.environ.get("OPENSQUILLA_RUN_DOCKER_SMOKE") != "1",
reason="docker smoke is opt-in; it pulls external images",
)
def test_docker_image_resolves_migrations() -> None:
"""`docker build` + `docker run` resolves _migrations including V010.
Verifies (C1 v2): .dockerignore no longer excludes migrations/.
"""
tag = "opensquilla-test:meta-runs-persistence"
build = subprocess.run(
["docker", "build", "-t", tag, "."],
cwd=REPO_ROOT,
capture_output=True,
text=True,
timeout=600,
)
assert build.returncode == 0, f"docker build failed: {build.stderr[-2000:]}"
run = subprocess.run(
[
"docker", "run", "--rm", "--entrypoint", "python", tag,
"-c",
(
"from opensquilla.gateway.boot import _resolve_migrations_dir;"
" d = _resolve_migrations_dir();"
" assert (d / 'V010__meta_skill_runs.py').exists();"
" print('OK', d)"
),
],
capture_output=True,
text=True,
timeout=60,
)
assert run.returncode == 0, f"docker run failed: {run.stderr}"
assert "OK" in run.stdout