Using Homebrew for distributing Go apps (part 2)

2023-04-13

Go · Golang · Goreleaser · Homebrew · Ruby · Tech

1 minute

For personal reference:

This is a followup on a previous post that is a bit more manual. This is a little bit easier.

a) Create your own Homebrew tap

Create a new GitHub public repository with a prefix homebrew-, i.e. homebrew-tap. This will host all the apps that you want to distribute via your tap. Users will install your apps using the following commands:

# No need to include the 'homebrew-' prefix
$ brew tap flowerinthenight/tap
$ brew install <toolname>

# Or one-liner
$ brew install flowerinthenight/tap/<toolname>

b) Let’s use Github Actions to setup goreleaser

First, add a .goreleaser.yml config file to your Go repo. Here’s an example:

Copy
version: 2
builds:
- id: "kubepfm"
binary: kubepfm
goos:
- linux
- darwin
goarch:
- amd64
checksum:
name_template: 'checksums.txt'
dist: /tmp/kubepfm/dist
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
release:
github:
owner: flowerinthenight
name: kubepfm
brews:
- repository:
owner: flowerinthenight
name: homebrew-tap
name: kubepfm
homepage: "https://github.com/flowerinthenight/kubepfm"
description: "A simple port-forward wrapper tool for multiple pods/deployments/services."
directory: Formula
install: |
bin.install "kubepfm"
test: |
assert_match /A simple port-forward wrapper tool for multiple pods\/deployments\/services/, shell_output("#{bin}/kubepfm -h", 0)
view raw .goreleaser.yml delivered with ❤ by emgithub

The section of note here is the brews: part. You can check goreleaser’s Quickstart guide for more information.

Here’s an example of a GitHub Action config on how to setup goreleaser to do the release for our tags.

Copy
---
name: main
on:
push:
branches: [ master ]
tags: ['*']
pull_request:
branches: [ master ]
jobs:
codeberg:
name: Codeberg
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Mirror to Codeberg
uses: yesolutions/mirror-action@master
with:
REMOTE: "https://codeberg.org/flowerinthenight/kubepfm.git"
GIT_USERNAME: flowerinthenight
GIT_PASSWORD: ${{ secrets.GIT_PASSWORD }}
build:
name: Build
if: "!contains(github.event.commits[0].message, 'ci skip')"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Run tests
run: go test -v ./...
- name: Build binary
run: go build -v
- name: Run goreleaser
uses: goreleaser/goreleaser-action@v3
if: startsWith(github.ref, 'refs/tags/')
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}

See the name: Run goreleaser section. You need to add a personal access token with repo, workflow, write:packages permissions to your repository’s secrets. In this example, the name used is GH_PAT but you can use other names as well.

c) Do a tagged release

Tagged releases should now do a deployment to your tap.

$ git tag v1.0.0
$ git push --tags