- Since #23312, `brew services start` always regenerated the service
definition from the formula `service` block. Formulae that bundle
their own service file only declare `name` there, so the generated
plist had empty `ProgramArguments` and `launchctl bootstrap` failed
with `Input/output error`.
- Read the installed service file instead unless the `service` block
defines a command, the same gate `FormulaInstaller#install_service`
uses when writing generated service files into the keg.
- Fixes https://github.com/Homebrew/brew/issues/23408.
- `brew bump` reported formulae as up to date when a newer upstream
release was suppressed by the release cooldown, confusing upstream
authors waiting for autobump.
- Show the suppressed version with how recently it was released, add
a `Bump-ready version:` line for what can be bumped now and change
the headline from `is up to date!` to `has a new version in
release cooldown`.
- Fixes#23396.
- Drop the status write that fork pull requests cannot receive.
- Pin the `2026.08.03.2` action release that fails validation jobs.
- Report the required check for synthetic merge queue commits.
- After #23381, homebrew-core CI fails installing dependencies on
version-bump PRs: the bumped formula's stale bottle block derives
its manifest URL from the new version, whose bottle has not been
published yet, and `DownloadQueue#fetch` treats every bottle
manifest failure as fatal.
- Before that change the default ask-mode plan fetched manifests
synchronously via `Formula#fetch_bottle_tab`, which rescues
download errors so dependency resolution falls back to a full
install, and the installer's memoisation then kept the queue from
retrying the download.
- Add `DownloadQueue#fetch(allow_failures:)`: failed downloads are
still reported but neither raise nor mark the fetch or run as
failed. Use it for the metadata-only drains (`fetch_formulae`'s
bottle manifest waits, `brew install`'s ask-mode drain and
`brew upgrade`'s tab prefetch), restoring the synchronous path's
tolerance. Manifest failures in fetches that pour bottles remain
fatal.
`brew info --installed --json=v2` emits `==> Downloading Homebrew API
data` to stdout when the API data needs (re)downloading, corrupting
the JSON for anything parsing it (e.g. piping to `jq`).
The heading was added in 284cd0ed4c (#23381) as an unconditional
`oh1`, regressing the intent of 43137fe877 (#20980), which moved the
queue's non-TTY per-download report lines to stderr for exactly this
reason. Print the heading to stderr when stdout is not a TTY so it
stays off parsed stdout and on the same stream as those report lines.
TTY behaviour is unchanged.
Use `$stderr.puts oh1_title(...)` rather than `$stderr.oh1` as
RSpec's `to_stderr` matcher replaces `$stderr` with a plain
`StringIO` that lacks the `Utils::Output::Mixin` extension.
- `brew install` only started network transfers after preinstall
checks and, in ask mode, fetched each bottle manifest serially
while computing the dry-run plan.
- Enqueue bottle manifests on the shared download queue right after
building formula installers in both ask and no-ask modes so
transfers overlap preinstall checks and dependant scanning and
manifests for multiple formulae download concurrently. Ask mode
drains them under a `Downloading bottle manifests` heading before
printing the plan; warm runs enqueue nothing and stay silent.
- Once downloads are confirmed (`--yes` installs, reinstall, upgrade
and other `Install.fetch_formulae` callers), also enqueue the
formula's own bottle in `FormulaInstaller#prelude_fetch`: the blob
URL needs neither the manifest nor dependency resolution, so both
transfer concurrently and staging joins the same queue cycle.
- Skip the `enqueue_fetch` requeue for bottles the prelude fetch
already enqueued so a completed early download is not reported a
second time.
- Give `DownloadQueue#fetch` `only:` and `heading:` so a heading is
always printed before any queue output and never for empty fetches:
dependency resolution inside `Install.fetch_formulae` waits on just
the bottle manifests it needs (under `Downloading bottle manifests`)
and the cask source pre-fetch on just its cask files, keeping other
in-flight downloads queued and unreported so bottles only ever
appear under the `Fetching downloads for:` heading, which now
prints lazily from the fetch that reports them (`brew upgrade`
enqueues before it knows that heading's contents). This replaces
`Install.show_combined_fetch_downloads_heading`, `brew upgrade`'s
manual manifest heading predicate and its dead
`show_downloads_heading` plumbing.
- Instrument `Install.perform_preinstall_checks_once` as a
`preinstall_checks` phase timing to keep the reordering visible.
- Archive-cold `brew install hello`: the first transfer starts at
~375ms instead of ~442ms, the bottle no longer waits for the
manifest round trip (~672ms before, ~375ms now) and `--yes` wall
time drops around 30%. Two-formula ask-mode installs drop one full
manifest round trip (~1240ms to ~1030ms).
Occasionally PR's or issues are opened in homebrew/cask due to
applications not matching the right case name on case-sensitive
filesystems. These are relatively rare since most users run with the
standard case-insensitive, but it's still a negative user experience.
This audit is intended to catch these cases.
We will be degrading support to Tier 3 next month so avoid creating new
taps that use Intel macOS. Users that specifically want it should
manually update the generated workflow instead which makes sure they are
aware that support will likely end next year.
- This `formula` helper returning `Class.new(::Formula, &block)` is not
of _instance_ type `Formula` (set in 540457b88b), but
`T.class_of(Formula)`.
- But the accurate `T.proc.bind(T.class_of(::Formula))` can't be used
instead because Sorbet errors with: "Malformed `bind`: Can only bind
to simple class names". See
https://github.com/Homebrew/brew/pull/23318#issuecomment-5087573557.
- Uses of this test helper that need to be typechecked still need
`T.bind(self, T.class_of(Formula))` inline until Sorbet can bind to
`T.class_of` of a class with a fixed `type_template` (maybe never).
- Ruby 4.0's `continuation` warns `callcc is obsolete; use Fiber
instead` whenever it is required, which happens on every `brew`
command that loads a formula from source.
- Run `Ignorable.hook_raise` blocks in a `Fiber`: `raise` now pauses
at the raise site and asks an `on_ignorable` callback whether to
resume (`:ignore`) or raise there as usual, replacing the rescue
plus continuation jump and `Ignorable::ExceptionMixin#ignore`.
- `Debrew` menus and `Formulary` `ignore_errors` decisions now happen
before the stack unwinds, so `ensure` blocks only run when an
exception is actually raised.
- Only require `ignorable` when `Formulary` uses `ignore_errors` and
drop the obsolete `brew verify-undefined` `Warnings` guard.
Fixes https://github.com/Homebrew/brew/issues/23384