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.
Calls to `opoo` and `onoe` produce duplicate `Warning:` and `Error:`
messages in CI logs because we print something to stdout and print an
annotation. Annotations also produce `Error:` and `Warning:` lines in
the log.
Let's fix this by skipping printing the message if we've already printed
an annotation.
- only use annotations for `opoo` and `onoe` if
`HOMEBREW_GITHUB_ACTIONS` is set. This will make using `brew` less
noisy in GitHub Actions for third parties. See
Homebrew/discussions#5602.
- if we've already called `puts_annotation_if_env_set`, then we no
longer need to print the message to `$stderr`. The message from the
annotation already show up in the GitHub Actions log, so printing to
`$stderr` just leads to duplicate messages in the log.
While we're here, let's make sure to forward the `file:` and `line:`
kwargs of `puts_annotation_if_env_set` to the `Annotation` constructor.
We currently generate invalid workflow commands when we create
annotations with a `title` but no `file`. Let's fix that.
While we're here, let's improve handling of `title`s with `:`s. We
cannot use `title`s with `::` since GitHub Actions uses this as a
separator for different fields between a workflow command.
Let's also make sure `metadata` never ends in a `:` to avoid confusing
the GitHub Actions command parser about where the `::` separator is
meant to be.
- 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
This will mean e.g. `opoo` etc. will output to stdout and not end up
being in the stdout of `brew deps` etc.
While we're here, remove a duplicate annotation output I noticed in
`extend/kernel.rb`.
Inspired by conversation in:
https://github.com/Homebrew/homebrew-test-bot/issues/1082
We already do this for deprecations but these may make warnings
and errors from Homebrew easier to spot in GitHub Actions logs.
While we're here, cleanup other cases that should have used
`GitHub::Actions::Annotation` but didn't and provide some helpers and
tweaks there necessary for our use case here.
- 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