Please purchase the course to watch this video.

Full Course
Go Releaser is a powerful tool that streamlines the process of packaging and distributing applications, not only for Go but also for languages like Rust, TypeScript, Zig, and Python. By automating the build, archive, and release steps, Go Releaser enables developers to easily generate and publish multi-platform binaries and assets to platforms like GitHub, saving significant time and effort compared to manual release workflows. Its sensible default configurations—such as build hooks, OS/architecture targeting, automated changelogs, and checksum generation—can be customized for diverse needs, while its compatibility with package managers and support for different operating systems ensure flexibility. For developers looking to share their CLI tools or applications efficiently, Go Releaser offers a robust, user-friendly solution capable of handling advanced use cases like Linux package creation and Docker image distribution.
No links available for this lesson.
At this point your CMS application should be starting to look almost complete and you may want to be able to figure out how to distribute it to other people such as your friends, families or other people who may be interested in managing your data sets. We've already briefly covered how we can actually release Go applications to the wild. However in this lesson we're going to take a look at a fantastic third-party package called GoReleaser which handles the complexities of releasing so you can focus on building.
GoReleaser is a simple tool to allow you to configure your releases and then simply release by running the GoReleaser command and it doesn't just support Go. It also supports Rust, TypeScript, Zig and Python. In this lesson we're going to make use of it in order to set it up and show how we can release it publishing our packages to GitHub.
Getting Started with GoReleaser
So let's go ahead and get started by taking a look at the actual documentation. Here you can see there's some introduction into what GoReleaser is and I do recommend reading this if you're interested a little more. However we're going to go through kind of the install steps and show how it works so that you can use it when it comes to your own application.
As you can see there are a few different ways you can install this onto your system including steps for:
- Homebrew Tap
- Homebrew
- NPM
- Snapcraft
- Scoop
- Chocolatey
- etc etc etc
You'll also notice there's two different versions you can install. OSS which is the open source software version and the pro version. We're going to use the open source software version for this video because we don't want to pay for it in our case.
Installing GoReleaser
So I'm going to go ahead and install it using the Homebrew Tap because I'm currently running on macOS so I can go ahead and run it using the following brew install command:
brew install goreleaser/tap/goreleaser
After a while this should install however you'll want to use it for whichever operating system you're using. Nix packages is probably the best one to use in this case but for the meantime I'm just using it on macOS because this is the machine I'm currently recording on.
As you can see this is taking a bit of time mainly because I don't use Homebrew that often so there's a few things that are being installed and being upgraded as well. By the way if you're interested in why I'm using macOS currently I'm upgrading my main machine. I just installed the new AI chipboard into it and I need to go about actually reinstalling NixOS. So for the meantime because I'm trying to get this course completed by a deadline I'm making use of my macOS machine which pretty much works the same way at least for everything that we're doing in these final modules.
Okay now it should be installed and everything else and every other package on my system should be as well. Now we can go ahead and test it out by using the goreleaser
and let's say version
maybe unknown command version there we go:
goreleaser version
So this is the current version that I have installed with go version 1.2 etc etc. So yours should look similar to mine if you're doing it recently to mine or in the future it would look slightly different.
Initializing GoReleaser
Okay now with GoReleaser installed we can go about making use of it following the quick start guide of the website. Here you can see we can initialize our module using the go mod init
command we've already done all of this this isn't what we need to do. So let's scroll down to where the GoReleaser commands actually are.
In this case we just want to go ahead and initialize the command in order to create a .goreleaser.yaml
file which is where the GoReleaser configuration will live. So let's go ahead and do:
goreleaser init
And as you can see it's setting up our gitignore for us we've it's generated the .goreleaser.yaml
and we can go ahead and take a look at what's actually changed. We can actually do a git diff
in order to see this. As you can see "added by goreleaser" which is the dist/
directory this is very similar to the binary directory that we implemented or the build directory that we implemented in our own releaser and we have the .goreleaser.yaml
.
Understanding the Configuration
Which if we take a look at you can see has a number of sensible defaults as it says. Here you have some before hooks so go mod tidy
go generate
very good go hooks to use. In this case the go mod tidy
make sure that our packages are up to date or or that are specified inside of our actual code and the go generate
we took a look at that in the last lesson this will be used to generate any go generate directives that we've defined.
before:
hooks:
- go mod tidy
- go generate ./...
Next we then have the build block. This is the actual building itself. Here we're setting CGO_ENABLED
to be zero. In our case this is what we want because I'm using the modernc version of SQLite but if you're not using the modernc version you'll need to use CGO_ENABLED=1
and you'll have some other challenges to deal with. Then we're also specifying the go operating system so in this case linux windows darwin. Again this should be very similar to you based on what we already built when it came to our own go release tool:
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
Next we have the archives block. This is where it specifies all of the different archives that we want to build. Currently it's just a tar.gzip but for windows this will be just a zip file. You can see this has a name template so the template in this case is similar to what we built when it came to the name. It makes use of go template strings in order to determine this:
archives:
- name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}
So the template is going to be project name. Then it's going to be the operating system name. Then it does an if expression so if arch is amd64 we do x86_64. Otherwise it's if it's 32-bit i386. Otherwise we then just print out the architecture. If it's if the architecture is ARM then it does v and the version of ARM that it is. Pretty simple.
It then provides a changelog which is basically the changes that have taken place inside. In this case it's just going to take the git commits and actually sort them ascending then get rid of any kind of commits that have anything to do with documentation or to do with testing:
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
So this uses more of a common git formatting where you define kind of the type of commit at the beginning like "feat: added in new feature" let's say etc etc. Or say "chore: updated to use xyz". Something like that. You may want to get rid of the actual chores themselves. So in this case I could add in an exclusion to "chore:" if you use chores. I do use chores quite often and sometimes they're just more about like refactoring code or changing things around when it comes to git. So adding in the chore here or excluding the chore here may be a good thing to do.
Otherwise we then have the footer and they give a nice little tag "released by goreleaser". If you don't want this inside of your release notes you can go ahead and remove this.
In any case that takes a look at the .goreleaser.yaml
and the defaults are pretty sensible. You can go ahead and update them if you want.
Testing Locally
Now that we have this let's go ahead and run a local only release to see if it works. Which we can do by copying the following command:
goreleaser release --snapshot --clean
So let's go ahead and paste this in and see what happens. As you can see it starts to build all of the binaries and I believe it does so concurrently. It also archives them concurrently as well and if we take a look at our directory we should have a dist/
directory created. Which we do.
So let's go ahead and have a look at dist/
and you can see it has all of our CLI CMS being built as well as all of the artifacts as well. Which in this case it is the tar.gzip etc etc. And we have a metadata.json
and a config.yaml.json
. So pretty cool. A very simple way of being able to build all of the different versions for our application.
Publishing to GitHub
So now that we've managed to build this how do we actually go about publishing this to GitHub. Well in order to do so rather than using goreleaser
with the --snapshot
and the --clean
instead we would just go ahead and use goreleaser release
as follows. But in this case it also tells us that we need to specify either a GitHub token, a GitLab token or a Gitea token.
Setting Up GitHub Token
In order to achieve this you can go ahead and follow the documentation in order to obtain a GitHub token. You can see here we can create one by clicking this URL here which will take you into your secure mode for doing this. I'm not going to show this on stream but you would follow the instructions here in order to create a GitHub token.
In my case I already have a token defined which I can go ahead and export using:
export GITHUB_TOKEN=$(pass show tokens/github/goreleaser)
I believe. Wrong name. I've saved it as git releaser. That's incorrect.
Preparing for Release
Okay now that we have our git token added and our remote repo setup in order to release we're going to need to do a couple more things. The first of which is to commit our code. So let's go ahead and commit this:
git add .
git commit -m "added in goreleaser"
Next we then need to specify a tag for this code in order for it to have a semantic version. We can do this easily by using the git tag
command. So specifying a semver version of what we want this current release to be. In my case I'm going to go ahead and set it to be the v0.1.0
release because it's a little bit before my version one release just because I'm doing it for this video:
git tag -a v0.1.0 -m "initial beta release"
So let's go ahead and write a message for this tag and we'll call this "initial beta release" or something similar to that.
Now with the tag created which we can verify by using git tag
we can see this tag is here. Let's go ahead and push the tags up to the origin by using:
git push origin --tags
As you can see my new tag has been pushed to my GitHub repository.
Running the Release
Okay with both the git commit made and the tag pushed we can now go ahead and release this by using the GoReleaser command with the release sub command:
goreleaser release
As you can see it's now taking in my token and uploading it to my GitHub repository which was actually incredibly fast.
Viewing the Release
Now if I head on over to my GitHub repository at CLI CMS you can see I have a release that's just been created v0.1.0
which if we click in you can see has all of the assets that were built and defined as well as some checksums which is great. We took a look at checksums already throughout this course. As you can see this has created all of those checksums already for us which we can go ahead and verify if we want to. Very cool.
But not only this it's also added in the changelog of all of the different things that we went and built. "Added in goreleaser", "added in database" etc etc. And if I scroll down you can see it also has the footer of "release by goreleaser" added to it.
As you can see by using GoReleaser it really simplifies the ability to publish up releases of your code to GitHub without you needing to do it manually. GoReleaser is a really fantastic tool and I recommend using it when it comes to your own CLI CMS or even other CLI applications that you want to release to GitHub.
Advanced Features
Of course I also recommend reading the documentation as there are a number of other things you can actually use it for. For example if we go onto the documentation itself you can use it for more advanced use cases such as creating:
- Linux packages
- App bundles
- Docker images
- Snaps
- etc etc
So as some homework I recommend reading more about GoReleaser and what you can actually do with it. Specifically if you want to target Linux it's a really useful tool to be able to add this in so that you can support APKs, Debian images, RPMs or even Arch Linux as well.
Homework Assignment
In addition to reading the documentation to see how GoReleaser can be used in your own use case I also recommend implementing it when it comes to your own CLI CMS application.
Course Completion
With that we've then completed the CLI CMS course and looking at some popular third-party packages when it comes to Go. In the next module it's going to be slightly different than what we've done before in that it's going to focus on me building an entire application from scratch in a structured way. However I'm going to be making use of many of the tools that we learned in this lesson and showing you how I will use them when it comes to my own personal preferences in building out a full application.
So it's going to be a little bit of learning through osmosis, seeing how I do things and comparing it to your own workflow. Of course you don't have to build things like I build things but it's good to see how other people solve problems in order to kind of test your own assumptions and to see how you would solve them yourself.
In any case, I look forward to seeing you in that module.
No homework tasks for this lesson.