fix(kvb-git-close-issues): drop false references found on a real PR
🧪 Test / 🧪 Lock + lint (push) Canceled after 0s

A read-only run of issues.py on infinito-nexus/core#1326 listed #0 and #1 from CI row names like WordPress#0 and docs#1, reported #1324 twice (plain and as infinito-nexus/core#1324 from the linked issue), and offered the pull request's own number. A bare # now needs no word character or slash before it and a number from 1, the required --repo maps the pull request's own repository to the plain form and merges the sources, and the pull request's number is skipped; the skill passes --repo and reads number. On #1326 only #1324 closing remains.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin Veen-BirkenbachandClaude Opus 5.5 committed 2026-11-03 17:57:08 +01:00
1 parent 6865ae718a
commit 32f58712e5
3 files changed
+26 -14

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@ body and the commits, a trailing number in the branch name, and the issues
GitHub already links:
```bash
gh pr view <pr> --json body,headRefName,commits,closingIssuesReferences | issues.py
gh pr view <pr> --json number,body,headRefName,commits,closingIssuesReferences | issues.py --repo <owner/name>
```
## Step 2: verify
+18 -10
View File
@@ -2,9 +2,11 @@
"""List the issues a pull request references, from `gh pr view --json` on stdin.
Args:
stdin: JSON with body, headRefName, commits and closingIssuesReferences,
as `gh pr view <pr> --json body,headRefName,commits,closingIssuesReferences`
prints it.
stdin: JSON with number, body, headRefName, commits and
closingIssuesReferences, as `gh pr view <pr> --json
number,body,headRefName,commits,closingIssuesReferences` prints it.
--repo: owner/name of the pull request's repository; its own references
are reported without a repository.
--json: print the candidates as JSON instead of tab-separated lines.
Exit codes:
@@ -19,7 +21,7 @@ import re
import sys
KEYWORD = r"(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)"
REF = r"(?:(?P<repo>[\w.-]+/[\w.-]+)#|https://github\.com/(?P<url>[\w.-]+/[\w.-]+)/issues/|#)(?P<num>\d+)"
REF = r"(?:(?P<repo>[\w.-]+/[\w.-]+)#|https://github\.com/(?P<url>[\w.-]+/[\w.-]+)/issues/|(?<![\w/])#)(?P<num>[1-9]\d*)"
PATTERN = re.compile(rf"(?P<kw>\b{KEYWORD}\b:?\s+)?{REF}", re.IGNORECASE)
BRANCH = re.compile(r"[/-](\d+)$")
@@ -40,7 +42,7 @@ def scan(text: str, source: str, found: dict) -> None:
entry["sources"].append(source)
def candidates(pr: dict) -> list[dict]:
def candidates(pr: dict, own: str) -> list[dict]:
found: dict = {}
scan(pr.get("body", ""), "body", found)
for commit in pr.get("commits", []):
@@ -57,14 +59,20 @@ def candidates(pr: dict) -> list[dict]:
entry = found.setdefault(key, {"closing": False, "sources": []})
entry["closing"] = True
entry["sources"].append("linked")
return [
{"repo": repo, "issue": num, **entry}
for (repo, num), entry in sorted(found.items())
]
merged: dict = {}
for (repo, num), entry in found.items():
key = ("" if repo.lower() == own.lower() else repo, num)
if key == ("", pr.get("number")):
continue
target = merged.setdefault(key, {"closing": False, "sources": []})
target["closing"] = target["closing"] or entry["closing"]
target["sources"] += [s for s in entry["sources"] if s not in target["sources"]]
return [{"repo": repo, "issue": num, **entry} for (repo, num), entry in sorted(merged.items())]
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("--repo", required=True)
parser.add_argument("--json", action="store_true")
args = parser.parse_args()
try:
@@ -73,7 +81,7 @@ def main() -> int:
fail("stdin is not the JSON of gh pr view --json")
if not isinstance(pr, dict):
fail("stdin is not a pull request object")
rows = candidates(pr)
rows = candidates(pr, args.repo)
if args.json:
print(json.dumps(rows, indent=1))
return 0
+7 -3
View File
@@ -11,7 +11,11 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
SCRIPT = REPO_ROOT / "skills" / "kvb-git-close-issues" / "scripts" / "issues.py"
PR = {
"body": "Fixes #12 and touches #13.\nCloses: other/repo#7\nSee https://github.com/a/b/issues/9",
"number": 40,
"body": (
"Fixes #12 and touches #13.\nCloses: other/repo#7\nSee https://github.com/a/b/issues/9\n"
"Rows WordPress#0 and docs#1 are not issues; this is #40."
),
"headRefName": "fix/sys-ctl-hlth-runtime/vulnerability-engines/1324",
"commits": [
{"oid": "abcdef1234567", "messageHeadline": "fix: guard", "messageBody": "Resolved #13"},
@@ -25,7 +29,7 @@ PR = {
def _run(payload: str) -> subprocess.CompletedProcess:
return subprocess.run(
[sys.executable, str(SCRIPT), "--json"],
[sys.executable, str(SCRIPT), "--repo", "Owner/repo", "--json"],
input=payload,
check=False,
capture_output=True,
@@ -46,7 +50,7 @@ class TestIssues(unittest.TestCase):
("other/repo", 7): (True, ["body"]),
("a/b", 9): (False, ["body"]),
("", 1324): (False, ["branch"]),
("owner/repo", 21): (True, ["linked"]),
("", 21): (True, ["linked"]),
},
)