70 lines
2.8 KiB
Python
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
|