mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
179 lines
6.3 KiB
Python
179 lines
6.3 KiB
Python
import importlib.util
|
|
import shutil
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
MODULE_PATH = (
|
|
Path(__file__).resolve().parents[2]
|
|
/ ".github"
|
|
/ "scripts"
|
|
/ "changelog_attribution.py"
|
|
)
|
|
SPEC = importlib.util.spec_from_file_location("changelog_attribution", MODULE_PATH)
|
|
changelog_attribution = importlib.util.module_from_spec(SPEC)
|
|
assert SPEC.loader is not None
|
|
SPEC.loader.exec_module(changelog_attribution)
|
|
|
|
|
|
def make_component(tmp_path):
|
|
component = tmp_path / "prowler"
|
|
fragments_dir = component / "changelog.d"
|
|
fragments_dir.mkdir(parents=True)
|
|
return component, fragments_dir
|
|
|
|
|
|
def fake_git_mv(*args):
|
|
if args[0] != "mv":
|
|
raise AssertionError(f"Unexpected git command: {args}")
|
|
shutil.move(args[1], args[2])
|
|
return ""
|
|
|
|
|
|
def fail_git(*args):
|
|
raise AssertionError(f"Unexpected git command: {args}")
|
|
|
|
|
|
def fail_api(*args):
|
|
raise AssertionError(f"Unexpected GitHub API call: {args}")
|
|
|
|
|
|
def run_main(monkeypatch, component, *extra_args):
|
|
monkeypatch.setattr(
|
|
sys,
|
|
"argv",
|
|
["changelog_attribution.py", str(component), *extra_args],
|
|
)
|
|
return changelog_attribution.main()
|
|
|
|
|
|
class TestChangelogAttribution:
|
|
def test_renames_slug_fragment_to_resolved_pr_number(self, tmp_path, monkeypatch):
|
|
component, fragments_dir = make_component(tmp_path)
|
|
fragment = fragments_dir / "add-workflow.fixed.md"
|
|
fragment.write_text("Fix changelog workflow.\n")
|
|
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "find_adding_commit", lambda path: "abc123"
|
|
)
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "pr_from_api", lambda repo, sha: 11572
|
|
)
|
|
monkeypatch.setattr(changelog_attribution, "git", fake_git_mv)
|
|
|
|
assert run_main(monkeypatch, component) == 0
|
|
assert not fragment.exists()
|
|
assert (fragments_dir / "11572.fixed.md").read_text() == (
|
|
"Fix changelog workflow.\n"
|
|
)
|
|
|
|
def test_appends_counter_when_pr_fragment_already_exists(
|
|
self, tmp_path, monkeypatch
|
|
):
|
|
component, fragments_dir = make_component(tmp_path)
|
|
(fragments_dir / "11572.fixed.md").write_text("Existing fix.\n")
|
|
fragment = fragments_dir / "another-fix.fixed.md"
|
|
fragment.write_text("Another fix.\n")
|
|
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "find_adding_commit", lambda path: "abc123"
|
|
)
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "pr_from_api", lambda repo, sha: 11572
|
|
)
|
|
monkeypatch.setattr(changelog_attribution, "git", fake_git_mv)
|
|
|
|
assert run_main(monkeypatch, component) == 0
|
|
assert (fragments_dir / "11572.fixed.md").read_text() == "Existing fix.\n"
|
|
assert (fragments_dir / "11572.fixed.1.md").read_text() == "Another fix.\n"
|
|
|
|
def test_uses_subject_fallback_when_api_is_disabled(self, tmp_path, monkeypatch):
|
|
component, fragments_dir = make_component(tmp_path)
|
|
fragment = fragments_dir / "fallback.added.md"
|
|
fragment.write_text("Add fallback behavior.\n")
|
|
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "find_adding_commit", lambda path: "abc123"
|
|
)
|
|
monkeypatch.setattr(
|
|
changelog_attribution,
|
|
"pr_from_api",
|
|
fail_api,
|
|
)
|
|
monkeypatch.setattr(changelog_attribution, "pr_from_subject", lambda sha: 42)
|
|
monkeypatch.setattr(changelog_attribution, "git", fake_git_mv)
|
|
|
|
assert run_main(monkeypatch, component, "--no-api") == 0
|
|
assert not fragment.exists()
|
|
assert (fragments_dir / "42.added.md").read_text() == "Add fallback behavior.\n"
|
|
|
|
def test_renames_unresolved_fragment_to_orphan(self, tmp_path, monkeypatch, capsys):
|
|
component, fragments_dir = make_component(tmp_path)
|
|
fragment = fragments_dir / "manual.changed.md"
|
|
fragment.write_text("Change manual entry.\n")
|
|
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "find_adding_commit", lambda path: None
|
|
)
|
|
monkeypatch.setattr(changelog_attribution, "git", fake_git_mv)
|
|
|
|
assert run_main(monkeypatch, component) == 0
|
|
assert not fragment.exists()
|
|
assert (fragments_dir / "+manual.changed.md").read_text() == (
|
|
"Change manual entry.\n"
|
|
)
|
|
assert "Could not resolve a PR" in capsys.readouterr().out
|
|
|
|
def test_rejects_malformed_fragment_names(self, tmp_path, monkeypatch, capsys):
|
|
component, fragments_dir = make_component(tmp_path)
|
|
fragment = fragments_dir / "bad.bugfix.md"
|
|
fragment.write_text("Invalid type.\n")
|
|
|
|
monkeypatch.setattr(
|
|
changelog_attribution,
|
|
"git",
|
|
fail_git,
|
|
)
|
|
|
|
assert run_main(monkeypatch, component) == 1
|
|
assert fragment.exists()
|
|
assert "Malformed fragment filename" in capsys.readouterr().out
|
|
|
|
def test_rejects_malformed_names_before_renaming_any_fragment(
|
|
self, tmp_path, monkeypatch, capsys
|
|
):
|
|
component, fragments_dir = make_component(tmp_path)
|
|
valid_fragment = fragments_dir / "valid.fixed.md"
|
|
malformed_fragment = fragments_dir / "bad.bugfix.md"
|
|
valid_fragment.write_text("Valid fix.\n")
|
|
malformed_fragment.write_text("Invalid type.\n")
|
|
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "find_adding_commit", lambda path: "abc123"
|
|
)
|
|
monkeypatch.setattr(
|
|
changelog_attribution, "pr_from_api", lambda repo, sha: 11572
|
|
)
|
|
monkeypatch.setattr(changelog_attribution, "git", fail_git)
|
|
|
|
assert run_main(monkeypatch, component) == 1
|
|
assert valid_fragment.read_text() == "Valid fix.\n"
|
|
assert malformed_fragment.read_text() == "Invalid type.\n"
|
|
assert not (fragments_dir / "11572.fixed.md").exists()
|
|
assert "Malformed fragment filename" in capsys.readouterr().out
|
|
|
|
def test_skips_fragments_that_already_start_with_pr_number(
|
|
self, tmp_path, monkeypatch
|
|
):
|
|
component, fragments_dir = make_component(tmp_path)
|
|
fragment = fragments_dir / "11572.added.md"
|
|
fragment.write_text("Already attributed.\n")
|
|
|
|
monkeypatch.setattr(
|
|
changelog_attribution,
|
|
"git",
|
|
fail_git,
|
|
)
|
|
|
|
assert run_main(monkeypatch, component) == 0
|
|
assert fragment.read_text() == "Already attributed.\n"
|