diff --git a/templates/assembly-root/scripts/validate-pins.py b/templates/assembly-root/scripts/validate-pins.py index 0fde1257..65607ce8 100755 --- a/templates/assembly-root/scripts/validate-pins.py +++ b/templates/assembly-root/scripts/validate-pins.py @@ -1077,8 +1077,14 @@ def _check_workflow_refs_for_leg(refs, repository: str, path: str, """Fact 3: split from `_check_leg` for #132 — every workflow `@` reference naming this leg's repository must agree with the gitlink. A mismatch is one `bump-leg.py` clears, since it moves every one (#478). + + THE NOTE COUNTS THE REFERENCES THAT AGREE (#739). It counted every + reference naming the repository, so one off its gitlink was its finding + and, beside it, `1 workflow @ reference(s) agree with the gitlink`. + Only those at the gitlink are counted, `N of M` where some are not, and + no note is printed where none is. """ - seen = 0 + seen = agree = 0 for wf_path, wf_repo, wf_sha in refs: if wf_repo != repository: continue @@ -1092,8 +1098,11 @@ def _check_workflow_refs_for_leg(refs, repository: str, path: str, ) report.curable.append(Curable(len(report.findings) - 1, role, path, gitlink, wf_sha)) - if seen: - report.note(f"{repository}: {seen} workflow @ reference(s) " + else: + agree += 1 + if agree: + counted = str(agree) if agree == seen else f"{agree} of {seen}" + report.note(f"{repository}: {counted} workflow @ reference(s) " f"agree with the gitlink") diff --git a/tests/test_pin_validator.py b/tests/test_pin_validator.py index cefcc200..1fad48fa 100644 --- a/tests/test_pin_validator.py +++ b/tests/test_pin_validator.py @@ -11,6 +11,8 @@ import subprocess +import pytest + from conftest import git, run_script OTHER_SHA = "0123456789abcdef0123456789abcdef01234567" @@ -165,6 +167,38 @@ def test_a_workflow_ref_that_agrees_with_the_gitlink_passes(project): assert "workflow @ reference(s) agree" in result.stdout +def code_workflow(project, *shas: str) -> None: + """`.github/workflows/lane.yml`, one job per sha, each naming the code + leg's repository at it.""" + (project / ".github" / "workflows" / "lane.yml").write_text( + "name: lane\non:\n pull_request:\njobs:\n" + "".join( + f" lane{at}:\n uses: testorg/Atlas-code/.github/workflows/" + f"reusable.yml@{sha}\n" for at, sha in enumerate(shas))) + + +@pytest.mark.parametrize("refs, counted", [ + (("off",), None), + (("at", "off"), "1 of 2"), + (("at", "at"), "2"), +], ids=["one-off", "one-of-two-off", "both-at"]) +def test_the_agree_note_counts_only_the_references_at_the_gitlink( + project, refs, counted): + """The note counted every reference to the leg's repository, so one off + its gitlink was its finding and, beside it, `1 workflow @ + reference(s) agree with the gitlink` (#739). It counts those at the + gitlink, `N of M` where some are not, and is not printed where none + is.""" + gitlink = git("rev-parse", "HEAD:code", cwd=project).stdout.strip() + code_workflow(project, *(gitlink if ref == "at" else OTHER_SHA + for ref in refs)) + result = validate(project) + said = [line for line in result.stdout.splitlines() + if "agree with the gitlink" in line] + assert said == ([] if counted is None else [ + f" ok testorg/Atlas-code: {counted} workflow @ reference(s) " + "agree with the gitlink"]), result.stdout + result.stderr + + def test_a_ref_to_something_that_is_not_a_leg_is_ignored(project): """`actions/checkout@` is not a leg and is none of this validator's business."""