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

  1. Install goreleaser with go toolchain go install github.com/goreleaser/goreleaser@v1.24.0
  2. Create an inital .goreleaser.yamlin your cli repo with goreleaser init
  3. See what goreleaser provides as options goreleaser release -h
  4. Test out goreleaser to create archives in dist folder goreleaser release --snapshot --clean
    1. You can run the binary that matches your os and arch and inspect what will be included in your changelog
  5. Setup github credentials export GITHUB_TOKEN="YOUR_GH_TOKEN"
  6. Create your first tag git tag -a v0.1.0 -m "First release" && git push origin v0.1.0
  7. 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.