Commit b4d9c08
authored
[smart-log] perf: parallelize status check fetches (#42)
* feat: add stack discovery API
Add src/api/stack.rs module for discovering PR stacks by walking
the base/head branch chain. This enables gh-stack to find related
PRs without requiring identifier patterns in titles.
New functions:
- fetch_pr_by_head: Find PR by head branch name
- fetch_prs_by_base: Find all PRs targeting a base branch
- fetch_all_open_prs: Get all open PRs in a repo
- discover_stack: Walk up/down to find full connected stack
- discover_all_stacks: Group all PRs into separate stacks
Includes 9 unit tests with mockito for API calls.
* feat: add rate limit retry logic
Add automatic retry with exponential backoff for GitHub API rate limits.
New functionality in src/api/mod.rs:
- RateLimitError struct with reset time info and Display impl
- parse_rate_limit_headers() to extract X-RateLimit-* headers
- is_rate_limited() to detect 429 and 403 with rate limit headers
- send_with_retry() for automatic retry with exponential backoff
Retries up to 3 times with 1s, 2s, 4s delays before returning
a RateLimitError with helpful message showing when to retry.
Includes 6 new tests for retry logic.
* feat: add identifier detection and prompts
Add src/identifier.rs module for trunk branch detection and
interactive stack selection prompts.
New types and functions:
- StackSummary: Display info for a stack (branch, PR count, numbers)
- is_trunk_branch(): Check if branch is a trunk (main, master, etc.)
- detect_trunk_branch(): Get default branch from git remote
- TrunkAction: Enum for user choices when on trunk
- prompt_trunk_action(): Interactive menu for trunk branch
- prompt_select_stack(): Let user pick from stack list
- prompt_identifier(): Manual identifier entry
Includes 12 unit tests for trunk detection and summary formatting.
* feat: add gh CLI helpers
Add src/gh_cli.rs module for GitHub CLI detection and installation
hints to help users create PRs when none exist for a branch.
New functions:
- is_gh_installed(): Check if gh CLI is available
- is_gh_authenticated(): Check if gh is logged in
- install_instructions(): Platform-specific install commands
- suggest_create_pr(): Print gh pr create command with hints
- prompt_create_pr(): Interactive PR creation prompt
The module handles non-TTY environments gracefully and provides
helpful messages when gh is not installed or not authenticated.
Includes 3 unit tests.
* feat: make log identifier optional with branch inference
Enable gh-stack log to work without an explicit identifier by
inferring the stack from the current branch's PR chain.
New CLI arguments for log command:
- --branch, -b: Infer stack from specified branch
- --all, -a: List all stacks and select interactively
- --ci: Non-interactive mode for CI environments
- --trunk: Override trunk branch detection
Behavior changes:
- Running 'gh-stack log' without args infers from current branch
- On trunk branch: prompts to enter identifier or select stack
- No PR found: suggests gh pr create command
- CI mode requires explicit identifier or --branch flag
The identifier argument is now optional but still fully supported
for backwards compatibility.
* feat: add branch inference to status command
Apply the same smart default behavior from log to status command:
New CLI arguments for status command:
- --branch, -b: Infer stack from specified branch
- --all, -a: List all stacks and select interactively
- --ci: Non-interactive mode for CI environments
- --trunk: Override trunk branch detection
The identifier argument is now optional. Running 'gh-stack status'
without args infers the stack from the current branch's PR chain.
JSON output mode handles errors gracefully with error field in response.
* docs: update log documentation for smart defaults
Update docs/log.md to document the new smart default behavior:
- Stack discovery from current branch
- New flags: --branch, --all, --ci, --trunk
- CI usage examples
- On trunk branch behavior
- No PR found behavior with gh pr create suggestion
Also add reference to status command in 'See also' section.
* docs: update status documentation for smart defaults
Update docs/status.md to document the new smart default behavior:
- Stack discovery from current branch
- New flags: --branch, --all, --ci, --trunk
- CI usage examples
- Updated options table with new flags
- Reorganized examples section
* perf: optimize stack discovery with batch fetch
Replace sequential API calls with batch-fetch strategy:
- Fetch all open PRs in one paginated request (up to 1000 PRs)
- Walk the PR chain in-memory using PrIndex lookup structure
- Reduces API calls from O(N) to O(1) for stack discovery
Changes:
- Add pagination support to fetch_all_open_prs (MAX_PAGES=10)
- Add PrIndex struct for fast in-memory head/base lookups
- Refactor discover_stack to use batch fetch + in-memory walk
- Extract discover_stack_from_index for pure in-memory operation
- Extract group_into_stacks for reuse between functions
Performance improvement:
- Before: ~12 sequential API calls for 6-PR stack (~6+ seconds)
- After: 1-2 API calls for any stack size (~2 seconds)
Enterprise support:
- Pagination handles repos with 100+ open PRs
- Capped at 1000 PRs (10 pages) for safety
Adds 11 new tests for PrIndex, batch fetch, and pagination.
* perf: parallelize status check fetches
Use futures::join_all to fetch CI checks and mergeable status
for all PRs in parallel instead of sequentially.
- Add PrCheckData struct to collect PR data in non-async pass
- Add fetch_pr_status helper to fetch CI and mergeable in parallel
- Refactor build_status_entries to batch fetch all status checks
Performance: ~3.3s for 7-PR stack (down from ~8s sequential)
* refactor: remove gh CLI dependency
Replace gh CLI with native Rust implementations:
- Add browser.rs for cross-platform browser opening and URL generation
- Add api/create.rs for GitHub API PR creation
- Add --create-pr flag for API-based PR creation
- Poll for PR after browser-based creation (30s timeout)
- Support GitHub Enterprise via remote URL parsing
- Add first_commit_message() and get_remote_url() helpers to tree.rs
New features:
- Interactive mode opens browser to create PR, then polls for it
- --create-pr flag creates PR via API with prompts for title/body
- CI mode prints PR creation URL
Removes: src/gh_cli.rs (no longer needed)1 parent 249d5c1 commit b4d9c08
11 files changed
Lines changed: 3064 additions & 104 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
8 | 18 | | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
13 | 22 | | |
14 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
15 | 34 | | |
16 | 35 | | |
17 | 36 | | |
| |||
50 | 69 | | |
51 | 70 | | |
52 | 71 | | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
53 | 76 | | |
| 77 | + | |
54 | 78 | | |
55 | 79 | | |
56 | 80 | | |
57 | 81 | | |
58 | 82 | | |
59 | 83 | | |
60 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
61 | 134 | | |
62 | 135 | | |
63 | 136 | | |
| |||
68 | 141 | | |
69 | 142 | | |
70 | 143 | | |
| 144 | + | |
71 | 145 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
9 | | - | |
10 | | - | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
11 | 25 | | |
12 | 26 | | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
13 | 37 | | |
14 | 38 | | |
15 | 39 | | |
| |||
68 | 92 | | |
69 | 93 | | |
70 | 94 | | |
71 | | - | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
72 | 100 | | |
73 | 101 | | |
74 | 102 | | |
75 | 103 | | |
76 | 104 | | |
77 | 105 | | |
78 | | - | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
79 | 127 | | |
80 | 128 | | |
81 | 129 | | |
82 | 130 | | |
83 | | - | |
| 131 | + | |
84 | 132 | | |
85 | 133 | | |
86 | 134 | | |
| |||
113 | 161 | | |
114 | 162 | | |
115 | 163 | | |
116 | | - | |
| 164 | + | |
117 | 165 | | |
118 | 166 | | |
119 | 167 | | |
120 | 168 | | |
121 | 169 | | |
122 | 170 | | |
123 | | - | |
| 171 | + | |
124 | 172 | | |
125 | 173 | | |
126 | | - | |
| 174 | + | |
127 | 175 | | |
128 | 176 | | |
129 | | - | |
| 177 | + | |
130 | 178 | | |
131 | 179 | | |
132 | | - | |
| 180 | + | |
133 | 181 | | |
134 | 182 | | |
135 | | - | |
| 183 | + | |
136 | 184 | | |
137 | 185 | | |
138 | | - | |
| 186 | + | |
139 | 187 | | |
140 | 188 | | |
141 | | - | |
| 189 | + | |
142 | 190 | | |
143 | 191 | | |
144 | | - | |
| 192 | + | |
145 | 193 | | |
146 | 194 | | |
147 | | - | |
| 195 | + | |
148 | 196 | | |
149 | 197 | | |
150 | | - | |
| 198 | + | |
151 | 199 | | |
152 | 200 | | |
153 | 201 | | |
| |||
0 commit comments