docs: update maintainer operations guides

Signed-off-by: Patrick Linnane <patrick@linnane.io>
This commit is contained in:
Patrick Linnane
2026-07-20 11:47:25 -07:00
parent d30c9956a9
commit d81691b615
13 changed files with 207 additions and 195 deletions
+31 -22
View File
@@ -3,40 +3,49 @@ logo: https://brew.sh/assets/img/brewtestbot.png
image: https://brew.sh/assets/img/brewtestbot.png
redirect_from:
- /Brew-Test-Bot-For-Core-Contributors
last_review_date: "1970-01-01"
last_review_date: "2026-07-18"
---
# BrewTestBot for Maintainers
[`brew test-bot`](Manpage.md#test-bot-options-formula) is the command our [CI](https://github.com/BrewTestBot) runs to test and build bottles for formulae.
[`brew test-bot`](Manpage.md#test-bot-options-formula) runs Homebrew's formula checks, builds bottles and tests affected dependents in GitHub Actions.
This page describes maintainer actions after the required checks have completed.
## Publishing Bottles
## Publishing bottles from a pull request
If CI is passing on a pull request and it doesn't need any modifications (e.g. commit message, revision bump, etc.):
When all required jobs pass and the pull request needs no changes:
1. Review and approve the pull request. Be sure to thank the contributor!
2. Wait for BrewTestBot to automatically merge the pull request. This job usually starts within a minute if both of the following are true:
- The pull request is approved by a maintainer who has write access to homebrew-core.
- CI is passing.
1. Review the formula file, including its test, and the generated bottle information.
2. Approve the pull request.
3. Allow BrewTestBot to merge and publish it automatically when repository rules permit.
4. Watch the final publication job and respond to a BrewTestBot failure notification.
If any jobs did not complete successfully, the pull request will not automatically merge. Additionally, BrewTestBot will comment on the pull request if there is a publishing failure.
Passing checks are not a substitute for reviewing the formula file, its test and the generated bottle checksums.
Do not approve a pull request merely to discover whether the publication workflow succeeds.
If a pull request won't be automatically merged by BrewTestBot (has the labels `autosquash`, `automerge-skip`, or`new formula`, or has some kind of acceptable CI failure):
When automatic publication is intentionally unavailable, trigger the supported workflow with the pull-request number or URL:
1. Ensure that bottles have built successfully.
2. Run `brew pr-publish 12345` where `12345` is the pull request number (or URL).
3. Watch the [actions queue](https://github.com/Homebrew/homebrew-core/actions) to ensure your job finishes. BrewTestBot will notify you of failures with a ping as well.
```sh
brew pr-publish PULL_REQUEST
```
If a pull request needs its commit messages changed in a way that autosquash doesn't support (has the label `automerge-skip`):
Use `--autosquash` only when the target tap supports it and the resulting commit structure matches the repository's policy.
Check the [Homebrew/core Actions queue](https://github.com/Homebrew/homebrew-core/actions) until publication finishes.
1. Ensure that bottles have built successfully.
2. Run `brew pr-pull 12345` where `12345` is the pull request number (or URL).
3. Amend any relevant commits if needed, then run `git push` to push the commits to the pull request.
## Changes that require a local commit edit
## Rebottling
Use `brew pr-pull PULL_REQUEST` when a maintainer must download bottle artifacts and edit unpublished commits locally.
Inspect the command's dry-run and help output before using options that change commits or upload artifacts.
If a formula in homebrew-core needs rebottling for any reason:
After editing, run the relevant formula checks, inspect the final commits and push only the intended pull-request branch.
See [Common Issues for Maintainers](Common-Issues-for-Maintainers.md) for preserving the current state before recovering a failed bottle upload from an earlier commit.
1. Navigate to [homebrew-core's rebottling workflow page](https://github.com/Homebrew/homebrew-core/actions/workflows/dispatch-rebottle.yml)
2. Click on the "Run workflow" button on the right of the page.
3. Fill out any necessary fields.
## Rebottling an existing formula
Use the [`homebrew/core` rebottling workflow](https://github.com/Homebrew/homebrew-core/actions/workflows/dispatch-rebottle.yml) when a formula needs new bottles without an ordinary version update.
1. Select **Run workflow**.
2. Enter the formula and required rebuild information.
3. Review the generated pull request and bottle jobs normally.
Do not use rebottling to conceal a formula change that requires a version or revision update.
+4 -4
View File
@@ -8,11 +8,11 @@ last_review_date: "2025-02-08"
# BrewTestBot
[`brew test-bot`](Manpage.md#test-bot-options-formula) is what runs the automated review and testing system funded by [our Kickstarter in 2013](https://www.kickstarter.com/projects/homebrew/brew-test-bot).
[`brew test-bot`](Manpage.md#test-bot-options-formula) is Homebrew's continuous-integration orchestration command, originally funded by [our Kickstarter in 2013](https://www.kickstarter.com/projects/homebrew/brew-test-bot).
Homebrew's GitHub Actions workflows run it on macOS and Linux runners to build bottles and test the lifecycle of changes to Homebrew and its taps.
The workflow definitions are the authoritative description of the current runner and job configuration.
It comprises three Mac Pros hosting virtual machines, several Intel and M1 Mac minis and some cloud Ubuntu instances that run the [`test-bot.rb`](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/dev-cmd/test-bot.rb) command to perform bottle builds and automated testing of the full lifecycle of any change to Homebrew or its taps.
## Pull Requests
## Pull requests
The bot automatically builds pull requests and updates their status depending on the result of the job.
@@ -1,30 +0,0 @@
---
last_review_date: "1970-01-01"
---
# Common Issues for Maintainers
## Overview
This is a page for maintainers to diagnose certain build errors.
## Issues
### Bottle publishes failed but the commits are correct in the git history
Follow these steps to fix this issue:
* Download and extract the bottle artifact.
* `brew pr-upload --no-commit` in the bottle directory.
Alternative instructions using `pr-pull`:
* `git reset --hard <SHA>` in `homebrew/core` to reset to the commit before all the commits created by `brew pr-pull`.
* `brew pr-pull <options>` to upload the right bottles. Add the `--warn-on-upload-failure` switch if the bottles have been partially uploaded and you're certain that the bottle checksums will match the checksums already present in the `bottle do` block of the formula.
* `git reset --hard origin/HEAD` to return to the latest commit and discard the commits made by `brew pr-pull`.
### `ld: internal error: atom not found in symbolIndex(__ZN10SQInstance3GetERK11SQObjectPtrRS0_) for architecture x86_64`
The exact atom may be different.
This can be caused by passing the obsolete `-s` option to the linker and can be fixed [using `inreplace`](https://github.com/Homebrew/homebrew-core/commit/c4ad981d788b21a406a6efe7748f2922986919a8).
+52
View File
@@ -0,0 +1,52 @@
---
last_review_date: "2026-07-18"
redirect_from:
- /Common-Issues-for-Core-Contributors
---
# Common Issues for Maintainers
This page records maintainer-only recovery procedures that are not part of normal user troubleshooting.
Preserve local work and prefer a temporary clone or Git worktree when reproducing an older repository state.
## Bottle publication failed after the commits were created
If the formula commits are correct and only bottle publication failed:
1. Download and extract the bottle artifact from the failed workflow.
2. Change to the extracted artifact directory.
3. Run `brew pr-upload --no-commit` with the appropriate upload options.
`brew pr-pull` always operates on the canonical tap checkout, regardless of the current directory.
If it must be repeated from an earlier commit, first ensure that the canonical `homebrew/core` checkout has no uncommitted work, fetch its remote and create a backup branch at its current commit:
```sh
git -C "$(brew --repository homebrew/core)" status --short
git -C "$(brew --repository homebrew/core)" fetch origin
git -C "$(brew --repository homebrew/core)" branch pr-pull-recovery-backup
```
Reset the canonical checkout to the commit before the commits created by the failed `brew pr-pull`, then repeat the command with the original options:
```sh
git -C "$(brew --repository homebrew/core)" reset --hard COMMIT_SHA
brew pr-pull PULL_REQUEST
```
Add `--warn-on-upload-failure` only when bottles were partially uploaded and their checksums are known to match the existing `bottle do` block.
After publication succeeds, return the checkout to the remote default branch:
```sh
git -C "$(brew --repository homebrew/core)" reset --hard origin/HEAD
```
Delete the backup branch only after confirming that it is no longer needed.
Do not use this recovery procedure when the canonical checkout contains work that has not been committed or preserved elsewhere.
## Unfamiliar build failures
Do not add a permanent workaround based only on an old issue or an exact linker error string.
Reproduce the failure on a supported runner, inspect the compiler and linker invocation, then determine whether the problem comes from the formula, upstream or the runner image.
Document reusable findings in the relevant maintainer or formula-author guide instead of adding one-off historical errors to this page.
+7 -17
View File
@@ -1,5 +1,5 @@
---
last_review_date: "2025-02-08"
last_review_date: "2026-07-18"
---
# Homebrew/brew Maintainer Guide
@@ -26,22 +26,12 @@ The prior approval may be on a `Homebrew/brew` PR from a fork, because that appr
## CI
Every PR in `Homebrew/brew` runs a series of CI tests to try to prevent bugs from being introduced. **A PR _must_ have passing CI before it can be merged.**
Every PR in `Homebrew/brew` runs continuous-integration checks intended to prevent regressions.
A PR must have passing required checks before it can be merged.
There are many checks that run on every PR. The following is a quick list of the various checks and what they represent:
- `Vendor Gems / vendor-gems`: This is skipped except for dependabot PRs. It updates the RBI files to match any new/changed dependencies. See [Type Checking With Sorbet](Typechecking.md) for more information about RBI files and typechecking.
- `Codecov / codecov/patch` and `codecov/project`: These show the Codecov report for the PR. See the [`brew tests` and Codecov](#brew-tests-and-codecov) section below for more info about Codecov.
- `CI / vendored gems`: This checks whether there was a change to the vendored gems on Linux that needs to be committed to the PR branch.
- `CI / test default formula (Linux)`: This runs `brew test-bot` on Linux to ensure it still works as expected.
- `CI / syntax`: This is run first to check whether the PR passes `brew style` and `brew typecheck`. If this job fails the following jobs will not run.
- `CI / tap syntax`: This runs `brew style` and `brew audit` on all official taps (note that although this runs on Linux, it does check all cask repositories).
- `CI / docker`: This builds and deploys a new Homebrew Docker image to GitHub Packages and Docker Hub.
- `CI / test everything (macOS)`: This runs several checks on macOS including `brew tests`, `brew update-tests`, `brew test-bot --only-formulae --test-default-formula`, `brew readall` and `brew doctor`.
- `CI / tests (generic OS)` and `CI / tests (Linux)`: These run `brew tests` with various options on Linux.
- `Documentation CI / linting` and `rubydoc`: These check the prose and formatting of the written documentation, and verify the [Homebrew Ruby API documentation](/rubydoc/index.html) can be built without issue.
_Note that this list is non-exhaustive and can change over time._
Depending on the files changed, the workflows check type signatures and style, run unit and integration tests on macOS and Linux, audit formulae and casks, validate vendored dependencies, build the documentation and test packaging such as the Docker image.
Codecov reports test coverage separately.
The current [GitHub Actions workflows](https://github.com/Homebrew/brew/tree/HEAD/.github/workflows) and the pull request's checks are authoritative; job names and path-based triggers change over time.
### `brew tests` and Codecov
@@ -55,7 +45,7 @@ CodeCov can be used as a guide to identify which flaky tests are causing the mos
To help find the root cause for a particular flaky test, CodeCov provides links to the most recent CI job and commit where the test failed and then passed with no change to the underlying code. You may want to check out the code at that commit to attempt to reproduce the failure locally. You can also see the list of recent failures on CodeCov to determine if the test always fails the same way.
## Manpages and Shell Completions
## Manpages and shell completions
Homebrew's manpages and shell completions are generated automatically by the `brew generate-man-completions` command. Contributors are welcome to run this command and commit the changes in a PR, but they don't have to. If they don't, a follow-up PR to make the necessary changes will be opened automatically by [@BrewTestBot](https://github.com/BrewTestBot) once the original PR is merged. These follow-up PRs can be merged immediately if the changes seem correct.
+14 -15
View File
@@ -1,12 +1,12 @@
---
last_review_date: "2026-07-17"
last_review_date: "2026-07-18"
---
# Homebrew/homebrew-cask Maintainer Guide
This guide is intended to help maintainers effectively maintain the cask repository. It is meant to be used in conjunction with the more generic [Maintainer Guidelines](Maintainer-Guidelines.md).
This guide is intended to help maintainers effectively maintain the `homebrew/cask` repository. It is meant to be used in conjunction with the more generic [Maintainer Guidelines](Maintainer-Guidelines.md).
## Common Situations
## Common situations
Here is a list of the most common situations that arise in cask PRs and how to handle them:
@@ -14,39 +14,38 @@ Here is a list of the most common situations that arise in cask PRs and how to h
- Only the `sha256` changes: Treat this as a retagged cask and follow the policy below.
- `livecheck` is updated: Use your best judgement and try to make sure that the changes follow the [`livecheck` guidelines](Brew-Livecheck.md).
- Only the `version` changes or the `version` format changes: Use your best judgement and merge if it seems correct (this is relatively rare).
- Other changes (including adding new casks): Use the [Cask Cookbook](Cask-Cookbook.md) to determine what's correct.
- Other changes, including adding new casks: Start with [Acceptable Casks](Acceptable-Casks.md) and the [shared package acceptance policy](Package-Acceptance-Policy.md), then use the [Cask Cookbook](Cask-Cookbook.md) for implementation details.
If in doubt, ask another cask maintainer on GitHub or Slack.
Unlike formulae, a cask's `sha256` stanza does not prove that an artefact is authentic because maintainers cannot realistically reproduce proprietary binaries.
Unlike formulae, a cask's `sha256` stanza does not prove that an artifact is authentic because maintainers cannot realistically reproduce proprietary binaries.
It does reveal when a pinned download has changed.
Casks download from upstream; if a malicious actor compromised a URL, they could potentially compromise a version and make it look like an update.
## Retagged Casks
## Retagged casks
Some vendors replace an existing versioned download in place.
If the checksum changes without a corresponding version change, treat this as a potential upstream compromise or supply-side attack rather than a routine update.
Where possible, contact the vendor through an official contact page, public bug tracker or similar channel and ask them to confirm why the artefact changed and that it was not the result of a compromise.
If the checksum changes without a corresponding version change, treat this as a potential upstream compromise or supply-chain attack rather than a routine update.
Where possible, contact the vendor through an official contact page, public bug tracker or similar channel and ask them to confirm why the artifact changed and that it was not the result of a compromise.
Do not open or merge a PR updating the cask's checksum until the vendor has confirmed the change was intentional or it has been verified under the exception below.
The PR should link to the vendor's confirmation.
Use a lower verification bar for a proprietary cask whose vendor has no practical public contact channel.
In this case, direct confirmation is not required if the PR documents the code-signing result, when available, and the strongest other evidence, such as official release information.
## Deprecating, Disabling and Removing Casks
## Deprecating, disabling and removing casks
Do not deprecate, disable or remove a cask just because upstream asks us to or claims Homebrew's packaging is "broken". If our analytics show non-zero installs and our issue tracker is not receiving user reports that the cask is broken, keep it unless there is a clear enough technical, policy or project-wide reason to do otherwise.
When this happens, point upstream developers to [Working with Homebrew as an Upstream Project](Working-with-Homebrew-as-an-Upstream-Project.md) and keep the discussion in public on GitHub.
Apply the shared policy for [upstream removal requests](Deprecating-Disabling-and-Removing.md#upstream-removal-requests).
## Merging
In general, using GitHub's "Merge" button is the best way to merge a PR. This can be used when the PR modifies only one cask, regardless of the number of commits or whether the commit message format is correct. When merging using this method, the commit message can be modified if needed. Usually, version bump commit messages follow the form `Update CASK from OLD_VERSION to NEW_VERSION`.
In general, using GitHub's "Merge" button is the best way to merge a PR. This can be used when the PR modifies only one cask, regardless of the number of commits or whether the commit message format is correct. When merging using this method, the commit message can be modified if needed. Usually, version bump commit messages follow the form `CASK NEW_VERSION`.
If the PR modifies multiple casks, use the "Rebase and Merge" button to merge the PR. This will use the commit messages from the PR, so make sure that they are appropriate before merging. If needed, checkout the PR, squash/reword the commits and force-push back to the PR branch to ensure the proper commit format.
Finally, make sure to thank the contributor for submitting a PR!
## Other Tips
## Other tips
A maintainer can easily rebase a PR onto the latest default branch by adding a `/rebase` comment. `BrewTestBot` will automatically rebase the PR and add a reaction to the comment once the rebase is in progress and complete.
Use GitHub's update-branch control when it is available.
Otherwise, check out the contributor's branch, rebase it onto the latest default branch and force-push only after confirming that the contributor permits maintainer edits.
+35 -59
View File
@@ -1,12 +1,13 @@
---
last_review_date: "2026-07-17"
last_review_date: "2026-07-18"
---
# Homebrew/homebrew-core Maintainer Guide
## Quick merge checklist
A detailed checklist can be found [below](#detailed-merge-checklist). This is all that really matters:
A detailed checklist appears [below](#detailed-merge-checklist).
Use this summary for routine reviews, then consult the detailed checklist when a change has unusual dependencies, build behaviour or release history:
- Ensure the name seems reasonable.
- Add aliases.
@@ -17,69 +18,38 @@ A detailed checklist can be found [below](#detailed-merge-checklist). This is al
- Use `brew pr-publish` or `brew pr-pull` otherwise, which adds messages to auto-close pull requests and pull bottles built by BrewTestBot.
- Thank people for contributing.
Checking dependencies is important, because they will probably stick around forever. Nobody really checks if they are necessary or not.
Review dependencies carefully because unnecessary dependencies impose an ongoing build, security and maintenance cost.
Revisit existing dependencies when upstream changes its defaults or removes a feature.
Depend on as little stuff as possible. Disable X11 functionality if possible. For example, we build Wireshark, but not the heavy GUI.
Keep the dependency graph as small as practical while preserving the supported functionality users reasonably expect.
Disable optional X11 functionality when it adds substantial dependencies and does not provide a suitable default macOS experience.
Homebrew is about Unix software. Stuff that builds to an `.app` should be in Homebrew Cask instead.
`homebrew/core` primarily packages command-line software and libraries.
Software whose primary artifact is a native macOS `.app` belongs in `homebrew/cask` as a cask.
## Dependencies and full variants
In `Homebrew/homebrew-core`, the default formula should generally carry the
dependencies needed to build and test the software and to satisfy other
formulae in `Homebrew/homebrew-core`. We should not try to enable every
optional upstream feature in the default formula, particularly when doing so
adds a large recursive dependency tree.
When deciding whether to add or keep a dependency:
- keep dependencies that are required to build, test or support current
`Homebrew/homebrew-core` dependents
- keep or add lightweight dependencies when they avoid obvious, surprising or
silent breakage in common workflows
- keep or add dependencies when they avoid relying on deprecated or
problematic system components
- avoid dependencies that only enable optional upstream features for a subset
of users, especially when they pull in many recursive dependencies
Repeated, specific user requests can justify adding a lightweight dependency
back to the default formula, particularly when missing support causes
surprising behaviour rather than a clear failure.
For formulae that need both a light default build and a maximal build, a
`*-full` formula can be appropriate. In these cases:
- other `Homebrew/homebrew-core` formulae should not depend on the `*-full`
formula
- the non-`-full` formula should remain the formula that other
`Homebrew/homebrew-core` formulae depend on
- the `*-full` formula should be treated as a rare escape hatch for extra
features rather than the default dependency target
- the conflicting sibling should be `keg_only` when needed so both formulae
can coexist
- these variants should be used sparingly and are best suited to formulae
whose `-full` variant is effectively a leaf in `Homebrew/homebrew-core`
If users want dependents to use a different dependency trade-off than
`Homebrew/homebrew-core` provides, that should generally live in a tap rather
than making more `Homebrew/homebrew-core` formulae depend on a `*-full`
formula.
Apply the contributor-facing [dependency and full-variant acceptance policy](Acceptable-Formulae.md#dependencies-and-full-variants).
When reviewing an existing dependency, also consider whether removing it would cause surprising breakage in common workflows or force formulae to rely on a deprecated system component.
## Merging, rebasing, cherry-picking
For most PRs that make formula modifications, you can simply approve the PR and an automatic merge (with bottles) will be performed by [@BrewTestBot](https://github.com/BrewTestBot). See [BrewTestBot for Maintainers](BrewTestBot-For-Maintainers.md) for more information.
Certain PRs may not be merged automatically by [@BrewTestBot](https://github.com/BrewTestBot), even after they've been approved. This includes PRs with the `new formula` and `automerge-skip` labels. To trigger a merge for these PRs, run `brew pr-publish`.
Some PRs may not be merged automatically by [@BrewTestBot](https://github.com/BrewTestBot), even after approval.
Inspect the current workflow result and labels to determine why automation stopped, then run `brew pr-publish` when manual publication is appropriate.
PRs modifying formulae that don't need bottles or making changes that don't require new bottles to be pulled should use GitHub's squash & merge or rebase & merge workflows.
Otherwise, you should use `brew pr-pull` (or `rebase`/`cherry-pick` contributions).
Dont `rebase` until you finally `push`. Once `main` is pushed, you cant `rebase`: **youre a maintainer now!**
Do not rebase commits after they have been pushed to `main`.
Rewrite only unpublished commits and inspect the final history before pushing.
Cherry-picking changes the date of the commit, which kind of sucks.
Cherry-picking changes commit metadata, so preserve the original contribution and authorship information when using it.
Dont `merge` unclean branches. So if someone is still learning `git` and their branch is filled with nonsensical merges, then `rebase` and squash the commits. Our main branch history should be useful to other people, not confusing.
Do not merge a branch whose history contains unrelated or accidental merge commits.
Rebase or squash unpublished contributor commits when needed so the `main` branch records a clear, reviewable change history.
Only one maintainer is necessary to approve and merge the addition of a new or updated formula which passes CI. However, if the formula addition or update proves controversial the maintainer who adds it will be expected to answer requests and fix problems that arise with it in future.
@@ -106,18 +76,26 @@ We now accept versioned formulae as long as they [meet the requirements](Version
## Testing
We need to at least check that it builds. Use [BrewTestBot](BrewTestBot.md) for this.
Every formula change must at least build successfully in the required BrewTestBot jobs.
Use [BrewTestBot](BrewTestBot.md) for this validation.
Verify the formula works if possible. If you cant tell (e.g. if its a library) trust the original contributor; it worked for them, so chances are it is fine. If you arent an expert in the tool in question, you cant really gauge if the formula installed the program correctly. At some point an expert will come along, cry blue murder that it doesnt work, and fix it. This is how open source works. Ideally, request a `test do` block to test that functionality is consistently available.
Verify installed functionality rather than relying solely on the contributor's local result.
Require a meaningful `test do` block that exercises the installed software without network access.
For a library, compile and run a small program against the installed headers and library when practical.
If the reviewer cannot evaluate specialised behaviour, request reproducible validation from upstream documentation, an existing test suite or another reviewer with relevant knowledge.
If the formula uses a repository, then the `url` parameter should have a tag or revision. `url`s have versions and are stable (not yet implemented!).
If a formula uses a source-code repository, its `url` must identify an immutable tag or revision.
Do not package a moving branch as a stable release.
Don't merge any formula updates with failing `brew test`s. If a `test do` block is failing it needs to be fixed. This may involve replacing more involved tests with those that are more reliable. This is fine: false positives are better than false negatives as we don't want to teach maintainers to merge red PRs. If the test failure is believed to be due to a bug in `Homebrew/brew` or the CI system, that bug must be fixed, or worked around in the formula to yield a passing test, before the PR can be merged.
Do not merge a formula update with a failing `brew test`.
Fix the failure or replace a flaky test with a reliable test that still detects whether the installed software works.
If the failure comes from Homebrew or CI, fix that problem or add a narrowly scoped formula workaround before merging.
Do not normalise merging a red pull request.
## Retagged formulae
Upstream source archives and Git tags for released versions are expected to be immutable.
If the checksum of a fixed-version source archive changes or a Git tag moves to a different commit, treat this as a potential upstream compromise or supply-side attack rather than a routine update.
If the checksum of a fixed-version source archive changes or a Git tag moves to a different commit, treat this as a potential upstream compromise or supply-chain attack rather than a routine update.
Where possible, contact upstream through an official channel, preferably a public issue tracker, and ask them to confirm why the source changed and that it was not the result of a compromise.
Do not open or merge a PR updating the formula's checksum, revision or source until upstream has confirmed the change was intentional.
@@ -127,7 +105,7 @@ If the change cannot be verified, deprecate the formula with `:checksum_mismatch
## Duplicates
We now accept stuff that comes with macOS as long as it uses `keg_only :provided_by_macos` to be [keg-only](FAQ.md#what-does-keg-only-mean) by default.
Software that duplicates a macOS-provided tool or library may be accepted when it uses `keg_only :provided_by_macos` and otherwise meets the [formula acceptance criteria](Acceptable-Formulae.md).
## Removing formulae
@@ -140,9 +118,7 @@ Formulae that:
should not be removed from Homebrew. The exception to this rule are [versioned formulae](Versions.md) for which there are higher standards of usage and a maximum number of versions for a given formula.
An upstream request or claim that Homebrew's packaging is "broken" is not enough of a reason to deprecate, disable or remove a formula when users are not reporting breakage in our issue tracker and our analytics show continued installs.
When this happens, point upstream developers to [Working with Homebrew as an Upstream Project](Working-with-Homebrew-as-an-Upstream-Project.md) and keep the discussion in public on GitHub.
Apply the shared policy for [upstream removal requests](Deprecating-Disabling-and-Removing.md#upstream-removal-requests).
For more information about deprecating, disabling and removing formulae, see the [Deprecating, Disabling and Removing](Deprecating-Disabling-and-Removing.md#formulae-and-casks) page.
@@ -186,14 +162,14 @@ The following checklist is intended to help maintainers decide on whether to mer
- make sure it has one commit per revision bump
- if CI is green and...
- bottles need to be pulled, and...
- the commits are correct, don't need changes, and BrewTestBot can merge it (doesn't have the label `automerge-skip`): approve the PR to trigger an automatic merge (use `brew pr-publish $PR_ID` to trigger manually in case of a new formula)
- the commits are correct, don't need changes, and BrewTestBot can merge it: approve the PR to trigger an automatic merge (use `brew pr-publish $PR_ID` to trigger it manually when necessary)
- the commits are correct and don't need changes, but BrewTestBot can't merge it (has the label `automerge-skip`): use `brew pr-publish $PR_ID`
- the commits need to be amended: use `brew pr-pull $PR_ID`, make changes, and `git push`
- don't forget to thank the contributor
- celebrate any first-time contributors
- suggest using `brew bump-formula-pr` next time if this was not the case
## Staging Branches
## Staging branches
### Summary
+6 -5
View File
@@ -17,7 +17,7 @@ All Homebrew maintainers are encouraged to contribute to all parts of the projec
- Linux maintainers: this team maintains the [`Homebrew/homebrew-core`](https://github.com/Homebrew/homebrew-core) repository on Linux.
- Cask maintainers: this team maintains the [`Homebrew/homebrew-cask`](https://github.com/Homebrew/homebrew-cask) repository. See the [Homebrew/homebrew-cask Maintainer Guide](Homebrew-homebrew-cask-Maintainer-Guide.md) for more details about being a cask maintainer.
These documents are meant to serve as guiding principles. As a maintainer, you can make a call to either request changes from a contributor or help them out based on their comfort and previous contributions. Remember, as a team we [Prioritise Maintainers Over Users](Maintainers-Avoiding-Burnout.md) to avoid burnout. If you wish to change or discuss any of the guidelines: open a PR to suggest a change.
These documents are meant to serve as guiding principles. As a maintainer, you can make a call to either request changes from a contributor or help them out based on their comfort and previous contributions. Remember, as a team we [prioritise maintainers over users](Maintainers-Avoiding-Burnout.md#3-prioritise-maintainers-over-users) to avoid burnout. If you wish to change or discuss any of the guidelines, open a PR to suggest a change.
## Reviewing PRs
@@ -32,7 +32,7 @@ When reviewing a PR, use "approve", "approve with comments", "comment" or "reque
- 🚫 Request changes: a last resort.
- When reviewing non-maintainers' PRs: this means "these changes must be made before this PR should be merged by anyone".
Other maintainers can dismiss this review when these changes have been made.
- When reviewing others maintainers' PRs: this is to be avoided whenever possible.
- When reviewing other maintainers' PRs: this is to be avoided whenever possible.
- Save it for "if this PR is merged before I personally have had a chance to ✅ approve it: it seems very likely to cause user-visible problems".
- It may be used by the Project Leader for "this functionality is not acceptable in Homebrew".
In that case: additional code changes should be held off until there's agreement that the functionality is acceptable.
@@ -62,12 +62,12 @@ Homebrew aims to be the missing package manager for macOS (and Linux). Its prima
## Common “gotchas”
1. [Ensure you have set your username and email address properly](https://help.github.com/articles/setting-your-email-in-git/)
2. Sign off cherry-picks if you amended them (use `git -s`)
2. Sign off cherry-picks if you amended them (use `git commit --amend --signoff`)
3. If your commit fixes a bug, use [issue linking syntax](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) (e.g. “Fixes \#104”) to close the bug report and link back to the commit
### Add comments
It may be enough to refer to an issue ticket, but make sure changes and context are clear enough so that anyone reading them for the first time can make sense of them. You don't want code you wrote to be removed because the someone new doesnt understand why its there. Regressions suck.
It may be enough to refer to an issue ticket, but make sure changes and context are clear enough so that anyone reading them for the first time can make sense of them. You don't want code you wrote to be removed because someone new doesnt understand why its there. Regressions are frustrating.
This also applies to issue and PR bodies. Be as explicit as possible. If a pull request is part of a larger initiative: link to a relevant tracking issue. If there isn't a tracking issue yet: create one to improve communication and get consensus.
@@ -75,7 +75,8 @@ This also applies to issue and PR bodies. Be as explicit as possible. If a pull
Amend a cherry-pick to remove commits that are only changes in whitespace. They are not acceptable because our history is important and `git blame` should be useful.
Whitespace corrections (to Ruby standard etc.) are allowed (in fact this is a good opportunity to do it) provided the line itself has some kind of modification that is more than just whitespace changes. But be careful about making changes to inline patches—make sure they still apply.
Whitespace corrections to match Ruby style are allowed when the line already has a substantive modification.
Be careful when changing inline patches; make sure they still apply.
### Closing issues/PRs
+4 -4
View File
@@ -16,7 +16,7 @@ you won't be a good maintainer unless you can put yourself in the shoes of our
users, but also because you may decide to stop using Homebrew and at that point
you should also decide not to be a maintainer and find other things to work on.
## 2. No Guilt About Leaving
## 2. No guilt about leaving
All maintainers can stop working on Homebrew at any time without any guilt or
explanation (like leaving a job). We may still ask for your help with questions
@@ -30,7 +30,7 @@ This also means contributors should be consumers. If an owner finds they are
not using a project in the real world, they should reconsider their involvement
with the project.
## 3. Prioritise Maintainers Over Users
## 3. Prioritise maintainers over users
It's important to be user-focused but ultimately, as long as you follow #1
above, Homebrew's minimum number of users will be the number of maintainers.
@@ -40,7 +40,7 @@ need takes priority over the burnout of maintainers. If users do not like the
direction of the project, the easiest way to influence it is to make
significant, high-quality code contributions and become a maintainer.
## 4. Learn To Say No
## 4. Learn to say no
Homebrew gets a lot of feature requests, non-reproducible bug reports, usage
questions and PRs we won't accept. These should be closed out as soon as we
@@ -48,7 +48,7 @@ realise that they aren't going to be resolved or merged. This is kinder than
deciding this after a long period of review. Our issue tracker should reflect
work to be done.
## 5. Slow Down
## 5. Slow down
We're a volunteer-run open source project used by a lot of people. That can mean
that it feels like there's a lot of pressure to get a fix, package or project
+6 -6
View File
@@ -4,7 +4,7 @@ last_review_date: "2025-02-08"
# New Maintainer Checklist
**Existing maintainers and project leadership uses this guide to invite and onboard new maintainers and project leaders.**
**Existing maintainers and project leadership use this guide to invite and onboard new maintainers and project leaders.**
**General Homebrew users might find it interesting but there's nothing here _users_ should have to know.**
- [Homebrew Maintainers](#maintainers)
@@ -28,7 +28,7 @@ If you agree to be a maintainer, you should spend the majority of the time you
are working on Homebrew (in descending order of priority):
- reviewing pull requests (from users and other maintainers)
- triaging, debugging and fixing user-reported issues and applying
- triaging, debugging and fixing user-reported issues
- opening PRs for widely used changes (e.g. version updates)
You should also be making contributions to Homebrew at least once per quarter.
@@ -67,14 +67,14 @@ Thanks for all your work so far!
If they accept, follow a few steps to get them set up:
- Invite them to the [**@Homebrew/maintainers** team](https://github.com/Homebrew/private/blob/main/user-management/.tfvars#L23) (or any relevant subteams) by making a pull request to linked file. This gives them write access to relevant repositories (but doesn't make them owners). They will need to enable [GitHub's Two Factor Authentication](https://help.github.com/articles/about-two-factor-authentication/).
- Invite them to the [**@Homebrew/maintainers** team](https://github.com/Homebrew/private/blob/main/user-management/.tfvars) or any relevant subteams by making a pull request to the linked file. This gives them write access to relevant repositories but does not make them owners. They will need to enable [GitHub's two-factor authentication](https://help.github.com/articles/about-two-factor-authentication/).
- Invite them as a full member to the [`machomebrew` private Slack](https://machomebrew.slack.com/admin/invites) (and ensure they've read the [communication guidelines](Maintainer-Guidelines.md#communication)) and ask them to use their real name there (rather than a pseudonym they may use on e.g. GitHub).
- Ask them to disable SMS as a 2FA device or fallback on their GitHub account in favour of using one of the other authentication methods.
- Ask them to (regularly) review remove any unneeded [GitHub personal access tokens](https://github.com/settings/tokens).
- Ask them to review and remove unneeded [GitHub personal access tokens](https://github.com/settings/tokens) regularly.
If there are problems, ask them to step down as a maintainer.
When they cease to be a maintainer for any reason, revoke their access to all of the above, and don't forget to remove them from the [user-management tooling](https://github.com/Homebrew/private/blob/main/user-management/.tfvars#L23).
When they cease to be a maintainer for any reason, revoke their access to all of the above and remove them from the [user-management tooling](https://github.com/Homebrew/private/blob/main/user-management/.tfvars).
In the interests of loosely verifying maintainer identity and building camaraderie, if you find yourself in the same town (e.g living, visiting or at a conference) as another Homebrew maintainer you should make the effort to meet up. If you do so, you can [expense your meal](https://docs.opencollective.com/help/expenses-and-getting-paid/submitting-expenses) (within [Homebrew's reimbursable expense policies](https://opencollective.com/homebrew/expenses)). This is a more relaxed version of similar policies used by other projects, e.g. the Debian system to meet in person to sign keys with legal ID verification.
@@ -82,7 +82,7 @@ Now sit back, relax and let the new maintainers handle more of our contributions
## Lead Maintainers
If a maintainer or member is elected to the Homebrew's Lead Maintainers:
If a maintainer is elected as a Homebrew Lead Maintainer:
- Invite them to the [**@Homebrew/lead-maintainers** team](https://github.com/orgs/Homebrew/teams/lead-maintainers/members)
+42 -29
View File
@@ -1,47 +1,60 @@
---
last_review_date: "1970-01-01"
last_review_date: "2026-07-18"
---
# Releases
Since Homebrew 1.0.0 most Homebrew users (those who haven't run a `dev-cmd` or set `HOMEBREW_DEVELOPER=1` which is ~99.9% based on analytics data) require tags on the [Homebrew/brew repository](https://github.com/homebrew/brew) in order to receive new versions of Homebrew. There are a few steps in making a new Homebrew release:
Homebrew users receive new versions of Homebrew/brew from GitHub release tags.
Only maintainers with write access to Homebrew/brew can create a release.
1. Check if there is anything pressing that needs to be fixed or merged before the next release in:
- [`Homebrew/brew` pull requests](https://github.com/homebrew/brew/pulls)
- [`Homebrew/brew` issues](https://github.com/homebrew/brew/issues)
- [`Homebrew/homebrew-core` issues](https://github.com/homebrew/homebrew-core/issues)
- [Homebrew/discussions (forum)](https://github.com/orgs/Homebrew/discussions)
## Prepare the release
If so, fix and merge these changes.
1. Check for urgent work that should be resolved before the release:
- [`Homebrew/brew` pull requests](https://github.com/Homebrew/brew/pulls)
- [`Homebrew/brew` issues](https://github.com/Homebrew/brew/issues)
- [`Homebrew/homebrew-core` issues](https://github.com/Homebrew/homebrew-core/issues)
- [Homebrew Discussions](https://github.com/orgs/Homebrew/discussions)
2. Confirm that the workflows on Homebrew/brew's `main` branch are passing and that at least one recent Homebrew/homebrew-core pull request has completed CI successfully.
3. Allow enough time after the last code change to detect regressions before releasing.
4. Confirm that the current `main` branch is suitable for release.
2. Ensure that:
- no code changes have happened for at least a couple of hours (ideally 4 hours),
- at least one Homebrew/homebrew-core pull request CI job has completed successfully,
- the state of the Homebrew/brew `main` CI job is clear (i.e. main jobs green or green after rerunning)
- you are confident there are no major regressions on the current `main` branch.
Do not create a release from an older commit on `main`.
If unreleased changes must be excluded from an urgent patch release, revert those changes, complete the release process and then reapply them.
3. Run `brew release` to create a new draft release. For major or minor version bumps, pass `--major` or `--minor`, respectively.
## Create the release
4. Publish the draft release on [GitHub](https://github.com/Homebrew/brew/releases).
Preview the release notes and version number:
If this is a major or minor release (e.g. X.0.0 or X.Y.0) then there are a few more steps:
```sh
brew release
```
1. Before creating the tag you should:
- delete any `odisabled` code,
- make any `odeprecated` code `odisabled`,
- uncomment any `# odeprecated` code
- add any new `odeprecations` that are desired.
Pass `--major` or `--minor` to preview a major or minor release instead of the default patch release.
Homebrew will refuse to create a major or minor release if the previous major or minor release was less than one month ago.
Also delete any command argument definitions that pass `replacement: ...`.
After reviewing the preview, create the draft release and trigger the release workflow:
See [Deprecating, Disabling and Removing](Deprecating-Disabling-and-Removing.md#the-deprecation-lifecycle) for details on the deprecation lifecycle.
```sh
brew release --force
```
2. Write up a release notes blog post for <https://brew.sh> (e.g. [brew.sh#319](https://github.com/Homebrew/brew.sh/pull/319)). This should use the output from `brew release [--major|--minor]` as input but have the wording adjusted to be more human readable and explain not just what has changed but why.
Include `--major` or `--minor` when required.
Review the resulting [draft release](https://github.com/Homebrew/brew/releases), confirm the version and notes, then publish it.
3. When the release has shipped and the blog post has been merged, tweet the blog post as the [@MacHomebrew Twitter account](https://twitter.com/MacHomebrew) or tweet it yourself and retweet it with the @MacHomebrew Twitter account (credentials are in 1Password).
## Major and minor releases
4. Consider whether to submit it to other sources, e.g. Hacker News, Reddit.
- Pros: gets a wider reach and user feedback
- Cons: negative comments are common and people take this as a chance to complain about Homebrew (regardless of their usage)
Before creating a major or minor release:
Please do not manually create a release based on older commits on the `main` branch. It's very hard to judge whether these have been sufficiently tested by users or if they will cause negative side effects with the current state of Homebrew/homebrew-core. If a new branch is needed ASAP but there are things on `main` that cannot be released yet (e.g. new deprecations and you want to make a patch release) then revert the relevant PRs, follow the process above and then revert the reverted PRs to reapply them on `main`.
1. Remove code marked `odisabled`.
2. Change code marked `odeprecated` to `odisabled`.
3. Uncomment code marked `# odeprecated` when it should enter the deprecation cycle.
4. Add planned `odeprecations`.
5. Remove command argument definitions that still pass `replacement:`.
See [Deprecating, Disabling and Removing](Deprecating-Disabling-and-Removing.md#the-deprecation-lifecycle) for the complete lifecycle.
Use the output from `brew release [--major|--minor]` as the basis for a release notes post on the [Homebrew website](https://brew.sh/).
Edit the generated notes to explain the purpose and user impact of the changes, not only what changed.
After the release and post are published, announce them through the project communication channels currently maintained by Homebrew.
Consider broader announcement channels only when their expected reach and moderation cost are appropriate for the release.
+5 -3
View File
@@ -8,7 +8,7 @@ The majority of the code in Homebrew is written in Ruby which is a dynamic langu
The [Sorbet Documentation](https://sorbet.org/docs/overview) is a good place to get started if you want to dive deeper into Sorbet and its abilities.
## Sorbet in the Homebrew Codebase
## Sorbet in the Homebrew codebase
### Inline type annotations
@@ -46,7 +46,9 @@ The `rbi` directory contains all Ruby Interface (`.rbi`) files auto-generated by
- `gems`: RBI files for all gems are generated using [Tapioca](https://github.com/Shopify/tapioca#tapioca).
- `dsl`: RBI files auto-generated by our [Tapioca compilers](https://github.com/Homebrew/brew/tree/HEAD/Library/Homebrew/sorbet/tapioca/compilers).
- `upstream.rbi`: This file is manually written and contains temporary workarounds for upstream Sorbet issues. It is typically empty.
- `annotations`: handwritten refinements for gem interfaces generated elsewhere.
- `shims`: handwritten interfaces for dynamically defined Homebrew code and other gaps.
- `upstream.rbi`: temporary workarounds for upstream Sorbet issues.
The `tapioca` directory contains configuration files and compilers for Tapioca, allowing Sorbet to type check the dynamically generated components of the codebase.
@@ -58,7 +60,7 @@ Every Ruby file in the codebase has a magic `# typed: <level>` comment at the to
When run without any arguments, `brew typecheck` will run considering the strictness levels set in each of the individual Ruby files in the core Homebrew codebase. However, when run on a specific file or directory, more errors may show up since Sorbet cannot resolve constants defined outside the scope of the specified file. These problems can be solved with RBI files. Currently `brew typecheck` provides `--quiet`, `--file`, `--dir` and `--ignore` options, but you can explore more options with `srb tc --help` and pass them with `srb tc`.
## Resolving Type Errors
## Resolving type errors
Sorbet reports type errors along with an error reference code, which can be used to look up more information on how to debug the error, or what causes the error in the [Sorbet Documentation](https://sorbet.org/docs/overview). Here's how to debug some common type errors:
+1 -1
View File
@@ -82,7 +82,7 @@ Documentation is grouped below by audience: users, contributors, maintainers and
- [Homebrew/homebrew-cask Maintainer Guide](Homebrew-homebrew-cask-Maintainer-Guide.md)
- [BrewTestBot for Maintainers](BrewTestBot-For-Maintainers.md)
- [Common Issues for Maintainers](Common-Issues-for-Core-Contributors.md)
- [Common Issues for Maintainers](Common-Issues-for-Maintainers.md)
- [Releases](Releases.md)
- [Linux CI](Linux-CI.md)