Help us shape the future of Go! Take the 2026 Go Developer Survey

gobottle

command module
v0.8.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2026 License: MIT Imports: 4 Imported by: 0

README

gobottle

Status: experimental. Interfaces and behavior change without notice.

gobottle is ko for Homebrew: it cross-compiles Go binaries, packages them as real Homebrew bottles, publishes them to GHCR using the same OCI conventions as homebrew-core, and generates the tap formula — all in pure Go, from any platform, with no Ruby, no skopeo, and no per-OS build runners.

Nothing else in the ecosystem does this: goreleaser generates formulae (now casks) that build from source or download release tarballs; official bottles require brew bottle + brew pr-upload running natively on every target platform. Static Go binaries (CGO_ENABLED=0) don't need any of that — one machine can bottle for every platform Homebrew supports.

Pipeline

gobottle build   -o json > bottles.json   # cross-compile + package bottles
gobottle push    -o json < bottles.json   # publish OCI index + blobs to GHCR
gobottle release -i bottles.json          # generate formula, commit to tap

Each verb emits machine-readable JSON on stdout (progress on stderr), so the stages compose in CI; gobottle release without -i runs the whole pipeline in one shot.

Configuration lives in .gobottle.yaml (see gobottle init); the formula is fully generated — description, license, dependencies, caveats, completions, test block and more are driven from the formula: section of the config, with a Go-template escape hatch for anything not yet modeled.

The generated formula also builds from source: its def install emits depends_on "go" => :build and system "go", "build", *std_go_args(...) with the ldflags, tags and flags inherited from source.build, so brew install --build-from-source and brew install --HEAD compile correctly while everyone else gets a poured bottle. Override it under formula.build, or set formula.build.enabled: false for the older bottle-only install block (the head stanza is then omitted, since a bin.install block cannot build a git checkout). gobottle init imports the build recipe from an existing goreleaser config so the source build reproduces the released binaries.

Recovering a failed release

gobottle release is idempotent: bottles already in the registry are re-pushed unchanged and an up-to-date formula is not committed again, so a release that failed part-way (say, a GitHub 5xx on the tap commit) is simply re-run. Keep bottles.json as a workflow artifact and the formula step alone can be replayed without rebuilding:

gh run download <run-id> -n bottles-manifest-v1.2.3
GOBOTTLE_TAP_TOKEN=... gobottle release -i bottles.json

Installation

brew trust isometry/tap               # Homebrew ≥6: one-time tap trust
brew install isometry/tap/gobottle    # poured as a bottle, naturally
go install github.com/isometry/gobottle@latest

In GitHub Actions, use isometry/gobottle-setup to install from verified release binaries.

Requirements

  • Go toolchain (for --source=go builds)
  • A GitHub token with write:packages (GHCR) and contents: write (tap)
  • After the first push, flip the GHCR package visibility to public so brew's anonymous pulls work

Claude Code plugin

This repository doubles as a Claude Code plugin providing a gobottle skill (usage, configuration reference, and a goreleaser-migration guide):

/plugin marketplace add isometry/gobottle
/plugin install gobottle@gobottle

License

MIT — see LICENSE.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
git
Package git provides git repository operations using go-git.
Package git provides git repository operations using go-git.
oci
Package oci publishes Homebrew bottles to an OCI registry using the exact conventions brew expects when pouring from GHCR (Homebrew's github_packages.rb is the reference implementation):
Package oci publishes Homebrew bottles to an OCI registry using the exact conventions brew expects when pouring from GHCR (Homebrew's github_packages.rb is the reference implementation):
tap

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL