As we have seen in Learning Go by examples: part 8 - Automatically cross-compile & release your Go app article, we can create an app and cross-compile automatically. It's cool but I think we can go more deeper.
It's cool to create awesome tools but it's better to provide a way to install them easily.
What do you think if Mac users can install and update our app through HomeBrew?
In this article, you will learn how to allows users to install your apps, hosted in a GitHub repository, through HomeBrew, starting from my GopherSay application.
HomeBrew
Homebrew is the missing package manager for macOS. It installs packages with a simple command like brew install curl
. Homebrew taps are third-party repositories. By creating a Homebrew tap formula, users can install and use your repository.
Taps are external sources of Homebrew formula, casks and/or external commands. They can be created by anyone to provide their own formula, casks and/or external commands to any Homebrew user.
For example, if you want to install curl app through HomeBrew, you just need to enter the following command:
$ brew install curl
Curl app is on the core HomeBrew tap so HomeBrew found the tap and install the tool in your computer.
If you want to install a tool that is in a private tap, you need to add it and then install the tool.
For example:
$ brew tap go-task/tap
$ brew install go-task
Or you can directly install the tool in a private tap in only one line:
$ brew install go-task/tap/go-task
Create a GitHub repository for our HomeBrew Tap
A Tap is usually a Git repository. If hosted on GitHub, it is recommended that the repository’s name start with homebrew- in order to use brew tap
command.
For example:
scraly/homebrew-tools
repository => brew tap scraly/tools
command
Note: even if we want to install only our GopherSay app in this tutorial, we will not name our repository homebrew-gophersay instead of that we will create a repository that will contains many of different formulas.
First, create our new repository in GitHub: homebrew-tools.
For that, I logged in GitHub website, clicked on the repositories link, click on "New" green button and then I created a new repository called homebrew-tools
.
Our new GitHub repository is created:
homebrew-tools
Homebrew formula for installing Scraly's apps & tools.
How To Use
Add repository:
brew tap scraly/tools
Install GopherSay:
brew install gophersay
Upgrade the GopherSay CLI to the latest version:
brew upgrade gophersay
Generate automatically HomeBrew Tap Formula through GoReleaser
In the previous article, we created GopherSay golang app, we generated the releases thanks to Go Releaser and we automatized them through GitHub actions.
Everytime we publish a new GitHub release in GopherSay, the GitHub action is runned and our release is created.
It's perfect.
So now we need to ask GoReleaser to generate also a HomeBrew tap formula :).
In order to do that automatically, we need to edit our goreleaser.yml
file.
If you don't already clone the repository, you need to clone it and go into the gophersay folder:
$ git clone https://github.com/scraly/gophersay.git
$ cd gophersay
Now, add the following step in .goreleaser.yml
file:
brews:
- name: gophersay
homepage: https://github.com/scraly/homebrew-tools
tap:
owner: scraly
name: homebrew-tools
Let's explain this code block:
- The brews section specifies how the formula should be created.
- homepage is for your app's homepage
- tap is for defining the GitHub/GitLab repository to push the formula to
Warning: the name of the brew will be the name of the formula, so what you want to install with brew install <name>
command.
Generate our formula!
In order to generate the HomeBrew formula automatically, we need to create a new tag in our Git repository and push it. This will create a new release in the GitHub repository.
Let's create and push v1.0.2 tag:
$ git tag v1.0.2
$ git push origin v1.0.2
Check if the new tag have been correctly added, go to GopherSay Releases page.
Fine, release v1.0.2 exists.
Now, go in Actions tab in the GitHub repository in order to check if GitHub action runned:
Everything is green, it's a good sign! 🙂
Let's check if our formula have been added
Go in our HomeBrew Tap repository.
The GopherSay formula have been automatically updated:
Let's have a look to our gophersay.rb
formula file:
# typed: false
# frozen_string_literal: true
# This file was generated by GoReleaser. DO NOT EDIT.
class Gophersay < Formula
desc ""
homepage "https://github.com/scraly/homebrew-tools"
version "1.0.2"
on_macos do
if Hardware::CPU.intel?
url "https://github.com/scraly/gophersay/releases/download/v1.0.2/gophersay_1.0.2_Darwin_x86_64.tar.gz"
sha256 "084b60f89b442cc66159a495421d3e9fb48b3861b324a2ac1062d4491c342f27"
def install
bin.install "gophersay"
end
end
if Hardware::CPU.arm?
url "https://github.com/scraly/gophersay/releases/download/v1.0.2/gophersay_1.0.2_Darwin_arm64.tar.gz"
sha256 "0e98ff426817075492f3e61569c28d5bfd7a69ab7264f6cf03dd99e007277ae1"
def install
bin.install "gophersay"
end
end
end
on_linux do
if Hardware::CPU.intel?
url "https://github.com/scraly/gophersay/releases/download/v1.0.2/gophersay_1.0.2_Linux_x86_64.tar.gz"
sha256 "bd3af60d4e9f5deb63dfd675cc5c2aa515d4897fb056b3170d316d9a9e466998"
def install
bin.install "gophersay"
end
end
if Hardware::CPU.arm? && Hardware::CPU.is_64_bit?
url "https://github.com/scraly/gophersay/releases/download/v1.0.2/gophersay_1.0.2_Linux_arm64.tar.gz"
sha256 "b8e8113b90efcd8dce4a38d648000cd5f1d8830bba039a585ca2d5067eb17740"
def install
bin.install "gophersay"
end
end
end
end
GoReleaser create and update this formula every time you will push a new tag is your app with release information like: version, executable binary archive depending on the OS, sha256...
Install our app through HomeBrew
Now your HomeBrew tap is ready and the formula is created, so we can install our app.
Add our tap:
$ brew tap scraly/tools
==> Tapping scraly/tools
Cloning into '/usr/local/Homebrew/Library/Taps/scraly/homebrew-tools'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 9 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), done.
Tapped 1 formula (13 files, 7.7KB).
Install our app:
$ brew install gophersay
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (scraly/tools).
==> New Formulae
scraly/tools/gophersay
==> Installing gophersay from scraly/tools
==> Downloading https://github.com/scraly/gophersay/releases/download/v1.0.1/gophersay_1.0.1_Darwin_x86_64.tar.gz
==> Downloading from https://github-releases.githubusercontent.com/398637863/968c588e-71e2-4300-b62a-33aa9b245ada?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20210830%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210830T100137
######################################################################## 100.0%
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/gophersay
Target /usr/local/bin/gophersay
already exists. You may want to remove it:
rm '/usr/local/bin/gophersay'
To force the link and overwrite all conflicting files:
brew link --overwrite gophersay
To list all files that would be deleted:
brew link --overwrite --dry-run gophersay
Possible conflicting files are:
/usr/local/bin/gophersay
==> Summary
🍺 /usr/local/Cellar/gophersay/1.0.1: 5 files, 1.5MB, built in 8 seconds
Or you can directly install the app in oneline installation command:
$ brew install scraly/tools/gophersay
Test our app
Run the following command:
$ gophersay test
----
< test >
----
\
\
(%%. .
@***,*********@ &****************& .&%(********%#
,(((((((@*******@ .*************///***********# @****(#((((((((((@
&(((((((((@*****@***********************************((((((((((,
.((((((((((%((((((((&****************************((((((((((@
&((((((((@. .@#((@***************************@((((((@
/@(@ @@@ (*************************&(((/(((((%
@ @@ /************************ @
(** /************************& (@@@ *
/*****% @**************************@ @
,*******************************************& ,
***************************************************
@***********************((((((((&*******************
*************************((((((&((&*****************&
***********************((((((((((((%****************
(****.......@......#***&((((((#((((%***..........@**,@,
****,/ .......#.......,******, ( ******.. ....@..*******@
@*@.... @.....#..(.....#*****@@@@/(*****..(...../...&. ****&
............ ......../************&.........&..&*, (((#
..............@........@********/.......... ..... &(((
...............%........&**#............/......( %((.
*..................,.......#...........#.......@ .((((
*....................(.......%.....#..........( (((((
......................@........%............. #((((
.......................&......@............( ((((
........................@................* #(((
/....................... ......(.......% #(((
(.......................,.....#....****@ (#((
.******.@.................,.....@* ****/ &((((/
/****. ##.
Awesome!
Upgrade our app
Through HomeBrew, you can now upgrade our GopherSay application to the latest version:
$ brew upgrade gophersay
Conclusion
As you have seen in this article and previous articles, it's possible to create multiple different applications in Go, and automatize build and cross-compilation and even provides an easy way to install our app for Mac users.
All the code of our GopherSay app in Go is available in: https://github.com/scraly/gophersay
In the following articles we will create others kind/types of applications in Go.
Hope you'll like it.
Top comments (5)
Hi, many thanks for your great work!
I want to add one case not considered here:
Hi, Thanks for the series. While it works great for MacOS. I was wondering, how would i make the app available incase of ubuntu? anywhere anytime.
Hi,
You can build a go app for Linux platform so the binary file will works in a Ubuntu 🙂.
Hi @Aurélie Vache
What if the github.com/scraly/gophersay repo is private ?
Strange because on my side, the repo is public :)