from backend.app.services.action_execution import approval_execution_supported from backend.app.services.action_registry import ACTION_RISK, ACTIONS, action_default_target from backend.app.services.portfolio_deployment_enrollment import ( _ENROLL_SCRIPT, _INSPECT_SCRIPT, _LEGACY_REVISION, _LEGACY_SINGLE_PROJECT, _PROJECT, _RECOVERY_FAILED_REVISION, _RECOVERY_FAILURE_MESSAGE, _RECOVERY_LIVE_REVISION, _REPOSITORY, PortfolioDeploymentEnrollment, ) class _Response: def __init__(self, *, payload=None, text=""): self._payload = payload self.text = text def json(self): return self._payload class _InspectPortainer: def __init__(self): self.calls = [] def _request(self, method, path, **kwargs): self.calls.append((method, path, kwargs)) if path.endswith("/exec"): return _Response(payload={"Id": "exec-safe-inspect"}) if path.endswith("/start"): return _Response( text='{"branch":"main","compose_files":["docker-compose.yml"],"containers":["Portfolio","Portfolio-api"],"present":true}' ) raise AssertionError(f"Unexpected Portainer path: {path}") def test_portfolio_enrollment_contract_is_fixed_and_paired(): assert _REPOSITORY == "jens/portfolio" assert _LEGACY_REVISION == "e59bfb3484531883e5486ee9e10b663ed0f6764f" assert _PROJECT["branch"] == "main" assert _PROJECT["exact_source"] is True assert _PROJECT["env_source"] == "/srv/example/appdata/Portfolio/.env" assert _PROJECT["compose_files"] == ["docker-compose.yml"] assert _PROJECT["compose_project"] == "portfolio" assert _PROJECT["containers"] == ["Portfolio", "Portfolio-api"] assert _PROJECT["verify_oci_revision"] is False assert _PROJECT["environment"] == { "GIT_COMMIT": "{revision}", "BUILD_ID": "build-{short_revision}", } def test_portfolio_enrollment_registry_alias_matches_controller_cache_bind_source(): assert 'registry_path = Path("/opt/gitea-deploy/projects.json")' in _ENROLL_SCRIPT assert ( 'host_registry_path = Path("/mnt/cache/appdata/gitea-deploy-runners/controller/projects.json")' in _ENROLL_SCRIPT ) assert "os.path.samefile(registry_path, host_registry_path)" in _ENROLL_SCRIPT assert '/srv/example/appdata/gitea-deploy-runners/deploy.lock' not in _ENROLL_SCRIPT assert '/mnt/cache/appdata/gitea-deploy-runners/deploy.lock' in _ENROLL_SCRIPT def test_portfolio_enrollment_uses_project_then_global_lock_order_without_child_deadlock(): project_lock = "fcntl.flock(project_lock, fcntl.LOCK_EX)" cache_lock = "fcntl.flock(lock, fcntl.LOCK_EX)" assert _ENROLL_SCRIPT.index(project_lock) < _ENROLL_SCRIPT.index(cache_lock) assert "controller.bootstrap_legacy_state(repository, project, legacy_revision)" in _ENROLL_SCRIPT assert '["python3", "/opt/gitea-deploy/deploy.py", "bootstrap-legacy"' not in _ENROLL_SCRIPT def test_portfolio_enrollment_only_migrates_known_legacy_single_target(): assert _LEGACY_SINGLE_PROJECT["containers"] == ["portfolio"] assert _LEGACY_SINGLE_PROJECT["compose_project"] == "portfolio" assert _LEGACY_SINGLE_PROJECT["compose_files"] == ["docker-compose.yml"] assert "env_source" not in _LEGACY_SINGLE_PROJECT def test_portfolio_target_registration_is_a_typed_high_risk_action(): action = "deployment.target.register_portfolio" assert action in ACTIONS assert ACTION_RISK[action] == "high" assert action_default_target(action) == "jens/portfolio" assert approval_execution_supported(action) is True def test_portfolio_target_inspection_returns_only_sanitized_json_from_controller(): portainer = _InspectPortainer() service = PortfolioDeploymentEnrollment(portainer=portainer) result = service._inspect_current_target(endpoint="1", container_id="controller-id") assert result == { "branch": "main", "compose_files": ["docker-compose.yml"], "containers": ["Portfolio", "Portfolio-api"], "present": True, } assert portainer.calls[0][2]["json"]["AttachStdout"] is True assert portainer.calls[0][2]["json"]["Tty"] is True assert portainer.calls[1][2]["json"] == {"Detach": False, "Tty": True} def test_portfolio_target_inspection_exposes_only_bounded_state_diagnostics(): assert ( 'state_path = Path("/mnt/cache/appdata/gitea-deploy-runners/state/portfolio.json")' in _INSPECT_SCRIPT ) for allowed in ( '"schema_version"', '"live_revision"', '"live_status"', '"live_legacy_provenance"', '"last_attempt"', '"live_artifact_containers"', ): assert allowed in _INSPECT_SCRIPT assert 'safe_attempt["message"]' in _INSPECT_SCRIPT assert "[:768]" in _INSPECT_SCRIPT assert 'state.get("live_receipt")' not in _INSPECT_SCRIPT assert 'state.get("rollback_snapshot")' not in _INSPECT_SCRIPT def test_portfolio_runtime_reconciliation_is_pinned_to_observed_failure(): assert _RECOVERY_LIVE_REVISION == "52c6f2fc74a1e39ad288f1c5e987a9cd5b072d3e" assert _RECOVERY_FAILED_REVISION == "b7955d90b63860ffff8e0bd84be123aaba632043" assert ( _RECOVERY_FAILURE_MESSAGE == "Existing production containers require a valid healthy live deployment state" ) assert 'existing_state.get("live_status") == "unknown"' in _ENROLL_SCRIPT assert 'existing_state.get("live_legacy_provenance") is False' in _ENROLL_SCRIPT assert 'last_attempt.get("revision") == recovery_failed_revision' in _ENROLL_SCRIPT assert 'last_attempt.get("message") == recovery_failure_message' in _ENROLL_SCRIPT assert 'isinstance(live_receipt, dict)' in _ENROLL_SCRIPT assert 'bool(live_receipt)' in _ENROLL_SCRIPT assert 'set(artifact_containers) == set(project["containers"])' in _ENROLL_SCRIPT def test_portfolio_runtime_reconciliation_proves_exact_recorded_artifacts(): assert 'revision_label != recovery_live_revision' in _ENROLL_SCRIPT assert 'build_label != f"build-{recovery_live_revision[:12]}"' in _ENROLL_SCRIPT assert 'artifact.get("image_id")' in _ENROLL_SCRIPT assert 'artifact.get("container_id")' in _ENROLL_SCRIPT assert 'str(container.get("Image") or "")' in _ENROLL_SCRIPT assert 'str(container.get("Id") or "")' in _ENROLL_SCRIPT assert 'reconciled_state = dict(existing_state)' in _ENROLL_SCRIPT assert 'reconciled_state["live_status"] = "healthy"' in _ENROLL_SCRIPT assert 'reconciled_state["status"] = "success"' in _ENROLL_SCRIPT assert 'bool(verify.get("live_receipt"))' in _ENROLL_SCRIPT assert "runtime-state-reconciled" in _ENROLL_SCRIPT