from __future__ import annotations import re from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] def test_controller_promoter_action_is_fixed_and_registered(): registry = (ROOT / "backend/app/services/action_registry.py").read_text(encoding="utf-8") execution = (ROOT / "backend/app/services/action_execution.py").read_text(encoding="utf-8") assert "'controller.artifact.promote'" in registry assert "return 'tower/deployment-controller'" in registry assert 'action == "controller.artifact.promote"' in execution assert 'target.strip().lower() != "tower/deployment-controller"' in execution def test_controller_promoter_helper_spec_is_fixed_and_bounded(): from backend.app.services.controller_artifact_promoter import ( CONTROLLER_VERSION, HELPER_NAME, helper_container_spec, ) revision = "a" * 40 image_id = "sha256:" + "b" * 64 spec = helper_container_spec(revision=revision, image_id=image_id) assert HELPER_NAME == "itworx-controller-artifact-promoter" assert re.fullmatch(r"2\.1\.\d+", CONTROLLER_VERSION) assert spec["Image"] == image_id assert spec["HostConfig"]["Privileged"] is False assert spec["HostConfig"]["NetworkMode"] == "host" assert spec["HostConfig"]["SecurityOpt"] == ["no-new-privileges:true"] assert set(spec["HostConfig"]["Binds"]) == { "/mnt/cache:/mnt/cache", "/mnt/user:/mnt/user", "/srv/example/appdata/gitea/git/repositories:/gitea-repositories:ro", "/var/lib/docker:/var/lib/docker:ro", "/var/run/docker.sock:/var/run/docker.sock", } assert spec["Cmd"][:2] == ["/bin/bash", "-lc"] command = spec["Cmd"][2] assert "scripts/upgrade_deployment_controller.sh" in command assert "UPGRADE_DEPLOYMENT_CONTROLLER_V2" in command assert revision in command assert CONTROLLER_VERSION in command assert "/gitea-repositories/jens/unraid-appops-gateway.git" in command assert f"itworx-controller-artifact-promoter-{revision[:12]}.XXXXXX" in command assert "work='/mnt/cache" not in command assert "rm -rf -- \"$work\"" in command assert "chmod 0600 \"$work/controller.tar\"" in command assert "scripts/prepare_controller_hub_release_volume.py" in command assert "scripts/upgrade_deployment_controller.sh > \"$work/controller.tar\"" in command assert f"--image-id '{image_id}'" in command @pytest.mark.parametrize( "revision,image_id", [ ("main", "sha256:" + "b" * 64), ("a" * 39, "sha256:" + "b" * 64), ("a" * 40, "ubuntu:latest"), ("a" * 40, "sha256:" + "z" * 64), ], ) def test_controller_promoter_rejects_mutable_or_invalid_identity(revision: str, image_id: str): from backend.app.services.controller_artifact_promoter import helper_container_spec with pytest.raises(ValueError): helper_container_spec(revision=revision, image_id=image_id) def test_controller_promoter_uses_only_protected_main_and_push_gate(): source = (ROOT / "backend/app/services/controller_artifact_promoter.py").read_text(encoding="utf-8") assert 'branch = "main"' in source assert 'REQUIRED_PUSH_CONTEXT = "Managed validation / full (push)"' in source assert "controller_promoter_main_not_validated" in source assert "caller_revision" not in source def test_deployment_broker_exposes_bounded_controller_health(): source = (ROOT / "backend/app/services/deployment_broker.py").read_text(encoding="utf-8") assert "def controller_health(self)" in source assert 'f"{self.base_url}/health"' in source assert "_MAX_CONTROLLER_HEALTH_BYTES" in source