1
0
mirror of https://github.com/home-assistant/core.git synced 2026-07-04 05:05:38 +01:00
Files
core/tests/scripts/check_requirements/test_main.py
T

165 lines
5.0 KiB
Python

"""Tests for script.check_requirements.__main__ (CLI entry point)."""
import json
from pathlib import Path
import pytest
from script.check_requirements import __main__ as main_mod
from script.check_requirements.gate import GateDecision
from script.check_requirements.pypi import ProvenanceResult, PypiPackageInfo
_SHA = "abc1234def5678abc1234def5678abc1234def56"
def _write_bump_diff(path: Path) -> None:
path.write_text(
"diff --git a/requirements_all.txt b/requirements_all.txt\n"
"--- a/requirements_all.txt\n"
"+++ b/requirements_all.txt\n"
"@@ -1 +1 @@\n"
"-pkg==1.0.0\n"
"+pkg==1.1.0\n",
encoding="utf-8",
)
def _mock_pypi(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
"script.check_requirements.runner.fetch_package_info",
lambda name, version: PypiPackageInfo(
project_urls={"Source": "https://github.com/example/pkg"},
repo_url="https://github.com/example/pkg",
file_provenance_urls=["whatever"],
found=True,
),
)
monkeypatch.setattr(
"script.check_requirements.runner.check_provenance",
lambda info: ProvenanceResult(
has_attestation=True,
publisher_kind="GitHub",
recognized_publisher=True,
detail="ok",
),
)
def test_main_writes_artifact(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
"""When the gate runs the checks, the CLI writes a non-skipped artifact."""
diff_file = tmp_path / "diff.patch"
_write_bump_diff(diff_file)
output_file = tmp_path / "results.json"
monkeypatch.setattr(
main_mod, "_resolve_skip", lambda pr, sha: GateDecision(False, "running checks")
)
_mock_pypi(monkeypatch)
exit_code = main_mod.main(
[
"--pr-number",
"42",
"--head-sha",
_SHA,
"--diff",
str(diff_file),
"--output",
str(output_file),
]
)
assert exit_code == 0
payload = json.loads(output_file.read_text(encoding="utf-8"))
assert payload["skip_aw"] is False
assert payload["pr_number"] == 42
assert payload["head_sha"] == _SHA
assert payload["packages"][0]["name"] == "pkg"
assert (
f"https://github.com/home-assistant/core/commit/{_SHA}"
in payload["rendered_comment"]
)
assert "check_requirements: 1 package change(s)" in capsys.readouterr().err
def test_main_skips_but_still_writes_artifact(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""When the gate skips, no checks run but a skip-flagged artifact is written."""
diff_file = tmp_path / "diff.patch"
_write_bump_diff(diff_file)
output_file = tmp_path / "results.json"
monkeypatch.setattr(
main_mod, "_resolve_skip", lambda pr, sha: GateDecision(True, "nothing changed")
)
# The checks must not run when skipping; make them explode if they do.
def _boom(name: str, version: str) -> None:
raise AssertionError("checks must not run when the gate skips")
monkeypatch.setattr("script.check_requirements.runner.fetch_package_info", _boom)
exit_code = main_mod.main(
[
"--pr-number",
"42",
"--head-sha",
_SHA,
"--diff",
str(diff_file),
"--output",
str(output_file),
]
)
assert exit_code == 0
payload = json.loads(output_file.read_text(encoding="utf-8"))
assert payload == {
"version": 1,
"pr_number": 42,
"skip_aw": True,
"head_sha": _SHA,
"needs_agent": False,
"packages": [],
"rendered_comment": "",
}
def test_resolve_skip_without_credentials_runs(monkeypatch: pytest.MonkeyPatch) -> None:
"""Missing repo/token falls open (runs) without ever calling the gate."""
monkeypatch.delenv("GITHUB_REPOSITORY", raising=False)
monkeypatch.delenv("GITHUB_TOKEN", raising=False)
def _boom(*args: object, **kwargs: object) -> None:
raise AssertionError("decide_skip must not be called without credentials")
monkeypatch.setattr(main_mod, "decide_skip", _boom)
assert main_mod._resolve_skip(42, _SHA).skip is False
def test_main_missing_diff_file_exits(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
"""A missing --diff file triggers argparse's error path (SystemExit)."""
output_file = tmp_path / "results.json"
missing_diff = tmp_path / "does-not-exist.patch"
with pytest.raises(SystemExit) as excinfo:
main_mod.main(
[
"--pr-number",
"1",
"--diff",
str(missing_diff),
"--output",
str(output_file),
]
)
assert excinfo.value.code == 2 # argparse error exit
captured = capsys.readouterr()
assert "not found" in captured.err