feat(integration): add pagination to github branches list API#53931
feat(integration): add pagination to github branches list API#53931VojtechBartos wants to merge 3 commits intomasterfrom
Conversation
|
| @patch("posthog.models.integration.requests.get") | ||
| def test_list_branches_returns_first_page(self, mock_get): | ||
| names = [f"branch-{i}" for i in range(100)] | ||
| mock_get.return_value = _make_github_branches_response(names, has_next=True) | ||
|
|
||
| branches, has_more = self.github.list_branches("org/repo", limit=100, offset=0) | ||
|
|
||
| assert branches == names | ||
| assert has_more is True | ||
| mock_get.assert_called_once() | ||
| assert "page=1" in mock_get.call_args[0][0] | ||
|
|
||
| @patch("posthog.models.integration.requests.get") | ||
| def test_list_branches_offset_skips_pages(self, mock_get): | ||
| """Requesting offset=200 should start fetching from GitHub page 3.""" | ||
| page3_names = [f"branch-{i}" for i in range(200, 300)] | ||
| mock_get.return_value = _make_github_branches_response(page3_names, has_next=True) | ||
|
|
||
| branches, has_more = self.github.list_branches("org/repo", limit=100, offset=200) | ||
|
|
||
| assert branches == page3_names | ||
| assert has_more is True | ||
| assert mock_get.call_count == 1 | ||
| assert "page=3" in mock_get.call_args[0][0] | ||
|
|
||
| @patch("posthog.models.integration.requests.get") | ||
| def test_list_branches_last_page_no_more(self, mock_get): | ||
| names = [f"branch-{i}" for i in range(50)] | ||
| mock_get.return_value = _make_github_branches_response(names, has_next=False) | ||
|
|
||
| branches, has_more = self.github.list_branches("org/repo", limit=100, offset=0) | ||
|
|
||
| assert branches == names | ||
| assert has_more is False | ||
|
|
||
| @patch("posthog.models.integration.requests.get") | ||
| def test_list_branches_spans_two_github_pages(self, mock_get): | ||
| """An offset that doesn't align with per_page=100 requires fetching two GitHub pages.""" | ||
| page1_names = [f"branch-{i}" for i in range(100)] | ||
| page2_names = [f"branch-{i}" for i in range(100, 200)] | ||
|
|
||
| mock_get.side_effect = [ | ||
| _make_github_branches_response(page1_names, has_next=True), | ||
| _make_github_branches_response(page2_names, has_next=False), | ||
| ] | ||
|
|
||
| branches, has_more = self.github.list_branches("org/repo", limit=100, offset=50) | ||
|
|
||
| assert len(branches) == 100 | ||
| assert branches == [f"branch-{i}" for i in range(50, 150)] | ||
| # There are still branches 150-199 beyond this window | ||
| assert has_more is True | ||
| assert mock_get.call_count == 2 | ||
|
|
||
| @patch("posthog.models.integration.requests.get") | ||
| def test_list_branches_empty_repo(self, mock_get): | ||
| mock_get.return_value = _make_github_branches_response([], has_next=False) | ||
|
|
||
| branches, has_more = self.github.list_branches("org/repo") | ||
|
|
||
| assert branches == [] | ||
| assert has_more is False | ||
|
|
There was a problem hiding this comment.
Prefer parameterised tests for single-page variants
test_list_branches_returns_first_page, test_list_branches_last_page_no_more, and test_list_branches_empty_repo are all variations of the same single-page logic (offset=0, different branch counts and has_next flags). Per repo conventions these should be collapsed into one parameterised test.
@pytest.mark.parametrize(
"branch_count, has_next, expected_has_more",
[
(100, True, True),
(50, False, False),
(0, False, False),
],
)
@patch("posthog.models.integration.requests.get")
def test_list_branches_single_page(self, mock_get, branch_count, has_next, expected_has_more):
names = [f"branch-{i}" for i in range(branch_count)]
mock_get.return_value = _make_github_branches_response(names, has_next=has_next)
branches, has_more = self.github.list_branches("org/repo", limit=100, offset=0)
assert branches == names
assert has_more is expected_has_more
mock_get.assert_called_once()
assert "page=1" in mock_get.call_args[0][0]Context Used: Do not attempt to comment on incorrect alphabetica... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: posthog/api/test/test_integration.py
Line: 1117-1179
Comment:
**Prefer parameterised tests for single-page variants**
`test_list_branches_returns_first_page`, `test_list_branches_last_page_no_more`, and `test_list_branches_empty_repo` are all variations of the same single-page logic (offset=0, different branch counts and `has_next` flags). Per repo conventions these should be collapsed into one parameterised test.
```python
@pytest.mark.parametrize(
"branch_count, has_next, expected_has_more",
[
(100, True, True),
(50, False, False),
(0, False, False),
],
)
@patch("posthog.models.integration.requests.get")
def test_list_branches_single_page(self, mock_get, branch_count, has_next, expected_has_more):
names = [f"branch-{i}" for i in range(branch_count)]
mock_get.return_value = _make_github_branches_response(names, has_next=has_next)
branches, has_more = self.github.list_branches("org/repo", limit=100, offset=0)
assert branches == names
assert has_more is expected_has_more
mock_get.assert_called_once()
assert "page=1" in mock_get.call_args[0][0]
```
**Context Used:** Do not attempt to comment on incorrect alphabetica... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
Size Change: -3.15 kB (0%) Total Size: 129 MB
ℹ️ View Unchanged
|
|
🎭 Playwright report · View test results →
These issues are not necessarily caused by your changes. |
Problem
The GitHub integration's branch listing was hard-capped at 2,000 branches (20 pages × 100 per page). Repositories with more than 2,000 branches — like the PostHog monorepo with 5,000+ — had their branch list silently truncated. Additionally, every request fetched all pages from GitHub sequentially with no pagination support on the PostHog API side.
Changes
GitHubIntegration.list_branches— now acceptslimit/offsetparams and fetches only the GitHubAPI pages needed for the requested window
github_branchesendpoint — supports?limit=(1–1000, default 100) and?offset=(default 0) query paramshas_moreboolean so consumers can paginate progressivelymainfirst) now only applies on the first page (offset=0) to keep paginated results consistentHow did you test this code?
Added 10 unit tests covering:
Publish to changelog?
No
Docs update
No