With Azure Pipelines we can build applications with many different languages, one of which is Go.
If youβre using a Hosted Agent, which is the recommended way (since you donβt need to manage your own machines), you are at the mercy of what software is installed on the agent. But if youβre building an application to target a specific runtime, say Go 1.12.3 (the latest at the time of writing), you might be out of luck as the agent doesnβt have that installed on it.
So letβs take a look at how to setup Go as part of your pipeline.
Side note: You can also use Docker for your builds, but Docker isnβt for everyone, so Iβm focusing on non-containerised agents here. Docker can also be a challenge if you need several runtimes, to say, build a web application with Go + WASM support.
Weβre going to be modifying the standard Go Azure Pipeline, so start with that a template.
Setting up our variables
The first thing weβll want to do is modify the variables that Go will be expecting, specifically GOPATH
and GOROOT
. By default, these point to one of the versions of Go on the agent, but weβll modify them to use our version of Go.
variables:
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
GOBIN: '$(GOPATH)/bin' # Go binaries path
modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code
Weβll using one of the Agents pre-defined variables, Agent.BuildDirectory
, as itβs somewhere I know I can write to on the Agent, and itβs scoped to my build in particular.
The GOPATH
is going to be a new folder weβll create and GOROOT
will be where Go is unpacked to. These will now be environment variables so when Go eventually executes, itβll be the right version of Go.
Downloading Go
Next, weβll add a new step to download and unpack the version of Go we want to target:
steps:
- script: |
wget "https://storage.googleapis.com/golang/go1.12.3.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.3.tar.gz"
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.3.tar.gz"
displayName: 'Install Go 1.12'
Since we know my agent is a Linux agent (from the pool
defined in the template) weβll use wget
to download the Linux binaries and drop them into the Agent.BuildDirectory
. With that done we can unpack it with tar
, specifying that we want to unpack to Agent.BuildDirectory
, and given the structure of the tar.gz
contains a folder named go
weβll end up with a path that matches GOROOT
nicely.
Lastly, we need to ensure that the PATH
of the agent knows about this version of Go, and we do that by setting output variables:
- script: |
echo '##vso[task.prependpath]$(GOBIN)'
echo '##vso[task.prependpath]$(GOROOT)/bin'
This is covered in the Set up a Go workspace step in the docs guide.
Now the rest of the pipeline can follow exactly as the template describes!
Conclusion
Version pinning of dependencies is really important to ensure that we have repeatable builds over time. Since we donβt want to end up in a situation where we manually manage our agent pool we want our build definition to prepare the agent to the environment we desire, including setting up the appropriate runtimes.
You can see a full pipeline definition on my GitHub that utilises this approach.
You could also use this approach to prepare multiple different versions of Go to create a build matrix against several runtime releases, but Iβll leave that as an exercise to you, dear reader π.
Top comments (0)