4.7 KiB
Homebrew packaging for beefy-player
A Homebrew tap is just a second git repository that Homebrew clones next to
homebrew/core. There is no central submission, no review and no binary host:
brew reads the Ruby formula from the tap, downloads the pinned source tarball
and installs it on the user's machine.
This directory is the staging area for the tap repository, which lives at
https://tildeforge.dev/beefcarver/homebrew-tap (repo name homebrew-tap, so
the tap name is beefcarver/tap).
Because Homebrew's one-argument brew tap assumes GitHub, a Forgejo tap has to
be tapped with its URL, and Homebrew 6+ also wants an explicit trust.
Install (user side)
brew tap beefcarver/tap https://tildeforge.dev/beefcarver/homebrew-tap
brew trust --formula beefcarver/tap/beefy-player
brew install beefcarver/tap/beefy-player
brew update refreshes the tap from then on; brew upgrade picks up new
versions like any core formula. If the tap is mirrored to GitHub later,
brew install beefcarver/tap/beefy-player becomes a one-liner, because that
form auto-taps from GitHub and trusts only the formula it installs.
Publishing the tap (maintainer side)
1. One tag per release, with a release asset
The formula pins a stable URL plus a SHA-256, so it needs an immutable tarball.
Do not point it at Forgejo's /archive/v$VERSION.tar.gz URL: those archives
are generated on demand and are not guaranteed byte-stable. Attach a tarball to
the release instead (Forgejo serves it at /releases/download/<tag>/<file>):
VERSION=$(uv run python -c 'import beefy_player; print(beefy_player.__version__)')
git archive --format=tar.gz --prefix="beefy-player-$VERSION/" \
-o "beefy-player-$VERSION.tar.gz" "v$VERSION"
sha256sum "beefy-player-$VERSION.tar.gz"
Create the tag on the mirror (git push tildeforge "v$VERSION"), upload the
tarball to the v$VERSION release, then paste the URL and checksum into
Formula/b/beefy-player.rb.
2. Resolve the Python resources
Every Python dependency (and its recursive dependencies) that is not provided by
another formula must be declared as a resource so Homebrew installs with
dependency resolution disabled. Never write these by hand:
brew tap beefcarver/tap /path/to/homebrew-tap # local clone, or the URL
brew update-python-resources --print-only beefcarver/tap/beefy-player
brew update-python-resources beefcarver/tap/beefy-player
pypi_packages exclude_packages: "numpy,pillow" keeps the two native builds out
of the resource list — they come from the numpy/pillow formulae, which ship
bottles, and the virtualenv picks them up through system site-packages.
extra_packages: "dbus-next" makes sure the Linux-only dependency is recorded
even though the resolver runs on macOS.
In a third-party tap, --ignore-errors records anything that cannot be resolved
and leaves a RESOURCE-ERROR comment; the official taps do not allow that, a
personal one does.
3. Build, test and audit locally
brew install --build-from-source beefcarver/tap/beefy-player
brew test beefcarver/tap/beefy-player
brew audit --strict beefcarver/tap/beefy-player
brew style beefcarver/tap/beefy-player
The formula's test do block runs --version and --offline --list, so it
needs no network and no audio device.
4. Push
git add Formula/b/beefy-player.rb && git commit -m 'beefy-player 1.2.2' && git push
Version bumps
For each release: tag, upload the tarball, update url/sha256, rerun
brew update-python-resources (only needed when the dependency set or pins
changed), install from source, test, push. brew bump-formula-pr only works
against GitHub-hosted taps, so on Forgejo the bump is a sed plus a re-test.
Optional livecheck support, so brew livecheck --tap beefcarver/tap can spot
new tags:
livecheck do
url "https://tildeforge.dev/beefcarver/beefy-player/tags"
regex(/^v?(\d+(?:\.\d+)+)$/i)
end
Bottles (optional)
Without a bottle do block users build from source — for this app that means
filling a virtualenv with pure-Python resources while numpy, pillow, mpv
and ffmpeg arrive as bottles, so it is quick. Prebuilt bottles need Homebrew's
GitHub Actions workflows, which cannot run on Forgejo; skip them unless the tap
is also mirrored to GitHub.
Why a tap and not homebrew-core
homebrew-core requires a tagged, immutable source URL and enough notability to be accepted at all (roughly 75+ stars / 30+ forks, or coverage that makes a project notable). A tap has none of those constraints, which is why upstream taps are the normal route for a project this size. The formula here follows core's conventions, so it could be submitted there later unchanged if the project qualifies.