from __future__ import annotations import importlib.util import sys from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] POLICY_PATH = ROOT / "ops" / "gitea-deploy-broker" / "runner_admission_policy.py" PROFILES_PATH = ROOT / "ops" / "gitea-deploy-broker" / "runner_profiles.py" def _load(name: str, path: Path): spec = importlib.util.spec_from_file_location(name, path) assert spec and spec.loader module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) return module @pytest.fixture def policy(): profiles = _load("appops_runner_profiles_for_admission_test", PROFILES_PATH) sys.modules["runner_profiles"] = profiles return _load("appops_runner_admission_policy_test", POLICY_PATH) def _job(job_id: str, labels: list[str], queued_at: float): return {"id": job_id, "labels": labels, "queued_at": queued_at} def test_oldest_compatible_job_wins_and_profile_choice_rotates(policy): jobs = [ _job("newer-security", ["itworx-ci-security"], 200.0), _job("older-linux", ["self-hosted", "linux-validation"], 100.0), ] first = policy.select_admission( jobs, available_profiles=["backend", "frontend", "security"], active_claims=[], cursor=0, ) second = policy.select_admission( jobs, available_profiles=["backend", "frontend", "security"], active_claims=[], cursor=first.next_cursor, ) assert (first.job_id, first.profile_id) == ("older-linux", "backend") assert (second.job_id, second.profile_id) == ("older-linux", "frontend") def test_enabled_legacy_slots_count_as_claims_and_can_consume_all_capacity(policy): decision = policy.select_admission( [_job("checks", ["itworx-ci-checks"], 1.0)], available_profiles=["checks"], # Two old broad Tower registrations are charged as two backend-envelope slots. active_claims=["backend", "backend"], ) assert decision.profile_id is None assert decision.reason == "runner_admission_claim_limit" def test_duplicate_legacy_claims_are_charged_against_dind_and_family_budgets(policy): dind_limited = policy.validate_claims(["frontend", "backend"]) family_excess = policy.validate_claims(["build", "backend"]) assert dind_limited.ok assert family_excess.reason == "runner_admission_dind_budget_exceeded" def test_two_heavy_profiles_cannot_be_admitted_together(policy): result = policy.validate_claims(["browser", "build"]) assert not result.ok assert result.reason == "runner_admission_heavy_claim_limit" def test_unmapped_enabled_registration_fails_closed(policy): result = policy.validate_claims(["unknown-legacy-runner"]) assert not result.ok assert result.reason == "runner_admission_profile_unmapped" def test_candidate_is_reserved_before_it_can_be_selected(policy): result = policy.select_admission( [_job("build", ["itworx-ci-build"], 1.0)], available_profiles=["build"], active_claims=["browser"], ) assert result.profile_id is None assert result.reason == "runner_admission_heavy_claim_limit" def test_unknown_required_job_label_does_not_fall_back_to_a_broad_profile(policy): result = policy.select_admission( [_job("mystery", ["linux-validation", "unraid-deploy"], 1.0)], available_profiles=["backend", "frontend"], active_claims=[], ) assert result.profile_id is None assert result.reason == "runner_admission_no_compatible_queue" def test_legacy_docker_alias_keeps_heavy_reservation_and_budget_gates(policy): selected = policy.select_admission( [_job("docker", ["docker-validation"], 1.0)], available_profiles=["build"], active_claims=[], ) assert selected.profile_id == "build" blocked = policy.select_admission( [_job("docker", ["docker-validation"], 1.0)], available_profiles=["build"], active_claims=["browser"], ) assert blocked.profile_id is None assert blocked.reason == "runner_admission_heavy_claim_limit" def test_malformed_queue_row_fails_closed(policy): with pytest.raises(policy.RunnerAdmissionPolicyError): policy.select_admission( [{"id": "bad", "labels": ["itworx-ci-checks"], "queued_at": "now"}], available_profiles=["checks"], active_claims=[], ) def test_lease_yields_to_the_oldest_eligible_other_profile_without_stealing_same_profile_work( policy, ): queue = [ _job("older-build", ["itworx-ci-build"], 100.0), _job("newer-backend", ["linux-validation"], 200.0), ] decision = policy.select_lease_yield( queue, leased_profile="backend", available_profiles=["checks", "security", "browser", "build"], active_claims=["backend", "frontend"], cursor=0, ) assert (decision.profile_id, decision.job_id) == ("build", "older-build") same_profile_is_oldest = policy.select_lease_yield( [ _job("older-backend", ["linux-validation"], 100.0), _job("newer-build", ["itworx-ci-build"], 200.0), ], leased_profile="backend", available_profiles=["checks", "security", "browser", "build"], active_claims=["backend", "frontend"], cursor=0, ) assert same_profile_is_oldest.profile_id is None assert same_profile_is_oldest.reason == "runner_admission_lease_retained" def test_lease_does_not_yield_when_current_claims_can_admit_queued_work(policy): decision = policy.select_lease_yield( [_job("checks", ["itworx-ci-checks"], 100.0)], leased_profile="backend", available_profiles=["checks"], active_claims=["backend"], cursor=0, ) assert decision.profile_id is None assert decision.reason == "runner_admission_lease_not_needed"