Coverage for src/workstack/status/collectors/github.py: 35%
26 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-19 09:31 -0400
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-19 09:31 -0400
1"""GitHub PR collector."""
3from pathlib import Path
5from workstack.core.context import WorkstackContext
6from workstack.status.collectors.base import StatusCollector
7from workstack.status.models.status_data import PullRequestStatus
10class GitHubPRCollector(StatusCollector):
11 """Collects GitHub pull request information."""
13 @property
14 def name(self) -> str:
15 """Name identifier for this collector."""
16 return "pr"
18 def is_available(self, ctx: WorkstackContext, worktree_path: Path) -> bool:
19 """Check if PR information should be fetched.
21 Args:
22 ctx: Workstack context
23 worktree_path: Path to worktree
25 Returns:
26 True if PR info is enabled in config
27 """
28 if not ctx.global_config_ops.get_show_pr_info():
29 return False
31 if not worktree_path.exists():
32 return False
34 return True
36 def collect(
37 self, ctx: WorkstackContext, worktree_path: Path, repo_root: Path
38 ) -> PullRequestStatus | None:
39 """Collect GitHub PR information.
41 Args:
42 ctx: Workstack context
43 worktree_path: Path to worktree
44 repo_root: Repository root path
46 Returns:
47 PullRequestStatus with PR information or None if collection fails
48 """
49 branch = ctx.git_ops.get_current_branch(worktree_path)
50 if branch is None:
51 return None
53 # Try Graphite first (fast - no CI status)
54 prs = ctx.graphite_ops.get_prs_from_graphite(ctx.git_ops, repo_root)
56 # If Graphite data not available, fall back to GitHub
57 if not prs:
58 prs = ctx.github_ops.get_prs_for_repo(repo_root, include_checks=True)
60 # Find PR for current branch
61 pr = prs.get(branch)
62 if pr is None:
63 return None
65 # Determine if ready to merge
66 ready_to_merge = (
67 pr.state == "OPEN"
68 and not pr.is_draft
69 and (pr.checks_passing is True or pr.checks_passing is None)
70 )
72 return PullRequestStatus(
73 number=pr.number,
74 title=None, # Title not available in PullRequestInfo
75 state=pr.state,
76 is_draft=pr.is_draft,
77 url=pr.url,
78 checks_passing=pr.checks_passing,
79 reviews=None, # Reviews not available in PullRequestInfo
80 ready_to_merge=ready_to_merge,
81 )