# 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) ```bash 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//`): ```bash 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: ```bash 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 ```bash 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 ```bash 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: ```ruby 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.