Files

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.