"""Unit tests for gitea dep provider path (phase drone). Tests: _enrich_deps_with_sso routing for gitea, recipe_meta.py loading for gitea and drone, the SCM-configured test's assertions (parametrized against mock redirect URLs). No real network calls or container execs — the gitea/drone setup logic is integration-tested by the real CI run (M1 build). """ from __future__ import annotations import os import sys import types import pytest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner")) from harness import meta as meta_mod # noqa: E402 TESTS_DIR = os.path.join(os.path.dirname(__file__), "..") # --------------------------------------------------------------------------- # recipe_meta.py loading for gitea and drone # --------------------------------------------------------------------------- def _load(recipe: str): return meta_mod.load(recipe, tests_dir=TESTS_DIR) def test_gitea_recipe_meta_health(): """gitea recipe_meta.py declares the correct health path and OK codes.""" m = _load("gitea") assert m.HEALTH_PATH == "/api/healthz" assert 200 in m.HEALTH_OK def test_gitea_recipe_meta_extra_env(): """gitea EXTRA_ENV returns sqlite3 COMPOSE_FILE and relaxed access controls.""" m = _load("gitea") ctx = types.SimpleNamespace( domain="gite-abc123.ci.commoninternet.net", base_url="", meta=m, deps={}, op=None ) env = meta_mod.extra_env(m, ctx) assert "compose.sqlite3.yml" in env.get("COMPOSE_FILE", "") assert env.get("GITEA_REQUIRE_SIGNIN_VIEW") == "false" assert env.get("GITEA_DISABLE_REGISTRATION") == "false" def test_drone_recipe_meta_deps(): """drone recipe_meta.py declares DEPS = ['gitea'].""" m = _load("drone") assert "gitea" in m.DEPS def test_drone_recipe_meta_health(): """drone recipe_meta.py declares the correct health path.""" m = _load("drone") assert m.HEALTH_PATH == "/healthz" assert 200 in m.HEALTH_OK # --------------------------------------------------------------------------- # _enrich_deps_with_sso routing for gitea (stub — no real container calls) # --------------------------------------------------------------------------- def _fake_setup_gitea_oauth(provider_domain, parent_domain): return { "admin_user": "ci_admin", "admin_password": "testpassword", "client_id": "abc-def-123", "client_secret": "secret-xyz", } def test_enrich_deps_routes_gitea(monkeypatch): """_enrich_deps_with_sso returns a correctly shaped entry for the gitea dep.""" sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner")) # Import the orchestrator; monkeypatch sso.setup_gitea_oauth so no real deploy happens import run_recipe_ci from harness import sso monkeypatch.setattr(sso, "setup_gitea_oauth", _fake_setup_gitea_oauth) deps_list = [{"recipe": "gitea", "domain": "gite-aabbcc.ci.commoninternet.net"}] result = run_recipe_ci._enrich_deps_with_sso( "drone", "dron-112233.ci.commoninternet.net", deps_list ) assert "gitea" in result entry = result["gitea"] assert entry["recipe"] == "gitea" assert entry["domain"] == "gite-aabbcc.ci.commoninternet.net" assert entry["client_id"] == "abc-def-123" assert entry["client_secret"] == "secret-xyz" assert entry["admin_user"] == "ci_admin" def test_enrich_deps_gitea_does_not_call_keycloak_path(monkeypatch): """_enrich_deps_with_sso for gitea does NOT call setup_keycloak_realm.""" sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner")) import run_recipe_ci from harness import sso monkeypatch.setattr(sso, "setup_gitea_oauth", _fake_setup_gitea_oauth) called_keycloak = [] monkeypatch.setattr( sso, "setup_keycloak_realm", lambda *a, **kw: called_keycloak.append(True) or {}, ) deps_list = [{"recipe": "gitea", "domain": "gite-aabbcc.ci.commoninternet.net"}] run_recipe_ci._enrich_deps_with_sso("drone", "dron-112233.ci.commoninternet.net", deps_list) assert not called_keycloak, "setup_keycloak_realm must not be called for gitea dep" # --------------------------------------------------------------------------- # SCM-configured test assertions (parametrized against mock URL scenarios) # --------------------------------------------------------------------------- @pytest.mark.parametrize( "location_url,gitea_domain,client_id,expect_pass", [ # Correct redirect: Location header points to gitea dep's authorize endpoint with matching client_id ( "https://gite-aabbcc.ci.commoninternet.net/login/oauth/authorize?client_id=abc-123&redirect_uri=x", "gite-aabbcc.ci.commoninternet.net", "abc-123", True, ), # Wrong domain: drone redirected to production gitea, not the dep ( "https://git.autonomic.zone/login/oauth/authorize?client_id=abc-123", "gite-aabbcc.ci.commoninternet.net", "abc-123", False, ), # Wrong path: not the OAuth authorize endpoint (e.g. gitea's /user/login after full-redirect-follow) ( "https://gite-aabbcc.ci.commoninternet.net/user/login?client_id=abc-123", "gite-aabbcc.ci.commoninternet.net", "abc-123", False, ), # Wrong client_id: drone is using a different OAuth app ( "https://gite-aabbcc.ci.commoninternet.net/login/oauth/authorize?client_id=wrong-id", "gite-aabbcc.ci.commoninternet.net", "abc-123", False, ), ], ) def test_scm_redirect_assertions(location_url, gitea_domain, client_id, expect_pass): """Parametrized verification of the SCM-configured test assertion logic (no HTTP calls). Tests the URL assertions against the Location header from drone's first 303 redirect (per ADV-drone-01 fix: _CaptureOneRedirect stops after drone's hop, not gitea's). """ import urllib.parse parsed = urllib.parse.urlparse(location_url) params = urllib.parse.parse_qs(parsed.query) checks = [ parsed.scheme == "https", parsed.netloc == gitea_domain, parsed.path == "/login/oauth/authorize", params.get("client_id", [None])[0] == client_id, ] all_pass = all(checks) assert all_pass == expect_pass, ( f"Expected {'pass' if expect_pass else 'fail'} for URL {location_url!r}; " f"checks: {checks}" )