|
38 | 38 | PATCH = "@@ -10,3 +10,4 @@ flags:\n - a\n - b\n+ - c\n - d" |
39 | 39 |
|
40 | 40 |
|
41 | | -def pr(additions=1, deletions=0, draft=False, fork=False, sha="abc1234def"): |
| 41 | +def pr(additions=1, deletions=0, draft=False, fork=False, sha="abc1234def", association="MEMBER"): |
42 | 42 | return { |
43 | 43 | "number": 7, "draft": draft, "title": "Add an org to a flag", "body": "Adds one org.", |
44 | | - "user": {"login": "someone"}, "author_association": "CONTRIBUTOR", |
| 44 | + "user": {"login": "someone"}, "author_association": association, |
45 | 45 | "additions": additions, "deletions": deletions, |
46 | 46 | "head": {"sha": sha, "repo": {"full_name": "external/infra" if fork else "kernel/infra"}}, |
47 | 47 | "base": {"sha": "base000", "ref": "main", "repo": {"full_name": "kernel/infra"}}, |
@@ -97,10 +97,10 @@ def visible_words(body): |
97 | 97 |
|
98 | 98 |
|
99 | 99 | class PRRiskTests(unittest.TestCase): |
100 | | - def run_pr(self, gh, verdict=VERDICT, result=None, extra_deny="", association="MEMBER"): |
| 100 | + def run_pr(self, gh, verdict=VERDICT, result=None, extra_deny=""): |
101 | 101 | with tempfile.TemporaryDirectory() as tmp: |
102 | 102 | work = Path(tmp) |
103 | | - gate = pr_risk.gather(gh, 7, extra_deny, association, work) |
| 103 | + gate = pr_risk.gather(gh, 7, extra_deny, work) |
104 | 104 | if gate["eligible"]: |
105 | 105 | (work / "result.json").write_text(json.dumps(result or {"is_error": False, "structured_output": verdict})) |
106 | 106 | code = pr_risk.comment(gh, 7, work, "https://example.com/run") |
@@ -130,22 +130,21 @@ def test_ineligible_reasons(self): |
130 | 130 | renamed = file("b.yaml", status="renamed", previous_filename="a.yaml", additions=0, changes=0) |
131 | 131 | del renamed["patch"] |
132 | 132 | cases = { |
133 | | - "draft": (pr(draft=True), [file()], "MEMBER"), |
134 | | - "fork": (pr(fork=True), [file()], "MEMBER"), |
135 | | - "not an org member": (pr(), [file()], "CONTRIBUTOR"), |
136 | | - "author is not an org member": (pr(), [file()], "NONE"), |
137 | | - "51 changed lines": (pr(additions=30, deletions=21), [file()], "MEMBER"), |
138 | | - "deny list (`identity/**`)": (pr(), [file("identity/access.go")], "MEMBER"), |
139 | | - "deny list (`.github/**`)": (pr(), [file("ci.yml", previous_filename=".github/workflows/ci.yml")], "MEMBER"), |
140 | | - "`bin/helper` has no reviewable text diff": (pr(additions=0), [binary], "MEMBER"), |
141 | | - "`b.yaml` has no reviewable text diff": (pr(additions=0), [renamed], "MEMBER"), |
| 133 | + "draft": (pr(draft=True), [file()]), |
| 134 | + "fork": (pr(fork=True), [file()]), |
| 135 | + "not an org member": (pr(association="CONTRIBUTOR"), [file()]), |
| 136 | + "author is not an org member": (pr(association="NONE"), [file()]), |
| 137 | + "51 changed lines": (pr(additions=30, deletions=21), [file()]), |
| 138 | + "deny list (`identity/**`)": (pr(), [file("identity/access.go")]), |
| 139 | + "deny list (`.github/**`)": (pr(), [file("ci.yml", previous_filename=".github/workflows/ci.yml")]), |
| 140 | + "`bin/helper` has no reviewable text diff": (pr(additions=0), [binary]), |
| 141 | + "`b.yaml` has no reviewable text diff": (pr(additions=0), [renamed]), |
142 | 142 | } |
143 | | - for expected, (p, files, association) in cases.items(): |
| 143 | + for expected, (p, files) in cases.items(): |
144 | 144 | with self.subTest(expected=expected): |
145 | | - self.assertIn(expected, pr_risk.ineligible_reason(p, files, patterns, association)) |
146 | | - # The API reports CONTRIBUTOR for private members; only the event payload's value counts. |
147 | | - self.assertIsNone(pr_risk.ineligible_reason(pr(additions=25, deletions=25), [file()], patterns, "MEMBER")) |
148 | | - self.assertIsNone(pr_risk.ineligible_reason(pr(), [file()], patterns, "OWNER")) |
| 145 | + self.assertIn(expected, pr_risk.ineligible_reason(p, files, patterns)) |
| 146 | + self.assertIsNone(pr_risk.ineligible_reason(pr(additions=25, deletions=25), [file()], patterns)) |
| 147 | + self.assertIsNone(pr_risk.ineligible_reason(pr(association="OWNER"), [file()], patterns)) |
149 | 148 |
|
150 | 149 | def test_ineligible_without_comment_is_silent(self): |
151 | 150 | gh = FakeGitHub(pr(additions=200), [file()]) |
@@ -281,8 +280,12 @@ def test_workflow_isolates_the_model(self): |
281 | 280 | names = list(steps) |
282 | 281 | self.assertLess(names.index("Classify"), names.index("Generate app token")) |
283 | 282 | self.assertEqual(steps["Generate app token"]["with"]["permission-pull-requests"], "write") |
284 | | - self.assertEqual(steps["Gather"]["env"]["AUTHOR_ASSOCIATION"], |
285 | | - "${{ github.event.pull_request.author_association }}") |
| 283 | + # The workflow token and event payload both report private members as CONTRIBUTOR. |
| 284 | + self.assertEqual(steps["Gather"]["env"]["GH_TOKEN"], "${{ steps.read-token.outputs.token }}") |
| 285 | + read = steps["Generate read token"]["with"] |
| 286 | + self.assertEqual({k: v for k, v in read.items() if k.startswith("permission-")}, |
| 287 | + {"permission-contents": "read", "permission-pull-requests": "read"}) |
| 288 | + self.assertLess(names.index("Generate read token"), names.index("Gather")) |
286 | 289 | triggers = workflow[True]["workflow_call"] |
287 | 290 | self.assertEqual(set(triggers["secrets"]), {"ADMIN_APP_ID", "ADMIN_APP_PRIVATE_KEY", "ANTHROPIC_API_KEY"}) |
288 | 291 |
|
|
0 commit comments