From 6debbf88a791c42049c0be29699954776c9b9f87 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Thu, 7 May 2026 18:51:45 +0200 Subject: [PATCH] verify-action-build: pass cleanly on removal-only PRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The --from-pr branch fails for removal-only PRs (e.g. #818) because extract_action_refs_from_diff correctly returns no refs when a PR only removes entries — there's nothing new to verify. The CLI treated that as a fatal error. Distinguish the two empty-result cases: a diff-fetch failure still exits 1, while a successfully-fetched diff with no added refs exits 0 with a "nothing to verify" message. --- utils/tests/verify_action_build/test_cli.py | 31 +++++++++++++++++++++ utils/verify_action_build/cli.py | 15 +++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/utils/tests/verify_action_build/test_cli.py b/utils/tests/verify_action_build/test_cli.py index 9c97b3fd0..9464367ed 100644 --- a/utils/tests/verify_action_build/test_cli.py +++ b/utils/tests/verify_action_build/test_cli.py @@ -44,3 +44,34 @@ def test_no_gh_without_token_exits(self): with pytest.raises(SystemExit) as exc_info: main() assert exc_info.value.code == 1 + + def test_from_pr_with_no_added_refs_passes(self): + removal_only_diff = ( + "diff --git a/actions.yml b/actions.yml\n" + "--- a/actions.yml\n" + "+++ b/actions.yml\n" + "@@ -10,5 +10,0 @@\n" + "-some-org/some-action:\n" + "- " + "a" * 40 + ":\n" + "- tag: v1.0.0\n" + ) + with mock.patch("sys.argv", ["verify-action-build", "--from-pr", "999"]): + with mock.patch("shutil.which", return_value="/usr/bin/docker"): + with mock.patch( + "verify_action_build.cli.GitHubClient" + ) as gh_cls: + gh_cls.return_value.get_pr_diff.return_value = removal_only_diff + with pytest.raises(SystemExit) as exc_info: + main() + assert exc_info.value.code == 0 + + def test_from_pr_when_diff_fetch_fails_errors(self): + with mock.patch("sys.argv", ["verify-action-build", "--from-pr", "999"]): + with mock.patch("shutil.which", return_value="/usr/bin/docker"): + with mock.patch( + "verify_action_build.cli.GitHubClient" + ) as gh_cls: + gh_cls.return_value.get_pr_diff.return_value = None + with pytest.raises(SystemExit) as exc_info: + main() + assert exc_info.value.code == 1 diff --git a/utils/verify_action_build/cli.py b/utils/verify_action_build/cli.py index 2a106dd1f..edaf073b9 100644 --- a/utils/verify_action_build/cli.py +++ b/utils/verify_action_build/cli.py @@ -26,7 +26,7 @@ from .console import console from .dependabot import check_dependabot_prs from .github_client import GitHubClient -from .pr_extraction import extract_action_refs_from_pr +from .pr_extraction import extract_action_refs_from_diff from .verification import SECURITY_CHECKLIST_URL, verify_single_action @@ -122,10 +122,17 @@ def main() -> None: gh = GitHubClient(token=args.github_token) if args.from_pr: - action_refs = extract_action_refs_from_pr(args.from_pr, gh=gh) - if not action_refs: - console.print(f"[red]Error:[/red] could not extract action reference from PR #{args.from_pr}") + diff_text = gh.get_pr_diff(args.from_pr) + if diff_text is None: + console.print(f"[red]Error:[/red] could not fetch diff for PR #{args.from_pr}") _exit(1) + action_refs = extract_action_refs_from_diff(diff_text) + if not action_refs: + console.print( + f"No added action references in PR #{args.from_pr} — nothing to verify " + "(removal-only or non-action changes)." + ) + _exit(0) for ref in action_refs: console.print(f" Extracted action reference from PR #{args.from_pr}: [bold]{ref}[/bold]") passed = all(