Example repo using go-semantic-release, goreleaser, and GitHub Actions to create trunk-based continuous releases.

  • By Alex Howard
  • Last update: Mar 28, 2022
  • Comments: 0


Example of using go-semantic-release and goreleaser to create a continuously deployed GitHub Release of Go binaries and Docker images.


go-semantic-release Creates the GitHub Releases and correctly tags the commits based on the commit message.


goreleaser creates the binaries and Docker images. The binaries are amended to the GitHub Release and the Docker images are sent to the specified image repo (in this case GitHub Container Registry and Docker Hub).

Why both?

goreleaser will only trigger on the push of a git tag which it will not create itself. If there is not a tag on the commit it is running on it will run in "snapshot" mode to create a snapshot release. This allows for more flexibility on when releases happen.

For the purposes of this example, I wanted to create a release any time a new feature or fix hit the trunk to keep things simple. Thus, go-semantic-release will automatically create the tag on the commit and goreleaser creates the binaries. I could have used something more lightweight like svu(from the same developer as goreleaser!) but I opted for go-semantic-release because it have more flexibility in options and is the defacto standard for semantic releases.

goreleaser made the creation and upload of binaries and Docker images to multiple sources convenient and pretty trivial.


  • To start, I made a test repository to play around with the Actions and configuration. I then created this repo as a fresh baseline for the example.
  • Next, I created two GitHub Actions Secrets for the personal access tokens utilized to push the Docker images to the Docker Hub and GitHub Container Registry repositories.
GHCR_TOKEN=<github container registry pat>
DOCKERHUB_TOKEN=<docker hub pat>
  • I then initialized git with:
$ git init
$ git branch -m main
$ git remote add origin https://github.com/ahoward1024/go-release-example.git
$ git add -A
$ git commit -m "feat: initial commit"
$ git push --set-upstream origin main

This ran the .github/workflows/release.yaml workflow to create the initial release of v1.0.0.

  • Then, I added branch protection rules on the main branch to require linear history and pull requests before merging. Each subsequent feature and fix were created in pull requests to show the version being bumped.