Files
Unraid-AppOps-Gateway-Public/backend/tests/test_runner_controller_artifact.py
T

70 lines
2.8 KiB
Python

from __future__ import annotations
import importlib.util
import shutil
import subprocess
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
def load(name, path):
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
@pytest.fixture
def artifact(tmp_path, monkeypatch):
renderer = load('runner_artifact_renderer', ROOT / 'scripts/prepare_controller_artifact.py')
controller_dir = ROOT / 'ops/gitea-deploy-broker'
monkeypatch.syspath_prepend(str(controller_dir))
controller = load('runner_artifact_controller', controller_dir / 'status_server.py')
stage = tmp_path / 'controller'
stage.mkdir()
for name in renderer._ARTIFACT_FILES:
source = ROOT / 'scripts/run_repopulse_adoption.py' if name == 'run_repopulse_adoption.py' else controller_dir / name
shutil.copyfile(source, stage / name)
result = subprocess.run([
sys.executable, str(ROOT / 'scripts/prepare_controller_artifact.py'),
'--artifact-dir', str(stage), '--source-repository', 'jens/unraid-appops-gateway',
'--source-revision', 'a' * 40, '--source-tree', 'b' * 40,
'--controller-version', '2.1.13', '--built-at', '2026-10-01T12:00:00Z',
], capture_output=True, text=True, check=True)
assert 'artifactSha256' in result.stdout
monkeypatch.setattr(controller, 'ROOT', stage)
monkeypatch.setattr(controller, 'CONTROLLER_RELEASE_PATH', stage / 'controller-release.json')
return controller, stage
def test_renderer_and_runtime_accept_the_same_complete_specialized_artifact(artifact):
controller, _stage = artifact
release = controller._controller_release()
assert release['controllerVersion'] == '2.1.13'
assert release['sourceRevision'] == 'a' * 40
@pytest.mark.parametrize('damage', ['missing_binding', 'missing_hub_store', 'changed_admission', 'symlink_envelope'])
def test_incomplete_or_changed_specialized_artifact_cannot_be_promoted(artifact, damage):
controller, stage = artifact
if damage == 'missing_binding':
(stage / 'runner_statistics_binding.py').unlink()
elif damage == 'missing_hub_store':
(stage / 'mcp_hub_release_store.py').unlink()
elif damage == 'changed_admission':
with (stage / 'runner_admission_policy.py').open('ab') as stream:
stream.write(b'\n# changed after manifest rendering\n')
else:
target = stage / 'runner_resource_envelope.py'
original = stage / 'moved_envelope.py'
target.rename(original)
try:
target.symlink_to(original)
except OSError:
pytest.skip('Host cannot create symlink fixture')
assert controller._controller_release() is None