🚀 GitHub Action for release your Go projects as fast and easily as possible
Tags: tutorial, go, github, beginners
Published: 2020-06-21 21:06:47

## Introduction

Hello, DEV World! 😉 Continuing the series of articles on automating routine using the excellent CI/CD tool — GitHub Actions.

It's time to automate the releases of your applications written on Go!

<a name="toc"></a>
### 📝 Table of contents

- [What will we automate?](#ch-1)
  - [Repository structure](#ch-1-1)
- [Configure GitHub Action](#ch-2)
- [Troubleshooting](#ch-3)
- [Time to release!](#ch-4)
  - [Real-life example](#ch-4-1)
- [Questions for better understanding](#ch-5)
- [Exercises for independent execution](#ch-6)

<a name="ch-1"></a>
## 🤔 What will we automate?

If you've ever faced the challenge of releasing a project written on Go for different platforms/OS, you already know _what kind of problems_ you may come across. If not, I will bring some of them:

- You need to constantly monitor the features of each OS (for example, specific slashes in the paths).
- You need to create archives manually and upload them to the release page on GitHub.
- You need to look at all the commits to make `CHANGELOG` for a new version.
- ...and many more!

So, what if I told you that there is a tool that will allow you to do all this (and more) automatically after creating a tag in your repository? 

I'm not kidding, it allows you to do all this with `GoReleaser` GitHub action 👇

{% github goreleaser/goreleaser-action %}

[↑ Table of contents](#toc)

<a name="ch-1-1"></a>
### 👀 Repository structure

For a short, project will be contain very simple function:

```go
package main

import "fmt"

func main() {
    fmt.Println("Hi, DEV World! 😉")
}
```

And the repository structure will be as simple as that: 

```bash
.
├── .github
│   └── workflows
│       └── release_build.yml  # <-- GitHub Action
└── main.go                    # <-- main function
```

[↑ Table of contents](#toc)

<a name="ch-2"></a>
## 🤖 Configure GitHub Action

Let's move on to the main character of our story. Look at the listing of the file `release_build.yml`, which already has a lot of familiar elements (_if you did read my previous articles about GitHub Action_ 😏):

```yml
name: Release Go project

on:
  push:
    tags:
      - "*" # triggers only if push new tag version, like `0.8.4` or else

jobs:
  build:
    name: GoReleaser build
    runs-on: ubuntu-latest

    steps:
      - name: Check out code into the Go module directory
        uses: actions/checkout@v2
        with:
          fetch-depth: 0 # See: https://goreleaser.com/ci/actions/

      - name: Set up Go 1.14
        uses: actions/setup-go@v2
        with:
          go-version: 1.14
        id: go

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@master
        with:
          version: latest
          args: release --rm-dist
        env:
          GITHUB_TOKEN: ${{ secrets.GO_RELEASER_GITHUB_TOKEN }}
```

Yes, GitHub automatically creates a `GITHUB_TOKEN` secret to use in your workflow, but I recommend to create your own token with `repo` scopes [here](https://github.com/settings/tokens/new):

![GITHUB_TOKEN](https://dev-to-uploads.s3.amazonaws.com/i/svfqkkqm1sy7eyvwfuay.png)

And now, create new GitHub secret (`GO_RELEASER_GITHUB_TOKEN` in my case):

![GitHub secret](https://dev-to-uploads.s3.amazonaws.com/i/ea5ofg93viernr9zrggl.png)

[↑ Table of contents](#toc)

<a name="ch-3"></a>
## ✅ Troubleshooting

If your file with `main()` function is not in the root directory of your repository, **GoReleaser** will generate an error. Therefore, you will need to specify the correct directory in the step settings, for example like this:

```yml
# ...

    steps:

      # ...

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@master
        with:
          version: latest
          args: release --rm-dist
          workdir: ./cmd/myapp # <-- path to directory with main() func
        env:
          GITHUB_TOKEN: ${{ secrets.GO_RELEASER_GITHUB_TOKEN }}
```

[↑ Table of contents](#toc)

<a name="ch-4"></a>
## 🚀 Time to release!

Create new release with tag (in my case, it's `0.8.4`) and go to Actions page in order to follow up on the job:

![go releaser job](https://dev-to-uploads.s3.amazonaws.com/i/477676wndnd30qr9fjts.png)

After successfully completing the job, go to release page to see awesome result: `CHANGELOG` with all of your commits (_between two versions_), `checksums.txt` file and uploaded archives with compiled apps for all platforms!

![release page](https://dev-to-uploads.s3.amazonaws.com/i/nicshg5vdx7evrbdtwnm.png)

That's it! Just like that! 🎉

[↑ Table of contents](#toc)

<a name="ch-4-1"></a>
### 🎯 Real-life example

If the screenshots above are not enough, I invite you to look at the one of my projects, where I use `GoReleaser` action in real-life:

{% github create-go-app/cli %}

[↑ Table of contents](#toc)

<a name="ch-5"></a>
## 💬 Questions for better understanding

1. Which parameter in the GitHub Actions config is triggering job?
2. Why we need to define `fetch-depth: 0` for `actions/checkout` action?
3. What does the `-rm-dist` argument mean in `Run GoReleaser` step?

[↑ Table of contents](#toc)

<a name="ch-6"></a>
## ✏️ Exercises for independent execution

- Repeat everything you have seen in the article, but with your own Golang project. _Please, write about your result & link to your shorter website in the comments below!_
- Change the triggering value so that it only works for major versions. _Please, read more about software versioning [here](https://semver.org/)._

[↑ Table of contents](#toc)

<a name=""></a>
## Photos/Images by

- GoReleaser Action repository & website (links: [1](https://github.com/goreleaser/goreleaser-action), [2](https://goreleaser.com/))
- GitHub repository settings ([link](https://github.com))

<a name=""></a>
## P.S.

If you want more articles (like this) on this blog, then post a comment below and subscribe to me. Thanks! 😻

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My projects that need your help (and stars) 👇

- 🔥 [gowebly][gowebly_url]: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
- ✨ [create-go-app][cgapp_url]: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
- 🏃 [yatr][yatr_url]: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
- 📚 [gosl][gosl_url]: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
- 🏄‍♂️ [csv2api][csv2api_url]: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
- 🚴 [json2csv][json2csv_url]: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

<!-- Footer links -->

[gowebly_url]: https://github.com/gowebly
[cgapp_url]: https://github.com/create-go-app
[yatr_url]: https://github.com/koddr/yatr
[gosl_url]: https://github.com/koddr/gosl
[csv2api_url]: https://github.com/koddr/csv2api
[json2csv_url]: https://github.com/koddr/json2csv