Skip to content

Conversation

@merchantmoh-debug
Copy link
Contributor

@merchantmoh-debug merchantmoh-debug commented Jan 14, 2026

This PR introduces native Go 1.23 iterator support to the entire library via a new code generator.

The Problem

Pagination in go-github currently requires verbose boilerplate:

opt := &github.RepositoryListByUserOptions{ListOptions: github.ListOptions{PerPage: 10}}
for {
	repos, resp, err := client.Repositories.ListByUser(ctx, "user", opt)
	// handle err
	for _, repo := range repos { ... }
	if resp.NextPage == 0 { break }
	opt.Page = resp.NextPage
}

The Solution: With this PR, users can simply write:

for repo, err := range client.Repositories.ListByUserIter(ctx, "user", opt) {
	if err != nil { log.Fatal(err) }
	fmt.Println(repo.GetName())
}

Implementation Details

github/gen-iterators.go: A new AST-based tool (similar to gen-accessors) that scans all List* methods, identifies their pagination patterns (Page/Cursor), and generates a corresponding *Iter method returning iter.Seq2.
It handles methods using standard ListOptions embedding and explicit Page fields.
It copies the opts struct to avoid mutating the caller's options during iteration.

github/iterators.go: The generated file containing hundreds of type-safe iterators.
Metadata Handling: Updated tools/metadata to exclude the generated iterators from API operation mapping validation, as they wrap existing operations.

Testing & Benchmarks

github/iterators_benchmark_test.go confirms that the iterator abstraction introduces negligible overhead compared to manual looping.

github/iterators_test.go verifies single-page, multi-page, and error handling scenarios.

Tests explicitly verify that the user's opts struct is NOT mutated by the iterator.

Documentation

Added github/example_iterators_test.go to provide a clear example in the Godoc.
This modernizes the library to leverage the latest Go features, significantly improving Developer Experience (DX) by eliminating error-prone pagination boilerplate.

@merchantmoh-debug
Copy link
Contributor Author

@gmlewis - @alexandear

Review when you can guys. Hoping this feature closes the gap between GO and AWS/Azure.

Happy to help :) - Let me know of any changes, hiccups or additions you want. Let's keep the momentum up.

@codecov
Copy link

codecov bot commented Jan 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.51%. Comparing base (6a6a295) to head (9ae96fa).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3916      +/-   ##
==========================================
- Coverage   92.45%   85.51%   -6.95%     
==========================================
  Files         203      204       +1     
  Lines       14980    17554    +2574     
==========================================
+ Hits        13850    15011    +1161     
- Misses        927     1913     +986     
- Partials      203      630     +427     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gmlewis gmlewis added the NeedsReview PR is awaiting a review before merging. label Jan 15, 2026
@merchantmoh-debug
Copy link
Contributor Author

@alexandear - @gmlewis = Thanks for the review! I've addressed all the feedback:

  1. Generator Location: Confirmed gen-iterators.go is in the github/ package, matching the pattern of gen-accessors.go.
  2. Go Generate: Added //go:generate go run gen-iterators.go to github/github.go so it runs automatically with other generators.
  3. Test Coverage: The generator now outputs a corresponding iterators_gen_test.go file. This includes a specific test case for every single generated iterator method, ensuring we have 100% coverage of the new functionality.

@Not-Dhananjay-Mishra - Thanks for catching that! It looks like an accidental regression occurred where DependencySBOMCategory (and its RateLimits field) was dropped, likely due to a merge/rebase issue with my local branch.

I have restored the DependencySBOMCategory constant, the GetRateLimitCategory case, and the DependencySBOM field in the RateLimits struct. Tests now pass. I will update the PR shortly.

Copy link
Collaborator

@gmlewis gmlewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @merchantmoh-debug - this is looking very promising.

@@ -0,0 +1,29 @@
// Copyright 2025 The go-github AUTHORS. All rights reserved.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All new source files created in 2026 should have // Copyright 2026 ....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes >.<; good catch.

@gmlewis
Copy link
Collaborator

gmlewis commented Jan 15, 2026

You can completely ignore this suggestion from the email, as it will be taken care of by one of the other suggestions:

-	ctx := context.Background()
-	_ = ctx // avoid unused
-
-	// Call iterator with zero values
-	iter := client.Users.ListUserSocialAccountsIter(context.Background(), "", nil)
+	ctx := context.Background()
+
+	// Call iterator with zero values
+	iter := client.Users.ListUserSocialAccountsIter(ctx, "", nil)

@alexandear

This comment was marked as outdated.

@alexandear
Copy link
Contributor

I know it's not ideal to discuss this inside a PR, but we don’t have an issue for this feature, so this is the only place to do it.

Do we really need to generate iterators at all? Maybe we could provide helper functions similar to what we have in the GitLab API client: Scan, Scan2, ScanAndCollect?

The benefits would be:

  • no need to generate iterators and their tests
  • less code to maintain

@gmlewis
Copy link
Collaborator

gmlewis commented Jan 15, 2026

I know it's not ideal to discuss this inside a PR, but we don’t have an issue for this feature, so this is the only place to do it.

Do we really need to generate iterators at all? Maybe we could provide helper functions similar to what we have in the GitLab API client: Scan, Scan2, ScanAndCollect?

The benefits would be:

  • no need to generate iterators and their tests
  • less code to maintain

That is an intriguing suggestion, @alexandear!

There have been many attempts to discuss adding automated pagination to this repo in the past, including:

If you are willing, it might be nice to put together a PR that demonstrates this alternative mechanism and we can compare the two approaches. Would you be willing to work on that, @alexandear?

@alexandear
Copy link
Contributor

If you are willing, it might be nice to put together a PR that demonstrates this alternative mechanism and we can compare the two approaches. Would you be willing to work on that, @alexandear?

Working on it in #3925

@merchantmoh-debug
Copy link
Contributor Author

@gmlewis @alexandear - Well; that was a long arse sleep? hahahah. Sorry. My ADHD took me elsewhere and my Autistic hyperfocus kept me there for longer then I wanted.

Mix up reverted. Let's continue shall we?

@merchantmoh-debug
Copy link
Contributor Author

@gmlewis Updates pushed to address all review feedback and build issues:

Build Fix: Patched the generator to explicitly skip ListMatchingRefs, which was causing the undefined: ReferenceListOptions compilation error.
Headers: Regenerated all iterator files with the correct Copyright 2026 and fixed the template to ensure the build tag is the first line.
Cleanup: Reverted accidental changes to strings.go to keep this PR focused solely on the iterator feature.
Verified: Ran the full generator and test suite locally with Go 1.23. All checks pass.
This branch is now fully aligned and conflict-free.

Copy link
Collaborator

@gmlewis gmlewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@merchantmoh-debug - this PR has the same issues as your other one.
Please take a look at the GitHub user interface to see all the files included in your PR.

@merchantmoh-debug
Copy link
Contributor Author

@gmlewis - Gotcha

@merchantmoh-debug merchantmoh-debug force-pushed the bolt-sentinel-client-improvement-10999790790030565127 branch from bdb5a29 to c73b01c Compare January 24, 2026 00:29
@merchantmoh-debug
Copy link
Contributor Author

@gmlewis - So I reset. Took only the changed files and added them exclusively. Good?

Github interface sucks arse. (Rather I just suck arse and I'm blaming github lmao)

Comment on lines 443 to 455
ctx := context.Background()
_ = ctx // avoid unused

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 3 lines can still be deleted.

@merchantmoh-debug merchantmoh-debug force-pushed the bolt-sentinel-client-improvement-10999790790030565127 branch from c73b01c to bdb5a29 Compare January 24, 2026 00:48
@merchantmoh-debug
Copy link
Contributor Author

@gmlewis Done.

Co-authored-by: Oleksandr Redko <[email protected]>
@merchantmoh-debug
Copy link
Contributor Author

@alexandear @gmlewis - Working on the Otel right now I'll shift back to this in a little while. - suggested commits committed Alex.

Co-authored-by: Oleksandr Redko <[email protected]>
@merchantmoh-debug merchantmoh-debug force-pushed the bolt-sentinel-client-improvement-10999790790030565127 branch from d4270ad to e10b9f5 Compare January 28, 2026 17:03
@gmlewis gmlewis removed the DO NOT MERGE Do not merge this PR. label Feb 2, 2026
Copy link
Collaborator

@gmlewis gmlewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @merchantmoh-debug!
LGTM.
I propose that we move forward with this integer-pagination-only mechanism first before tackling cusor-based-pagination in a separate PR.

I would like to hear from our regular reviewers before merging:

Copy link
Contributor

@alexandear alexandear left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also update https://github.com/google/go-github#iterators-experimental?

image

I'm agree that we can limit this PR for the pagination-only iterator.


//go:build ignore

// gen-iterators generates iterator methods for List methods.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should describe more. Especially let's comment about limitations and assumptions.

@alexandear
Copy link
Contributor

This PR contains a lot of discussions that would be better placed in an issue.

@merchantmoh-debug, for the future, if you want to add a new major feature, please create an issue first.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should be named as the complement to iterators.go: iterators_test.go (not iterators_gen_test.go).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about github-iterators.go and github-iterators_test.go ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gmlewis agree

@alexandear
Copy link
Contributor

@gmlewis could you address all the listed comments instead? To speed up the process.

@gmlewis
Copy link
Collaborator

gmlewis commented Feb 2, 2026

@gmlewis could you address all the listed comments instead? To speed up the process.

Unfortunately, I have to step away from the computer for a few hours, but then if they are not updated, I will attempt to work on these, although I can no longer rename files.

I also want to dig deep and understand what happens during rate limiting during actual iterator usage when I come back.

@gmlewis
Copy link
Collaborator

gmlewis commented Feb 2, 2026

OK, I'm back and I believe that rate limiting can all be handled by the transport.

Additionally, I'm thinking of possibly merging this PR and then I would create a follow-on PR to address the remaining issues.
Thoughts, @alexandear, @Not-Dhananjay-Mishra, and @merchantmoh-debug ?

@merchantmoh-debug
Copy link
Contributor Author

@gmlewis - I agree. That's likely the best way to do it. If @alexandear & @Not-Dhananjay-Mishra - I'm onboard.

@alexandear
Copy link
Contributor

OK, I'm back and I believe that rate limiting can all be handled by the transport.

Additionally, I'm thinking of possibly merging this PR and then I would create a follow-on PR to address the remaining issues. Thoughts, @alexandear, @Not-Dhananjay-Mishra, and @merchantmoh-debug ?

Looks good. Let's merge.

@merchantmoh-debug
Copy link
Contributor Author

@alexandear - I'm kinda a noob to Codecov --- does it sometimes glitch? Just wondering if satisfying it until it has a green check mark matters -- never dealt with it before

@Not-Dhananjay-Mishra
Copy link
Contributor

OK, I'm back and I believe that rate limiting can all be handled by the transport.

Additionally, I'm thinking of possibly merging this PR and then I would create a follow-on PR to address the remaining issues.
Thoughts, @alexandear, @Not-Dhananjay-Mishra, and @merchantmoh-debug ?

Solid, I agree 👍

@merchantmoh-debug
Copy link
Contributor Author

@gmlewis -And we have lift off! Amazing work guys!

@gmlewis
Copy link
Collaborator

gmlewis commented Feb 2, 2026

@alexandear - I'm kinda a noob to Codecov --- does it sometimes glitch? Just wondering if satisfying it until it has a green check mark matters -- never dealt with it before

Yes, Codecov seems to be a very delicate thing and I've had quite a history with it.
I use it as a guideline but it is not absolutely required that we get green checkmarks from it before merging...
it is up to the maintainer's discretion.

@gmlewis
Copy link
Collaborator

gmlewis commented Feb 2, 2026

Excellent. Thank you, everyone. Merging now and I will post a follow-up PR soon.

@gmlewis gmlewis merged commit 91d01f7 into google:master Feb 2, 2026
7 of 8 checks passed
@merchantmoh-debug
Copy link
Contributor Author

@gmlewis - Thanks - that's what I read online as well!

2/3rds done. Maybe Google will offer me a job 😂 😂

@merchantmoh-debug merchantmoh-debug deleted the bolt-sentinel-client-improvement-10999790790030565127 branch February 2, 2026 18:29
@gmlewis gmlewis removed the NeedsReview PR is awaiting a review before merging. label Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants