feat(deploy): gate claims on pinned runtime readiness
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a06ba0-10aa-7ea0-b20a-4f3fac39efe9
This commit is contained in:
parent
d00ffcb402
commit
4310c15eac
17 changed files with 757 additions and 10 deletions
86
tests/test_readiness.py
Normal file
86
tests/test_readiness.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from rein_aharness.close_outbox import CloseOutbox
|
||||
from rein_aharness.ops_run_client import OpsRunConfig, OpsRunError
|
||||
from rein_aharness.readiness import run_readiness_checks
|
||||
|
||||
|
||||
class _Client:
|
||||
def __init__(self, *, repo_map: dict[str, str] | None = None, error=None):
|
||||
self.config = OpsRunConfig(repo_map=repo_map or {})
|
||||
self.error = error
|
||||
self.list_calls = 0
|
||||
|
||||
def list_open(self, *, limit: int = 50):
|
||||
self.list_calls += 1
|
||||
assert limit == 1
|
||||
if self.error is not None:
|
||||
raise self.error
|
||||
return []
|
||||
|
||||
|
||||
def test_readiness_is_read_only_and_passes_minimal_runtime(tmp_path: Path) -> None:
|
||||
client = _Client()
|
||||
report = run_readiness_checks(
|
||||
client, # type: ignore[arg-type]
|
||||
CloseOutbox(state_dir=tmp_path / "state"),
|
||||
environ={},
|
||||
)
|
||||
|
||||
assert report.ok
|
||||
assert client.list_calls == 1
|
||||
assert [check.name for check in report.checks] == [
|
||||
"close_outbox",
|
||||
"profiled_runtime",
|
||||
"activity_core",
|
||||
]
|
||||
|
||||
|
||||
def test_readiness_fails_before_claim_when_queue_probe_is_unavailable(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
client = _Client(error=OpsRunError("transport", action="list"))
|
||||
|
||||
report = run_readiness_checks(
|
||||
client, # type: ignore[arg-type]
|
||||
CloseOutbox(state_dir=tmp_path / "state"),
|
||||
environ={},
|
||||
)
|
||||
|
||||
assert not report.ok
|
||||
failure = next(check for check in report.checks if check.name == "activity_core")
|
||||
assert failure.detail == "read-only queue probe failed (OpsRunError)"
|
||||
|
||||
|
||||
def test_readiness_refuses_quarantine_and_missing_workspace(tmp_path: Path) -> None:
|
||||
outbox = CloseOutbox(state_dir=tmp_path / "state")
|
||||
(outbox.quarantine_dir / "entry.deadbeef.json").write_text("{}", encoding="utf-8")
|
||||
client = _Client(repo_map={"missing": str(tmp_path / "absent")})
|
||||
|
||||
report = run_readiness_checks(
|
||||
client, # type: ignore[arg-type]
|
||||
outbox,
|
||||
environ={},
|
||||
check_activity_core=False,
|
||||
)
|
||||
|
||||
assert not report.ok
|
||||
failed = {check.name for check in report.checks if not check.ok}
|
||||
assert failed == {"close_outbox", "repository:missing"}
|
||||
|
||||
|
||||
def test_readiness_requires_exact_profile_versions_without_optional_imports(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
report = run_readiness_checks(
|
||||
_Client(), # type: ignore[arg-type]
|
||||
CloseOutbox(state_dir=tmp_path / "state"),
|
||||
environ={"AGENT_HARNESS_REQUIRED_PROFILE_REFS": "harness.agent-dev-local"},
|
||||
check_activity_core=False,
|
||||
)
|
||||
|
||||
assert not report.ok
|
||||
failure = next(check for check in report.checks if check.name.startswith("profile:"))
|
||||
assert failure.detail == "production profile reference must pin an exact version"
|
||||
90
tests/test_runtime_lock.py
Normal file
90
tests/test_runtime_lock.py
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from scripts.verify_runtime_lock import verify
|
||||
|
||||
|
||||
def _git(repo: Path, *args: str) -> str:
|
||||
return subprocess.check_output(["git", *args], cwd=repo, text=True).strip()
|
||||
|
||||
|
||||
def _fixture(tmp_path: Path) -> tuple[Path, Path]:
|
||||
root = tmp_path / "root"
|
||||
worker = root / "rein-aharness"
|
||||
source = root / "dependency"
|
||||
(worker / "deploy").mkdir(parents=True)
|
||||
source.mkdir(parents=True)
|
||||
(source / "pyproject.toml").write_text(
|
||||
'[project]\nname = "example-runtime"\nversion = "1.2.3"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
subprocess.run(["git", "init", "-q"], cwd=source, check=True)
|
||||
subprocess.run(["git", "add", "pyproject.toml"], cwd=source, check=True)
|
||||
subprocess.run(
|
||||
[
|
||||
"git",
|
||||
"-c",
|
||||
"user.name=Test",
|
||||
"-c",
|
||||
"user.email=test@example.invalid",
|
||||
"commit",
|
||||
"-qm",
|
||||
"initial",
|
||||
],
|
||||
cwd=source,
|
||||
check=True,
|
||||
)
|
||||
lock = worker / "deploy" / "runtime-contract-lock.json"
|
||||
lock.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"schema_version": "1",
|
||||
"contracts": {
|
||||
"activity_core_contract_commit": "a" * 40,
|
||||
"activity_core_schema": "0010",
|
||||
"glas_contract_version": "1.0",
|
||||
},
|
||||
"dependencies": [
|
||||
{
|
||||
"distribution": "example-runtime",
|
||||
"version": "1.2.3",
|
||||
"source": "../dependency",
|
||||
"commit": _git(source, "rev-parse", "HEAD"),
|
||||
}
|
||||
],
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return lock, source
|
||||
|
||||
|
||||
def test_runtime_lock_accepts_exact_clean_source(tmp_path: Path) -> None:
|
||||
lock, _source = _fixture(tmp_path)
|
||||
|
||||
report = verify(lock)
|
||||
|
||||
assert report["ok"] is True
|
||||
assert report["dependencies"][0]["distribution"] == "example-runtime"
|
||||
assert report["dependencies"][0]["clean"] is True
|
||||
|
||||
|
||||
def test_runtime_lock_rejects_revision_or_dirty_source(tmp_path: Path) -> None:
|
||||
lock, source = _fixture(tmp_path)
|
||||
payload = json.loads(lock.read_text(encoding="utf-8"))
|
||||
payload["dependencies"][0]["commit"] = "0" * 40
|
||||
lock.write_text(json.dumps(payload), encoding="utf-8")
|
||||
|
||||
with pytest.raises(ValueError, match="revision mismatch"):
|
||||
verify(lock)
|
||||
|
||||
payload["dependencies"][0]["commit"] = _git(source, "rev-parse", "HEAD")
|
||||
lock.write_text(json.dumps(payload), encoding="utf-8")
|
||||
(source / "untracked.txt").write_text("dirty\n", encoding="utf-8")
|
||||
with pytest.raises(ValueError, match="source checkout is dirty"):
|
||||
verify(lock)
|
||||
Loading…
Add table
Add a link
Reference in a new issue