- test_scm_configured.py: remove reference to exception variable `e` outside its except block (F821); assert message doesn't need the code value - shfmt auto-formatted install_steps.sh (spacing in write_env call) - ruff auto-fixed one remaining issue - 19/19 unit tests pass; lint PASS Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
182 lines
6.4 KiB
Python
182 lines
6.4 KiB
Python
"""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}"
|
|
)
|