The fanciest way of releasing Go binaries with GoReleaser 😎

developer-guy
Published in
6 min readOct 5, 2021

--

Written by Furkan Türkal developer-guy Erkan Zileli

The first thing that comes to our minds when we want to release our Go binaries is doing it with the help of the command "go get," and of course, there is nothing wrong with this approach. But even "go get" is a super-simple way of installing Go binaries, but not everyone has a Go compiler installed. Also, we want to distribute our binaries differently, like Docker images and Homebrew Formulas. Finally, we expect our binary to suit different OSs and architectures (Linux, Darwin, Windows, Arm, etc.). So, through a bit of research into the best way to distribute a Go binary according to our needs, I stumbled upon GoReleaser, and GoReleaser meets all of our needs at this point. Thanks to Carlos A. Becker 🙋🏻‍♂️

Release Go projects as fast and easily as possible!
https://goreleaser.com

With GoReleaser, you can:

  • 🙅🏻‍♂️ Cross-compile your Go project (Darwin, Linux, Windows) automatically
  • 🚀 Release your project to GitHub, GitLab, and Gitea
  • 📦 Build and Push Docker images, also supports multi-platform Docker images with Docker manifests
  • 💬 Announce new releases on Twitter, Slack, Discord and Microsoft Teams, and many more…

The best part of using GoReleaser is that it is easier to use, easier to integrate with your Go project, and has a wide range of features while building, releasing, announcing, etc., the software. In addition to that, it is well-documented. You can reach out to all of the options that you have from its official documentation.

GoReleaser is a trendy project, especially in the open-source world for Go projects. I see this project integrated with nearly every Go project in GitHub because GoReleaser has its GitHub Action, making it super easy to use with GitHub Action. But this is not limited to only GitHub Action, and you can integrate GoReleaser with various types of CI systems. There is a particular category for it in the official documentation, and you can reach out to available options from here to pick one that meets your needs.

This blog post is not a getting started guide for the GoReleaser project, but if you only want to make your hands dirty with this technology, of course, there is a better place to do this; please take a look at the official Quick Start page of the GoReleaser. But to get started with GoReleaser is just as easy as running the following command within your project directory:

$ goreleaser init
• Generating .goreleaser.yml file
• config created; please edit accordingly to your needs file=.goreleaser.yml
$ vim .goreleaser.yml # after editing save the changes
$ goreleaser check # check the sy
$ git tag -a v0.1.0 -m "My First Release"
$ export GITLAB_TOKEN=""
$ goreleaser release --rm-dist # test with --skip-publish --snapshot
and BOOM!🚀🚀

To install GoReleaser on your own machine please refer to the Installation page.

Then, start editing this file according to your needs, and while doing this, you can follow up on the documentation to learn other options that you have, that's all ✨

If we need to summarize this guide, we'll be talking about the following:

  1. But, first, how can we use GoReleaser as part of the CI/CD solution (GitLab, in this case)?
  2. How can we distribute our Go binaries for three types of OSs (Linux, Darwin, Windows) using GitLab Releases?
  3. How can we build and push container images to the GitLab Container Registry?

But, before diving deep into the details, let me introduce our brand new project called KinK (KinD in Kubernetes). We recently introduced this project and explained all the information in this blog post. We have used GoReleaser to distribute this project on both platforms GitLab and GitHub. Today, we will be trying to answer these three questions above based on our experiences with this project.

We started with creating the necessary sections within the .goreleaser.yml file. The first section that we started to work on is the builds section. The whole journey begins with this section. In the builds section, we have to define the OSs and architectures we want our binary to run on. So, we want our binary to run on Windows, Linux, and Darwin OSs for amd64 architecture.

https://gist.github.com/developer-guy/07f8227edfb026de56f2d2f4ea2c7228

🚨 Please let me tell you something that I faced with recently when I start to learn and implement GoReleaser for the first time in our project. When I start to implement it with my project, I did some research about the projects that are already using GoReleaser, so I copied some examples from there and tried to run it. The mistake that I did in the beginning is that I have used the same binary names for all the builds together with “no_unique_dist_dir: true” option. So, my Darwin build made Linux build obsolete at the end of the day because the names of the binaries are same. So, my recommendation is that please read all the documentations first in the GoReleaser website before diving into the implemention details so quick.

The following section is dockers. Since v0.31.0, GoReleaser supports building and pushing Docker images. So, be careful with the version of GoReleaser that you are using if you want to use this option. In this section, we specify the details of the image that we will build, such as the path of the Dockerfile, the template of the name of an image, which binary you want to put in the Docker image, etc.

https://gist.github.com/developer-guy/30b524339aff44a6c595047fe8a4c65a

But there is a convention in here; your Dockerfile has to be like the following:

https://gist.github.com/developer-guy/c71e1a82387ecf6f2d99d770a67a8b8d

That's all you need, nothing more than this!

The next step is defining the details of your GitLab because, in Trendyol, we are using self-hosted or enterprise GitLab. Still, GoReleaser is using official gitlab.com by default to upload release archives push docker images to the registry.

https://gist.github.com/developer-guy/12bd5d1ad53bc02ea6ebf124c382c25b

Yes, that's all you need to set up all the necessary steps to create releases in GitLab using GoReleaser. The whole .goreleaser.yml would become to the following:

https://gist.github.com/developer-guy/1accbae945e7216b2faa930f17980746

You might notice that we don't cover the other sections such as archives, gomod, changelog, etc. because the purpose of this post is to give you a quick overview of how you can start using GoReleaser in GitLab. As I mentioned above, you can find all the nitty details about these sections in GoReleaser's official documentation.

Last but least, we have to create .gitlab-ci.yml to define our jobs. The .gitlab-ci.yml file is a YAML file where you configure specific GitLab CI/CD instructions.

https://gist.github.com/developer-guy/d3056b6d29e1137e989deb012fe45dbe

🚨 Don’t make your GitLab variables protected if your branch is not protected because you can’t read your variables if they are protected and run on a non-protected branch.

You might also notice that we are using the make command here. Let me share the contents of the Makefile:

https://gist.github.com/developer-guy/c73e5f003193ba120438c15ad0a75cd8

If everything goes fine, you will end up with the following results:

Conclusion

As you can see, releasing the Go binary is pretty neat if you do it with GoReleaser. However, if you think of that you do it manually; you have to create your Go binary by using GOOS and GOARCH environment variables to make it suitable with the targeted operating system and architecture, then, of course, you have to upload your archives to the releases page of Gitlab. So, by using GoReleaser, we automate all of these manual processes.

Thanks for reading. I hope you enjoy this blog post; for the next blog posts, please stay tuned. 🙋‍♂

--

--

developer-guy
Trendyol Tech

🇹🇷KCD Turkey Organizer🎖Best Sigstore Evangelist🐦SSCS Twitter Community Admin✍️@chainguard_dev Fan📦Container Addict📅Organizer at @cloudnativetr•@devopstr