Files

87 lines
3.2 KiB
Python
Raw Permalink Normal View History

"""CI orchestration must isolate host resources and clean up on failure."""
import importlib.util
import subprocess
from pathlib import Path
from types import SimpleNamespace
import pytest
@pytest.fixture
def ci(monkeypatch, tmp_path):
spec = importlib.util.spec_from_file_location(
"ci_compose", Path(__file__).parents[1] / "scripts/ci-compose-verify.py"
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
monkeypatch.setenv("GITHUB_ENV", str(tmp_path / "job-env"))
return module
def test_ci_config_preserves_runtime_and_isolates_resources(ci):
config = ci.isolated_compose("ffci-fixture")
production = ci.yaml.safe_load((ci.ROOT / "docker-compose.yml").read_text())
service = config["services"]["pigway-frame-flow"]
assert not any(key in service for key in ("ports", "container_name", "env_file"))
assert service["volumes"] == ["data:/data", "config:/config"]
assert config["volumes"] == {"data": {}, "config": {}}
assert config["name"] == "ffci-fixture"
assert service["image"] != "pigway-frame-flow:latest"
assert service["environment"]["KOKONNA_MOCK"] == "true"
assert service["environment"]["KOKONNA_WRITE_ENABLED"] == "false"
for key in (
"user",
"read_only",
"healthcheck",
"restart",
"cap_drop",
"security_opt",
):
assert service[key] == production["services"]["pigway-frame-flow"][key]
assert (
production["services"]["pigway-frame-flow"]["container_name"]
== "pigway-frame-flow"
)
@pytest.mark.parametrize("fail_smoke", [False, True])
def test_verification_cleanup_and_container_side_smoke(ci, monkeypatch, fail_smoke):
calls = []
def run(command, **kwargs):
calls.append((command, kwargs))
if command[-2:] == ["python", "-"] and fail_smoke:
raise subprocess.CalledProcessError(1, command)
return SimpleNamespace(returncode=0, stdout="fixture-container\n")
monkeypatch.setattr(ci.subprocess, "run", run)
if fail_smoke:
with pytest.raises(subprocess.CalledProcessError):
ci.verify()
else:
ci.verify()
assert any("down" in cmd and "--volumes" in cmd for cmd, _ in calls)
assert any(cmd[1:3] == ["image", "rm"] for cmd, _ in calls)
smoke = [(cmd, kw) for cmd, kw in calls if cmd[-2:] == ["python", "-"]]
assert len(smoke) == (1 if fail_smoke else 2)
assert all("exec" in cmd and "-T" in cmd and kw["input"] for cmd, kw in smoke)
if not fail_smoke:
assert any("restart" in cmd for cmd, _ in calls)
build_env = calls[0][1]["env"]
assert build_env["FRAME_FLOW_IMAGE"].startswith("pigway-frame-flow-ci:ffci-")
assert not Path(build_env["COMPOSE_FILE"]).exists()
def test_cleanup_failure_keeps_manifest_for_always_step(ci, monkeypatch, tmp_path):
path = tmp_path / "compose.yml"
path.write_text(ci.yaml.safe_dump(ci.isolated_compose("ffci-fixture")))
def fail(*args, **kwargs):
raise subprocess.CalledProcessError(1, args[0])
monkeypatch.setattr(ci.subprocess, "run", fail)
with pytest.raises(subprocess.CalledProcessError):
ci.cleanup(path)
assert path.exists()