Motivation Link to heading
My motivation behind this post is to learn more about Golang’s build and release process. I found this nifty tool called goreleaser that handles building binaries and artifacts for various OS and Architectures. Building for different OS and architectures is needed nowadays since developers usually work cross-platform. This post is about a project walkthrough where I used goreleaser
to build and release a version of a tool called pipeline
for Darwin and Linux platforms.
Project Link to heading
pipeline
is a simple CLI tool that draws inspiration from a pipe operator in Linux to execute various commands sequentially. With pipeline
, Definitions of commands are defined through configuration to be completed in order and repeated for N
of repetitions. For example,
actions:
- data: ""
cmd: cat data.json
repeat: 3
- data: ""
cmd: ls
repeat: 1
The codebase is here if you want to learn more aboutpipeline
. The tool is simple, but I will extend it to monitor processes and create dependencies amongst processes to create a simple local workflow/pipeline.
The main focus of this post is not the pipeline
tool, but it is a goreleaser
! Here is an example config on creating an archive in Github for Darwin and Linux OS for arm64 and amd64 architecture.
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
# The lines below are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/need to use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
version: 1
before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
# you may remove this if you don't need go generate
- go generate ./...
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64
archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}_{{ .Version }}
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
Declarative right! I couldn’t believe it either!

Release process Link to heading
The release process is straightforward for using goreleaser
for you own personal cli tool
- Install
goreleaser
with go toolchaingo install github.com/goreleaser/goreleaser@v1.24.0
- Create an inital
.goreleaser.yaml
in your cli repo withgoreleaser init
- See what goreleaser provides as options
goreleaser release -h
- Test out goreleaser to create archives in
dist
foldergoreleaser release --snapshot --clean
- You can run the binary that matches your os and arch and inspect what will be included in your changelog
- Setup github credentials
export GITHUB_TOKEN="YOUR_GH_TOKEN"
- Create your first tag
git tag -a v0.1.0 -m "First release" && git push origin v0.1.0
- Create a release
goreleaser release --clean
Learnings Link to heading
Golang provides tooling in its toolchain for building binaries. You can generate scripts to handle the release and release note process. My main question is, why should I replicate this from scratch if there are outstanding developers who maintain this tool to reduce my focus on building and releasing so that my focus is strictly on building business logic? I will continue my journey to see how I can publish packages to Krew or Artifactory in the future. That is a topic for another day.