I initially set the type for livecheck's `post_form` and `post_json`
hashes to allow either a string or symbol key. I used string keys in
the documentation, as there will inevitably be some form field names
that would pose a problem for symbols (e.g., `E-mail` uses a hyphen,
`1twothree` starts with a digit, etc.). However, I remembered that we
can simply use quote symbols like `:"E-mail"` to handle these
situations, as they have the flexibility of a string while still being
a symbol.
With that in mind, this updates related type signatures to only allow
symbol keys and updates documentation and tests accordingly. The
documentation example contains a hyphenated form field, so it
demonstrates how to handle names that don't work as a bare symbol.
Import these from the homebrew/formula-analytics tap and deprecate
that tap.
This required a little messing around with filenames and paths to get
it finding Python and writing to the user's home directory.
Import these from the homebrew/aliases tap and deprecate that tap.
This required a little messing around with class/module/constant names
to get `brew tests` and `brew typecheck` to play nicely.
I added also added Sorbet type signatures and integration tests.
Between this commit and the previous one, this brings test coverage
for `Livecheck::Strategy` up to 98.18% line coverage and 97.22%
branch coverage. The only uncovered areas are some Sorbet `params`
calls (which I'm not sure how to cover) and a conditional `break` in
`page_headers` that will be refactored away in the future.
The increased coverage is primarily in areas that weren't covered
before because they call methods that make network requests. I worked
around this with stubs and doubles, so we can test this code to some
degree. I plan to expand this approach to other areas in livecheck
that aren't covered for the same reason and that should significantly
increase test coverage (along with some other test improvements that
I have lined up).
livecheck currently doesn't support `POST` requests but it wasn't
entirely clear how best to handle that. I initially approached it as
a `Post` strategy but unfortunately that would have required us to
handle response body parsing (e.g., JSON, XML, etc.) in some fashion.
We could borrow some of the logic from related strategies but we would
still be stuck having to update `Post` whenever we add a strategy for
a new format.
Instead, this implements `POST` support by borrowing ideas from the
`using: :post` and `data` `url` options found in formulae. This uses
a `post_form` option to handle form data and `post_json` to handle
JSON data, encoding the hash argument for each into the appropriate
format. The presence of either option means that curl will use a
`POST` request.
With this approach, we can make a `POST` request using any strategy
that calls `Strategy::page_headers` or `::page_content` (directly or
indirectly) and everything else works the same as usual. The only
change needed in related strategies was to pass the options through
to the `Strategy` methods.
For example, if we need to parse a JSON response from a `POST`
request, we add a `post_data` or `post_json` hash to the `livecheck`
block `url` and use `strategy :json` with a `strategy` block. This
leans on existing patterns that we're already familiar with and
shouldn't require any notable maintenance burden when adding new
strategies, so it seems like a better approach than a `Post` strategy.
This is particularly useful for third-party Python formulae that have a ton of resources, not all of which may adhere to homebrew/core's strict policies. See #19240 for context.
I've also added logic that ignores `--ignore-errors` on `homebrew/core`, although I personally think this new behavior is also useful for mainline formula creation.
Before: error out on a single non-conforming resource, zero resource blocks added to formula, scary stacktrace.
After: all conforming resources added, all non-conforming resources identified in comments, error message at end, `brew` exits non-zero without scary stacktrace:-
```
% brew update-python-resources --ignore-errors gromgit/test/auto-coder || echo OOPS
==> Retrieving PyPI dependencies for "auto-coder==0.1.243"...
==> Retrieving PyPI dependencies for excluded ""...
==> Getting PyPI info for "aiohappyeyeballs==2.4.4"
[200+ resource lines elided]
==> Getting PyPI info for "zhipuai==2.1.5.20250106"
==> Updating resource blocks
Error: Unable to resolve some dependencies. Please check /opt/homebrew/Library/Taps/gromgit/homebrew-test/Formula/auto-coder.rb for RESOURCE-ERROR comments.
OOPS
% brew cat gromgit/test/auto-coder | ggrep -C10 RESOURCE-ERROR
license "Apache-2.0"
depends_on "python@3.11"
# Additional dependency
# resource "" do
# url ""
# sha256 ""
# end
# RESOURCE-ERROR: Unable to resolve "azure-cognitiveservices-speech==1.42.0" (no suitable source distribution on PyPI)
# RESOURCE-ERROR: Unable to resolve "ray==2.42.0" (no suitable source distribution on PyPI)
resource "aiohappyeyeballs" do
url "e4373e888f/aiohappyeyeballs-2.4.4.tar.gz"
sha256 "5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"
end
resource "aiohttp" do
url "952d49c730/aiohttp-3.11.12.tar.gz"
sha256 "7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0"
end
```
I was recently running `brew tests` without `--online` and I noticed
that there was still one formulae.brew.sh request. I narrowed it down
to a `brew desc` test, so this adds `:needs_network` to that test.
As expected, `brew tests` doesn't make any network requests after this
change unless `--online` is used.
This came up in the AGM and has bothered me for years: let's actually
split out `software_spec.rb` into one file per class, as is more typical
in Ruby.
This will make these classes easier to find.
- use e.g. `$HOMEBREW_*` for cases where only the environment variable
is the entire backtick-quoted string
- use e.g. `${HOMEBREW_*}` for cases where the environment variable is
part of a backtick-quoted string to make clear what parts are variable
and what parts are not
- use `export HOMEBREW_*=...` for cases where we're talking about
setting the environment variable (because it likely needs to be
exported to work how they want)
Inspired by https://github.com/Homebrew/homebrew-bundle/pull/1579 making
similar changes for Homebrew/homebrew-bundle.
We're using `formula.eligible_kegs_for_cleanup` to figure out which
formula should be kept or removed based on e.g. `brew pin` status but
we didn't use this sufficiently in `brew cleanup` to avoid cleaning up
all cached files related to a pinned keg.
Instead, let's use a (cached) call to
`formula.eligible_kegs_for_cleanup` to ensure that we check all
related resources, manifests, etc. for pinned bottles rather than just
the latest version.
This adds more tests to `curl_spec.rb` to increase test coverage.
This brings almost all of the methods that don't make network
requests up to 100% line and branch coverage (the exception being
some guards in `parse_curl_output` that shouldn't happen under
normal circumstances).
In the process of writing more tests for `parse_curl_response`, I
made some tweaks to remove checks for conditions that shouldn't ever
be true (e.g., `match["code"]` isn't optional, so it will be present
if `HTTP_STATUS_LINE_REGEX` matches) and to refactor some others. I
contributed this method a while back (9171eb2), so this is me coming
back to clarify some behavior.
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.
Allow the ability for a system administrator to use
`HOMEBREW_BREW_WRAPPER` and `HOMEBREW_FORCE_BREW_WRAPPER` variables to
enforce the usage of a particular `brew` command for non-trivial (e.g.
`brew --prefix` is considered trivial, it doesn't need to write to the
prefix) Homebrew commands.
This also introduces a `HOMEBREW_ORIGINAL_BREW_FILE` variable for some
internal usage; `HOMEBREW_BREW_FILE` was being used internally for
both "how should we shell out to Homebrew" and "what should we use
to check permissions on Homebrew". `HOMEBREW_ORIGINAL_BREW_FILE` is
now used just for the latter case.
Inspired by conversation in
https://github.com/Homebrew/homebrew-bundle/pull/1551 which suggested
this was worth fixing in wider than just `brew bundle`.
- don't care about no checksums being defined for official casks
- don't complain about Gatekeeper being disabled on GitHub Actions as
it's been globally disabled for the team
The `mesa` formula currently uses a mesa.freedesktop.org/archive/
`stable` URL but it redirects to archive.mesa3d.org. Upstream links
to archive.mesa3d.org as the location to find Mesa releases, so we
should update the formula URLs accordingly.
This updates the `Xorg` strategy to be able to handle
archive.mesa3d.org URLs, so livecheck will continue to be able to
check `mesa` without needing a one-off `livecheck` block. [This would
also work for `mesalib-glw` (which has an archive.mesa3d.org `stable`
URL) but that formula is deprecated.]
When running `generate_completions_from_executable` with a formula's
`bin`/`sbin` executable, the resulting completion is usually intended
for the executable itself.