Files
horizon/tests/test_overlap_note.py
Ludovic MarieandClaude Opus 5.5 ca0888663e Overlap note: one comment naming the open pull requests doing the same work
On open and push, overlap-note.yml (pull_request_target, main's script only)
lists, in one comment edited on every push, the other open pull requests that
close the same issue or change the same functions. Functions come from git's
own rust/python hunk headers, which name indented methods (GitHub's stop at
`impl Game<'_>`). The heads are fetched as objects and diffed, never checked
out; hooks, fsmonitor, external diff and textconv are off.

Measured on the 207 open pull requests: one shared function, or a few of a
big pull request's hundred, was mostly chance, so a pair needs a shared
issue, or 2 shared functions and a tenth of the bigger one's; functions 5
compared pull requests change, probes, tests and stacks don't count.
21 pairs (34 notes): 16 related (4 duplicates), 4 doubtful, 1 unrelated.

Part of #3859.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 21:36:37 +01:00

148 lines
5.9 KiB
Python

import unittest
from pathlib import Path
from tools.ci import overlap_note as ov
ROOT = Path(__file__).resolve().parents[1]
DIFF = """\
diff --git a/crates/horizon-client/src/game/dragon.rs b/crates/horizon-client/src/game/dragon.rs
index 1..2 100644
--- a/crates/horizon-client/src/game/dragon.rs
+++ b/crates/horizon-client/src/game/dragon.rs
@@ -440 +440,2 @@ impl Dragon {
- let a = 1;
+ let a = 2;
+ let b = 3;
@@ -2092,0 +2093,3 @@ pub fn tick_dragon(&mut self) {
+ if x {
+ y();
+ }
@@ -2200,0 +2205,4 @@ fn last_existing(&self) -> u32 {
+
+ /// A new helper.
+ pub(crate) fn brand_new(&self) {
+ }
@@ -2300 +2310 @@ fn helper() {
- a
+ b
@@ -10 +10 @@ use std::fmt;
-use a;
+use b;
diff --git a/tools/lan_e2e.py b/tools/lan_e2e.py
--- a/tools/lan_e2e.py
+++ b/tools/lan_e2e.py
@@ -5 +5 @@ def check_chest(args):
- x
+ y
diff --git a/crates/horizon-client/examples/probe/mob_ai_probe.rs b/crates/horizon-client/examples/probe/mob_ai_probe.rs
--- a/crates/horizon-client/examples/probe/mob_ai_probe.rs
+++ b/crates/horizon-client/examples/probe/mob_ai_probe.rs
@@ -214,0 +215,2 @@ fn goal_name(m: &Mob, name: &str) -> String {
+ "a" => 1,
+ "b" => 2,
diff --git a/old.rs b/old.rs
deleted file mode 100644
--- a/old.rs
+++ /dev/null
@@ -1 +0,0 @@ fn gone() {
-x
"""
def pull(n, funcs=(), closes=(), files=(), changed=None, author="a"):
p = ov.Pull(n, f"PR {n}", author, False, f"{n:040x}", list(files), changed or len(files), set(closes))
p.funcs = set(funcs)
return p
def fx(*names, path="a.rs"):
return {(path, n) for n in names}
class FunctionTests(unittest.TestCase):
def test_functions_from_a_diff(self):
self.assertEqual(ov.functions(DIFF), {
("crates/horizon-client/src/game/dragon.rs", "tick_dragon"),
("crates/horizon-client/src/game/dragon.rs", "helper"),
("tools/lan_e2e.py", "check_chest"),
})
# `impl Dragon` and `use` headers name no function; a hunk that only adds a new function after
# `last_existing` doesn't count; probes, tests and deleted files don't either.
def test_empty(self):
self.assertEqual(ov.functions(""), set())
class OverlapTests(unittest.TestCase):
def test_same_issue(self):
me, o = pull(1, closes={9}), pull(2, closes={9, 10})
self.assertEqual(ov.overlaps(me, [o]), [(o, {9}, set())])
def test_two_shared_functions_and_a_tenth(self):
me = pull(1, fx("a", "b", "c"))
o = pull(2, fx("a", "b", *[f"x{i}" for i in range(10)]))
self.assertEqual([t[0].number for t in ov.overlaps(me, [o])], [2])
big = pull(3, fx("a", "b", *[f"x{i}" for i in range(30)]))
self.assertEqual(ov.overlaps(me, [big]), []) # 2 of 32: chance
self.assertEqual(ov.overlaps(pull(1, fx("a")), [pull(2, fx("a"))]), []) # one function: chance
def test_hot_functions_dont_count(self):
me = pull(1, fx("new", "draw_frame", "mine"))
others = [pull(n, fx("new", "draw_frame")) for n in range(2, 6)] + [pull(9, fx("new", "draw_frame", "mine"))]
self.assertEqual(ov.overlaps(me, others), [])
def test_stacks_and_integration_branches_left_out(self):
me, o = pull(1, fx("a", "b")), pull(2, fx("a", "b"))
self.assertEqual(ov.overlaps(me, [o], stacked=lambda a, b: True), [])
self.assertEqual(ov.overlaps(me, [pull(3, fx("a", "b"), changed=150)]), [])
def test_most_shared_first_and_five_at_most(self):
shared = {n: fx(*(f"f{n}_{i}" for i in range(n))) for n in range(2, 9)} # 35 functions in all
me = pull(1, set().union(*shared.values()))
others = [pull(n, shared[n]) for n in shared] + [pull(20)]
found = ov.overlaps(me, others) # 4 or more of 35 is a tenth
self.assertEqual([t[0].number for t in found], [8, 7, 6, 5, 4])
me.closes = {5}
others.append(pull(30, closes={5}))
self.assertEqual(ov.overlaps(me, others)[0][0].number, 30)
def test_candidates_share_a_file_or_an_issue(self):
me = pull(1, files=["src/a.rs", "Cargo.lock", "src/lib.rs"], closes={4})
cands = [pull(2, files=["src/a.rs"]), pull(3, files=["Cargo.lock", "src/lib.rs"]), pull(4, closes={4}),
pull(5, files=["src/a.rs"], changed=500)]
self.assertEqual([p.number for p in ov.candidates(me, cands)], [4, 2])
class NoteTests(unittest.TestCase):
def test_text(self):
o = pull(7, author="dev")
o.draft = True
text = ov.note([(o, {3}, {("crates/x/src/a.rs", f) for f in "abcdef"})])
self.assertTrue(text.startswith(ov.MARKER + "\n🤖 Overlap:"))
self.assertIn("- #7 (draft) by dev: also closes #3; changes `a` in `a.rs`, `b` in `a.rs`, `c` in `a.rs`, "
"`d` in `a.rs` and 2 more", text)
self.assertNotIn("@", text) # names, never mentions
self.assertIsNone(ov.note([]))
self.assertTrue(ov.CLEARED.startswith(ov.MARKER))
class WorkflowTests(unittest.TestCase):
def test_workflow_is_safe(self):
text = (ROOT / ".github/workflows/overlap-note.yml").read_text()
run_lines = [l.strip() for l in text.splitlines() if l.strip().startswith("run:")]
self.assertEqual(run_lines, ["run: python3 tools/ci/overlap_note.py event"])
for needed in ("pull_request_target", "ref: main", "persist-credentials: false", "filter: blob:none",
"sparse-checkout: |\n tools/ci/overlap_note.py\n sparse-checkout-cone-mode"):
self.assertIn(needed, text)
for bad in ("contents: write", "issues: write", "head.sha", "head.ref", "github.event.pull_request.body"):
self.assertNotIn(bad, text)
def test_git_never_runs_their_code(self):
for flag in ("core.hooksPath=/dev/null", "core.fsmonitor=false", "diff.external="):
self.assertIn(flag, ov.SAFE_GIT)
if __name__ == "__main__":
unittest.main()