Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions pr-status/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,14 @@ scripts/pr_status.py diagnose # detect from current branch

## Drilling Into Specific Areas

After running `diagnose`, use these commands for deeper investigation:
After running `diagnose`, use these commands for deeper investigation.
All subcommands accept PR URLs or `--repo owner/repo` for cross-repo context:

### CI Failures

```bash
# Get run IDs from failed checks
scripts/pr_status.py failed-runs 123
scripts/pr_status.py failed-runs https://github.com/org/repo/pull/123

# Analyze logs for a specific run (pass PR URL for cross-repo context)
scripts/pr_status.py analyze-logs 789012 https://github.com/org/repo/pull/123
Expand All @@ -94,37 +95,38 @@ scripts/pr_status.py analyze-logs 789012 https://github.com/org/repo/pull/123

```bash
# All comments and reviews
scripts/pr_status.py comments 123
scripts/pr_status.py comments https://github.com/org/repo/pull/123

# Bot comments only (renovate[bot], dependabot[bot], etc.)
scripts/pr_status.py bot-comments 123
scripts/pr_status.py bot-comments https://github.com/org/repo/pull/123
```

### Check Details

```bash
# Full check results with required vs optional
scripts/pr_status.py checks 123
scripts/pr_status.py checks https://github.com/org/repo/pull/123

# Branch protection required checks
scripts/pr_status.py required-checks 123
scripts/pr_status.py required-checks https://github.com/org/repo/pull/123

# Compare required vs actual — find what's missing
scripts/pr_status.py missing-checks 123
scripts/pr_status.py missing-checks https://github.com/org/repo/pull/123
```

### PR Metadata

```bash
scripts/pr_status.py status 123
scripts/pr_status.py status https://github.com/org/repo/pull/123
```

## Cross-Repo Support

Pass `--repo owner/repo` for PRs in different repos, or use a full URL:
All subcommands accept `--repo owner/repo` or a full PR URL for cross-repo work:

```bash
scripts/pr_status.py diagnose --repo org/other-repo 42
scripts/pr_status.py checks --repo org/other-repo 42
scripts/pr_status.py diagnose https://github.com/org/other-repo/pull/42
```

Expand Down
4 changes: 2 additions & 2 deletions pr-status/scripts/pr_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -1043,12 +1043,11 @@ def build_parser() -> argparse.ArgumentParser:
prog="pr_status",
description="PR Status Analyzer — diagnose why a PR can't merge",
)
parser.add_argument("--repo", help="Repository in owner/repo format")

sub = parser.add_subparsers(dest="command", required=True)

def _add_pr_subcommand(name: str, help_text: str, *, has_pr: bool = True, has_format: bool = True) -> argparse.ArgumentParser:
p = sub.add_parser(name, help=help_text)
p.add_argument("--repo", help="Repository in owner/repo format")
if has_format:
p.add_argument("--format", choices=["text", "json"], default="text", help="Output format")
if has_pr:
Expand All @@ -1066,6 +1065,7 @@ def _add_pr_subcommand(name: str, help_text: str, *, has_pr: bool = True, has_fo

# analyze-logs has run_id instead of pr, but accepts optional pr for repo detection
p = sub.add_parser("analyze-logs", help="Download and analyze failed CI logs")
p.add_argument("--repo", help="Repository in owner/repo format")
p.add_argument("run_id", help="GitHub Actions run ID")
p.add_argument("pr", nargs="?", help="PR number or URL (for repo detection)")

Expand Down
27 changes: 23 additions & 4 deletions pr-status/scripts/test_pr_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,30 @@ def test_diagnose_accepts_pr_number(self):
args = parser.parse_args(["diagnose", "123"])
assert args.pr == "123"

def test_global_repo_flag(self):
def test_repo_flag_on_subcommand(self):
parser = build_parser()
args = parser.parse_args(["--repo", "org/repo", "status", "42"])
args = parser.parse_args(["status", "--repo", "org/repo", "42"])
assert args.repo == "org/repo"
assert args.command == "status"
assert args.pr == "42"

def test_repo_flag_on_diagnose(self):
parser = build_parser()
args = parser.parse_args(["diagnose", "--repo", "org/repo", "42"])
assert args.repo == "org/repo"
assert args.command == "diagnose"
assert args.pr == "42"

def test_repo_flag_on_analyze_logs(self):
parser = build_parser()
args = parser.parse_args(["analyze-logs", "--repo", "org/repo", "789"])
assert args.repo == "org/repo"
assert args.run_id == "789"

def test_repo_default_is_none(self):
parser = build_parser()
args = parser.parse_args(["checks", "42"])
assert args.repo is None

def test_subcommand_format_flag(self):
parser = build_parser()
Expand Down Expand Up @@ -456,10 +475,10 @@ class TestCmdAnalyzeLogsRepoResolution:

def _make_args(self, run_id: str, pr: str | None = None, repo: str | None = None):
parser = build_parser()
argv = []
argv = ["analyze-logs"]
if repo:
argv.extend(["--repo", repo])
argv.extend(["analyze-logs", run_id])
argv.append(run_id)
if pr:
argv.append(pr)
return parser.parse_args(argv)
Expand Down