GitHub Actions and the macOS Release
I’m using Goreleaser to build releases of Audax tools, since it works quite well in cross-compiling a Go program to various OS targets in a single run. I use this in a GitHub actions. Whenever I create a tag, the release pipeline will kick-off a run of Goreleaser, which will cross-compile Dynamo-Browse, package it, and publishing it to GitHub itself.
Recently, I found a bug in the MacOS Brew release of Dynamo-Browse. When the user tries to press c to copy the current item, the entire program will crash with a panic. I tracked the cause to the clipboard package that I’m using. Apparently, it requires Cgo to be usable on Darwin, and it will panic if CGO is not enabled1. But the GitHub action I was using was an Ubuntu runner. And since the package required some symbols from Foundation, which was only available on Darwin, I couldn’t just enable CGO.
However, I did learn that GitHub Actions actually supports MacOS runners. I don’t know why I didn’t think they wouldn’t. I guess, much like most of my experience with anything Apple, it would come at some sort of price. So you can imagine my delight in learning about this. And the first thing I did was try to use them in the release pipeline.
I first tried blindly switching from ubuntu-latest
to macos
. Sadly, it didn’t work as expected. It Turns out that the macos
runners do not have Docker installed, which broke a number of the actions I was using. And since the original ubuntu-latest
runner worked well for the Linux and Windows releases, I didn’t want to just junk them.
So what I did was split the release pipeline into three separate jobs:
- The first, running on
ubuntu-latest
, builds Audax tools and runs the tests to verify that the code is in working order. - The second, also running on
ubuntu-latest
, will invoke the Goreleaser action to build the Windows & Linux targets. - At the same time, the third, running on
macos
, will install Goreleaser viabrew
and run it to build the MacOS target.
The resulting pipeline looks a little like this:
name: release
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
services:
# localstack Docker image
steps:
# Checkout, build test
release-linux:
needs: build
runs-on: ubuntu-latest
steps:
# Checkout
- name: Release
uses: goreleaser/goreleaser-action@v1
if: startsWith(github.ref, 'refs/tags/')
with:
version: latest
args: release -f linux.goreleaser.yml --skip-validate --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
release-macos:
needs: build
runs-on: macos-12
steps:
# Checkout
- name: Setup Goreleaser
run: |
# Can't use goreleaser/goreleaser-action as that requires Docker
# So need to launch it and run it using the shell.
brew install goreleaser/tap/goreleaser
brew install goreleaser
- name: Release
if: startsWith(github.ref, 'refs/tags/')
run: |
goreleaser release -f macos.goreleaser.yml --skip-validate --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
I’ve only used this to make a small maintenance release that fixes the clipboard panic problem, and so far it seems to work quite well.
After doing this, I also learnt that there’s actually a Goreleaser Docker image which could theoretically be used to cross-compile with CGO. I haven’t tried it, and honestly it sounds like too much trouble than it’s worth. Rather keep things simple.
-
This is where I complain that the function that is panicing actually returns an
error
type. Instead of panacing and bringing down the whole program, why not just return an error? ↩︎