Howdy again, hope you’re all going well. Let’s get right to it.


GoReleaser is already installed in the devcontainer environment for you, let’s check that it’s happy.

$ pwd
/workspaces/go-goreleaser-drone-example/crimp-city
$ goreleaser -h
GoReleaser is a release automation tool for Go projects.
Its goal is to simplify the build, release and publish steps while providing
variant customization options for all steps.

GoReleaser is built for CI tools, you only need to download and execute it
in your build script. Of course, you can also install it locally if you wish.

You can also customize your entire release process through a
single .goreleaser.yml file.

Usage:
  goreleaser [command]

Available Commands:
  build       Builds the current project
  check       Checks if configuration is valid
  completion  generate the autocompletion script for the specified shell
  help        Help about any command
  init        Generates a .goreleaser.yml file
  jsonschema  outputs goreleaser's JSON schema
  release     Releases the current project

Flags:
      --debug     Enable debug mode
  -h, --help      help for goreleaser
  -v, --version   version for goreleaser

Use "goreleaser [command] --help" for more information about a command.

Excellent, everything seems to be in order here. Let’s generate the default config.

$ goreleaser init
   • Generating .goreleaser.yml file
   • config created; please edit accordingly to your needs file=.goreleaser.yml

It should look something like the below, though I’ve made some small changes to make it only build for 64-bit linux hosts.

before:
  hooks:
    - go mod tidy
builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
    goarch:
      - amd64
archives:
  - replacements:
      linux: Linux
      amd64: x86_64
checksum:
  name_template: 'checksums.txt'
snapshot:
  name_template: "{{ incpatch .Version }}-next"
changelog:
  sort: asc
  filters:
    exclude:
      - '^docs:'
      - '^test:'

As usual, let’s test this works before moving on.

$ goreleaser release --snapshot --rm-dist
   • releasing...
   • loading config file       file=.goreleaser.yml
   • loading environment variables
   • getting and validating git state
      • ignoring errors because this is a snapshot error=git doesn't contain any tags. Either add a tag or use --snapshot
      • building...               commit=9dac672bfae18f00162a9c96a6bc87197c652d4b latest tag=v0.0.0
      • pipe skipped              error=disabled during snapshot mode
   • parsing tag
   • running before hooks
      • running                   hook=go mod tidy
   • setting defaults
      • snapshotting
      • github/gitlab/gitea releases
      • project name
      • loading go mod information
      • building binaries
      • universal binaries
      • creating source archive
      • archives
      • linux packages
      • snapcraft packages
      • calculating checksums
      • signing artifacts
      • signing docker images
      • docker images
      • docker manifests
      • artifactory
      • blobs
      • homebrew tap formula
      • gofish fish food cookbook
      • scoop manifests
      • discord
      • reddit
      • slack
      • teams
      • twitter
      • smtp
      • mattermost
      • milestones
      • telegram
   • snapshotting
      • building snapshot...      version=0.0.1-next
   • checking ./dist
      • --rm-dist is set, cleaning it up
   • loading go mod information
   • writing effective config file
      • writing                   config=dist/config.yaml
   • building binaries
      • building                  binary=/workspaces/go-goreleaser-drone-example/crimp-city/dist/crimp-city_linux_amd64/crimp-city
   • archives
      • creating                  archive=dist/crimp-city_0.0.1-next_Linux_x86_64.tar.gz
   • calculating checksums
      • checksumming              file=crimp-city_0.0.1-next_Linux_x86_64.tar.gz
   • release succeeded after 0.29s

Okay, good, and what about the binary that it actually produced?

$ ./dist/crimp-city_linux_amd64/crimp-city

█░█ █▀▀ █░░ █░░ █▀█   █░█░█ █▀█ █▀█ █░░ █▀▄
█▀█ ██▄ █▄▄ █▄▄ █▄█   ▀▄▀▄▀ █▄█ █▀▄ █▄▄ █▄▀ version 0.0.1-next

Nice! But what’s this? The version has changed from dev to 0.0.1-next. Why? Well, Go lets you pass in variables at build time, and GoReleaser has some defaults that it will pass in.

# Custom ldflags templates.
# Default is `-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser`.

Normally GoReleaser will do some magic with the most recent git tag for the version, but we don’t currently have a tag, so it supplies 0.0.1-next for us.

So, we have a Go program and a local working GoReleaser config. Let’s make things official and actually make a release in Gitea. We’ll need to create an API token for GoReleaser to use, and tell GoReleaser how to reach Gitea.

GoReleaser requires an API token to deploy the artifacts to Gitea. You can create one in Settings | Applications | Generate New Token page of your Gitea instance.

This token should be added to the environment variables as GITEA_TOKEN.

Set the token you just created.

export GITEA_TOKEN=<your-token-here>

Update the .goreleaser.yml configuration.

Now, I think there’s a bug in the current version of GoReleaser. I’ve raised an issue for it, but basically, the release block included below shouldn’t be necessary. If you’re following along, try without it and if you get a 404 error, add it in.

I found a bug in GoReleaser, and it was fixed almost immediately! Awesome work. If you’re on v1.1.0 of GoReleaser, you can leave the commented part of the block below as is. If you’re on a lower version, you need to uncomment it. Or just upgrade. 🤷

gitea_urls:
  api: http://gitea:3000/api/v1/
  download: http://gitea:3000
# release:
#   gitea:
#     owner: gitea
#     name: crimp-city

Now commit the changes, tag the commit and push it to Gitea.

$ git add .goreleaser.yml
$ git commit -m "Update gitea goreleaser config"
[master 4836926] Update gitea goreleaser config
 1 file changed, 4 insertions(+)
$ git tag -a v0.1 -m "First release"
$ git push origin v0.1
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://gitea:3000/gitea/crimp-city.git
 * [new tag]         v0.1 -> v0.1
$ goreleaser release --rm-dist
   • releasing...
   • loading config file       file=.goreleaser.yml
   • loading environment variables
   • getting and validating git state
      • building...               commit=4836926dc37b8e8cac913f7f0e6f8ae5d2376c06 latest tag=v0.1
   • parsing tag
   • running before hooks
      • running                   hook=go mod tidy
   • setting defaults
      • snapshotting
      • scm releases
      • project name
      • loading go mod information
      • building binaries
      • universal binaries
      • creating source archive
      • archives
      • linux packages
      • snapcraft packages
      • calculating checksums
      • signing artifacts
      • signing docker images
      • docker images
      • docker manifests
      • artifactory
      • blobs
      • homebrew tap formula
      • krew plugin manifest
      • gofish fish food cookbook
      • scoop manifests
      • discord
      • reddit
      • slack
      • teams
      • twitter
      • smtp
      • mattermost
      • milestones
      • linkedin
      • telegram
   • checking ./dist
      • --rm-dist is set, cleaning it up
   • loading go mod information
   • writing effective config file
      • writing                   config=dist/config.yaml
   • generating changelog
      • writing                   changelog=dist/CHANGELOG.md
   • building binaries
      • building                  binary=/workspaces/go-goreleaser-drone-example/crimp-city/dist/crimp-city_linux_amd64/crimp-city
   • archives
      • creating                  archive=dist/crimp-city_0.1_Linux_x86_64.tar.gz
   • calculating checksums
      • checksumming              file=crimp-city_0.1_Linux_x86_64.tar.gz
   • publishing
      • scm releases
         • creating or updating release repo= tag=v0.1
         • Gitea release created     id=3
         • uploading to release      file=dist/checksums.txt name=checksums.txt
         • uploading to release      file=dist/crimp-city_0.1_Linux_x86_64.tar.gz name=crimp-city_0.1_Linux_x86_64.tar.gz
   • announcing
   • release succeeded after 1.44s

Great success. If you go browse to the releases page for your repo1, you’ll see a new release, including:

  • a changelog of all the commits
  • zipped archives of the source code
  • a zipped copy of the crimp-city binary
  • a checksums.txt so that people can confirm their copy of the downloaded binary is legitimate.

How good is that? And you remember how we had the version embedded in the binary output? Yep, that’s using the git tag we set.

$ ./dist/crimp-city_linux_amd64/crimp-city

█░█ █▀▀ █░░ █░░ █▀█   █░█░█ █▀█ █▀█ █░░ █▀▄
█▀█ ██▄ █▄▄ █▄▄ █▄█   ▀▄▀▄▀ █▄█ █▀▄ █▄▄ █▄▀ version 0.1

Nice. Alright, that’s all for now. Next time we’ll get Drone CI to automatically create a release for us when we push a tag to Gitea.


  1. Something like http://gitea:3000/gitea/crimp-city/releases ↩︎