- Add an `--organisation` flag to search a specific organisation.
- Wait for the GitHub API rate limit to reset before automatically
retrying.
- Use (much) fewer API calls by using organisation-wide API PR searches
rather than per-repository. This makes the rate limit easier to avoid
and also makes things much faster (with the trade-off of showing a max
PR count per-user rather than per-repository).
- Improve output to clarify when the max PR/commit count is reached.
- Move more logic and add more Sorbet signatures to the `GitHub` and
`Utils::Git` modules.
- Rename a few GitHub API methods.
- Remove a lot of (now unused) `GitHub` module methods.
- Add, use a `Tap#full_repository` method.
- Add `formula-analytics` as a deprecated tap.
This reduces the surface area of our `Kernel` monkeypatch and removes
the need to `include Kernel` in a bunch of modules.
While we're here, also move `Kernel#require?` to `Homebrew` and fully
scope the calls to it.
This upgrades `utils/curl.rb` to `typed: strict`, which requires
a number of changes to pass `brew typecheck`. The most
straightforward are adding type signatures to methods, adding type
annotations (e.g., `T.let`) to variables that need them, and ensuring
that methods always use the expected return type.
I had to refactor areas where we call a `Utils::Curl` method and use
array destructuring on a `SystemCommand::Result` return value
(e.g., `output, errors, status = curl_output(...)`), as Sorbet
doesn't understand implicit array conversion. As suggested by Markus,
I've switched these areas to use `#stdout`, `#stderr`, and `#status`.
This requires the use of an intermediate variable (`result`) in some
cases but this was a fairly straightforward substitution.
I also had to refactor how `Cask::URL::BlockDSL::PageWithURL` works.
It currently uses `page.extend PageWithURL` to add a `url` attribute
but this reworks it to subclass `SimpleDelegator` and use an
`initialize` method instead. This achieves the same goal but in a way
that Sorbet can understand.
- Previously I thought that comments were fine to discourage people from
wasting their time trying to bump things that used `undef` that Sorbet
didn't support. But RuboCop is better at this since it'll complain if
the comments are unnecessary.
- Suggested in https://github.com/Homebrew/brew/pull/18018#issuecomment-2283369501.
- I've gone for a mixture of `rubocop:disable` for the files that can't
be `typed: strict` (use of undef, required before everything else, etc)
and `rubocop:todo` for everything else that should be tried to make
strictly typed. There's no functional difference between the two as
`rubocop:todo` is `rubocop:disable` with a different name.
- And I entirely disabled the cop for the docs/ directory since
`typed: strict` isn't going to gain us anything for some Markdown
linting config files.
- This means that now it's easier to track what needs to be done rather
than relying on checklists of files in our big Sorbet issue:
```shell
$ git grep 'typed: true # rubocop:todo Sorbet/StrictSigil' | wc -l
268
```
- And this is confirmed working for new files:
```shell
$ git status
On branch use-rubocop-for-sorbet-strict-sigils
Untracked files:
(use "git add <file>..." to include in what will be committed)
Library/Homebrew/bad.rb
Library/Homebrew/good.rb
nothing added to commit but untracked files present (use "git add" to track)
$ brew style
Offenses:
bad.rb:1:1: C: Sorbet/StrictSigil: Sorbet sigil should be at least strict got true.
^^^^^^^^^^^^^
1340 files inspected, 1 offense detected
```
Per feedback to https://github.com/Homebrew/brew/pull/17806, this
moves some `require` statements in `dev-cmd/contributions.rb` and
`Utils::GitHub` into the methods that need them.
This resolves `unitialized constant` errors in `brew contributions`
(`Tap`, `GitHub`) and `Utils::GitHub` (`Utils::Curl`).
This also preemptively adds some requires to `Utils::GitHub` and
`GitHub::API`, to avoid similar errors.
Take 2 of https://github.com/Homebrew/brew/pull/17692 but with:
- provide and document `HOMEBREW_NO_VERIFY_ATTESTATIONS`
- don't try to run unless there's GitHub credentials
- don't try to run unless `gh` is installed
- don't try to run in CI
While we're here:
- split out a `Homebrew::EnvConfig.devcmdrun?` helper method
- add some missing `Homebrew::EnvConfig.github_api_token` presence
checks
- more sensible/performant defaults: default to primary repositories
only for the last year rather than all repositories forever
- allow specifying more than one user at a time
- output the breakdown of contributions without needing `--csv`
- add a space before the `--csv` output
- consolidate some code
- avoid counting authored commits twice, to improve performance
- retry failed GitHub API calls (this happens often when querying all
maintainers)
- stop counting after we find 1000 commits for a given user to avoid
excessive API queries/pagination
- The `API_MAX_PAGES` value is 50, so for pages 1 to 50, the
`paginate_rest` method was making an API call even if there was no
data past, for example, page 8.
- This made `brew contributions --user=issyl0` take 11 minutes, since we
made 50 API calls _per repo_ even if it was unnecessary, burning down
our API allowance.
- Instead, stop looping if we detect that there's no data in `result`.
- This probably needs more testing for other parts of Homebrew that rely
on `paginate_rest` and the different shapes of data it outputs.