Files
astral/tests/test_ensure_rolling_pr.py
Tomas Kracmar 17d745bdac Sync from dev @ 252c1cf
Source: main (252c1cf)
Excluded: live tenant exports, generated artifacts, and dev-only tooling.
2026-04-17 15:57:35 +02:00

343 lines
14 KiB
Python

from __future__ import annotations
import importlib.util
import os
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
MODULE_PATH = Path(__file__).resolve().parents[1] / "scripts" / "ensure_rolling_pr.py"
def load_module():
# Preload common helper so the script can import it.
common_path = MODULE_PATH.parent / "common.py"
common_spec = importlib.util.spec_from_file_location("common", common_path)
if common_spec is not None and common_spec.loader is not None:
common_mod = importlib.util.module_from_spec(common_spec)
sys.modules["common"] = common_mod
common_spec.loader.exec_module(common_mod)
module_name = "ensure_rolling_pr"
spec = importlib.util.spec_from_file_location(module_name, MODULE_PATH)
if spec is None or spec.loader is None:
raise RuntimeError(f"Unable to load module from {MODULE_PATH}")
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
return module
def _run(cmd: list[str], cwd: Path) -> None:
subprocess.run(cmd, cwd=cwd, check=True, capture_output=True, text=True)
class EnsureRollingPrTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.module = load_module()
def test_is_workload_config_path_filters_docs_and_reports(self) -> None:
is_path = self.module._is_workload_config_path
self.assertTrue(
is_path(
"tenant-state/entra/Conditional Access/policy.json",
workload_dir="entra",
backup_folder="tenant-state",
reports_subdir="reports",
)
)
self.assertFalse(
is_path(
"tenant-state/entra/Conditional Access/policy.md",
workload_dir="entra",
backup_folder="tenant-state",
reports_subdir="reports",
)
)
self.assertFalse(
is_path(
"tenant-state/reports/entra/assignment_report.md",
workload_dir="entra",
backup_folder="tenant-state",
reports_subdir="reports",
)
)
def test_config_fingerprint_ignores_docs_and_reports(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
repo = Path(tmp)
_run(["git", "init"], repo)
_run(["git", "config", "user.name", "Test"], repo)
_run(["git", "config", "user.email", "test@example.com"], repo)
config_file = repo / "tenant-state" / "entra" / "Conditional Access" / "policy.json"
report_file = repo / "tenant-state" / "reports" / "entra" / "summary.md"
doc_file = repo / "tenant-state" / "entra" / "README.md"
config_file.parent.mkdir(parents=True, exist_ok=True)
report_file.parent.mkdir(parents=True, exist_ok=True)
doc_file.parent.mkdir(parents=True, exist_ok=True)
config_file.write_text('{"state":"enabled"}\n', encoding="utf-8")
report_file.write_text("report v1\n", encoding="utf-8")
doc_file.write_text("doc v1\n", encoding="utf-8")
_run(["git", "add", "."], repo)
_run(["git", "commit", "-m", "initial"], repo)
fp1 = self.module._config_fingerprint_from_local_tree(
repo_root=str(repo),
commitish="HEAD",
workload_dir="entra",
backup_folder="tenant-state",
reports_subdir="reports",
)
report_file.write_text("report v2\n", encoding="utf-8")
doc_file.write_text("doc v2\n", encoding="utf-8")
_run(["git", "add", "."], repo)
_run(["git", "commit", "-m", "doc/report only"], repo)
fp2 = self.module._config_fingerprint_from_local_tree(
repo_root=str(repo),
commitish="HEAD",
workload_dir="entra",
backup_folder="tenant-state",
reports_subdir="reports",
)
config_file.write_text('{"state":"disabled"}\n', encoding="utf-8")
_run(["git", "add", "."], repo)
_run(["git", "commit", "-m", "config change"], repo)
fp3 = self.module._config_fingerprint_from_local_tree(
repo_root=str(repo),
commitish="HEAD",
workload_dir="entra",
backup_folder="tenant-state",
reports_subdir="reports",
)
self.assertTrue(fp1)
self.assertEqual(fp1, fp2)
self.assertNotEqual(fp2, fp3)
def test_ref_has_commit_for_local_and_missing_ref(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
repo = Path(tmp)
_run(["git", "init"], repo)
_run(["git", "config", "user.name", "Test"], repo)
_run(["git", "config", "user.email", "test@example.com"], repo)
(repo / "README.md").write_text("x\n", encoding="utf-8")
_run(["git", "add", "."], repo)
_run(["git", "commit", "-m", "init"], repo)
self.assertTrue(self.module._ref_has_commit(str(repo), "HEAD"))
self.assertFalse(self.module._ref_has_commit(str(repo), "origin/does-not-exist"))
def test_workload_config_diff_exists_ignores_docs_and_reports(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
repo = Path(tmp)
_run(["git", "init"], repo)
_run(["git", "config", "user.name", "Test"], repo)
_run(["git", "config", "user.email", "test@example.com"], repo)
config_file = repo / "tenant-state" / "intune" / "Device Configurations" / "policy.json"
report_file = repo / "tenant-state" / "reports" / "intune" / "summary.md"
doc_file = repo / "tenant-state" / "intune" / "README.md"
config_file.parent.mkdir(parents=True, exist_ok=True)
report_file.parent.mkdir(parents=True, exist_ok=True)
doc_file.parent.mkdir(parents=True, exist_ok=True)
config_file.write_text('{"setting":"enabled"}\n', encoding="utf-8")
report_file.write_text("report v1\n", encoding="utf-8")
doc_file.write_text("doc v1\n", encoding="utf-8")
_run(["git", "add", "."], repo)
_run(["git", "commit", "-m", "baseline"], repo)
baseline_commit = subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=repo,
check=True,
capture_output=True,
text=True,
).stdout.strip()
report_file.write_text("report v2\n", encoding="utf-8")
doc_file.write_text("doc v2\n", encoding="utf-8")
_run(["git", "add", "."], repo)
_run(["git", "commit", "-m", "doc only"], repo)
doc_only_commit = subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=repo,
check=True,
capture_output=True,
text=True,
).stdout.strip()
config_file.write_text('{"setting":"disabled"}\n', encoding="utf-8")
_run(["git", "add", "."], repo)
_run(["git", "commit", "-m", "config change"], repo)
config_change_commit = subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=repo,
check=True,
capture_output=True,
text=True,
).stdout.strip()
self.assertFalse(
self.module._workload_config_diff_exists(
repo_root=str(repo),
baseline_commitish=baseline_commit,
drift_commitish=doc_only_commit,
workload_dir="intune",
backup_folder="tenant-state",
reports_subdir="reports",
)
)
self.assertTrue(
self.module._workload_config_diff_exists(
repo_root=str(repo),
baseline_commitish=baseline_commit,
drift_commitish=config_change_commit,
workload_dir="intune",
backup_folder="tenant-state",
reports_subdir="reports",
)
)
def test_main_suppresses_pr_creation_when_drift_matches_baseline_config(self) -> None:
env = {
"SYSTEM_ACCESSTOKEN": "token",
"SYSTEM_COLLECTIONURI": "https://dev.azure.com/example",
"SYSTEM_TEAMPROJECT": "Project",
"BUILD_REPOSITORY_ID": "repo-id",
}
with patch.dict(os.environ, env, clear=False):
with patch.object(
sys,
"argv",
[
"ensure_rolling_pr.py",
"--repo-root",
"/tmp/repo",
"--workload",
"intune",
"--drift-branch",
"drift/intune",
"--baseline-branch",
"main",
"--pr-title",
"Intune drift review (rolling)",
],
):
with patch.object(self.module, "_query_prs", return_value=[]):
with patch.object(self.module, "_run_git"):
with patch.object(self.module, "_ref_has_commit", return_value=True):
with patch.object(self.module, "_workload_config_diff_exists", return_value=False):
with patch.object(self.module, "_request_json") as request_json:
result = self.module.main()
self.assertEqual(result, 0)
request_json.assert_not_called()
def test_main_creates_pr_as_draft_when_notification_delay_enabled(self) -> None:
env = {
"SYSTEM_ACCESSTOKEN": "token",
"SYSTEM_COLLECTIONURI": "https://dev.azure.com/example",
"SYSTEM_TEAMPROJECT": "Project",
"BUILD_REPOSITORY_ID": "repo-id",
"BUILD_BUILDNUMBER": "42",
"BUILD_BUILDID": "1001",
"ROLLING_PR_DELAY_REVIEWER_NOTIFICATIONS": "true",
}
created_bodies: list[dict[str, object]] = []
def request_json(url: str, headers: dict[str, str], method: str = "GET", body: dict[str, object] | None = None):
if method == "POST" and url.endswith("/pullrequests?api-version=7.1"):
created_bodies.append(body or {})
return {"pullRequestId": 123}
raise AssertionError(f"Unexpected request: {method} {url}")
with patch.dict(os.environ, env, clear=False):
with patch.object(
sys,
"argv",
[
"ensure_rolling_pr.py",
"--repo-root",
"/tmp/repo",
"--workload",
"intune",
"--drift-branch",
"drift/intune",
"--baseline-branch",
"main",
"--pr-title",
"Intune drift review (rolling)",
],
):
with patch.object(self.module, "_query_prs", side_effect=[[], []]):
with patch.object(self.module, "_run_git"):
with patch.object(self.module, "_ref_has_commit", return_value=True):
with patch.object(self.module, "_workload_config_diff_exists", return_value=True):
with patch.object(self.module, "_tree_id_for_commitish", return_value="tree123"):
with patch.object(self.module, "_find_matching_abandoned_pr", return_value=(None, "")):
with patch.object(self.module, "_request_json", side_effect=request_json):
result = self.module.main()
self.assertEqual(result, 0)
self.assertEqual(len(created_bodies), 1)
self.assertTrue(created_bodies[0]["isDraft"])
def test_main_skips_active_pr_patch_when_already_up_to_date(self) -> None:
env = {
"SYSTEM_ACCESSTOKEN": "token",
"SYSTEM_COLLECTIONURI": "https://dev.azure.com/example",
"SYSTEM_TEAMPROJECT": "Project",
"BUILD_REPOSITORY_ID": "repo-id",
}
with patch.dict(os.environ, env, clear=False):
with patch.object(
sys,
"argv",
[
"ensure_rolling_pr.py",
"--repo-root",
"/tmp/repo",
"--workload",
"intune",
"--drift-branch",
"drift/intune",
"--baseline-branch",
"main",
"--pr-title",
"Intune drift review (rolling)",
],
):
with patch.object(
self.module,
"_query_prs",
return_value=[
{
"pullRequestId": 123,
"title": "Intune drift review (rolling)",
"description": "Existing description with summary",
"completionOptions": {"mergeStrategy": "rebase"},
"url": "https://dev.azure.com/example/_apis/git/repositories/repo/pullRequests/123",
}
],
):
with patch.object(self.module, "_request_json") as request_json:
result = self.module.main()
self.assertEqual(result, 0)
request_json.assert_not_called()
if __name__ == "__main__":
unittest.main()