2019-08-29
If you are yet to adopt Go modules, you ought to have GOPATH set in Github Actions to have your builds succeed.
I already found a way how to set $GOPATH and in this article I demonstrate a slightly different approach.
But first a detour to understand the environment.
With the runs-on: ubuntu-latest
field you can set the runtime environment for the job. This will define the host VM the job will run in.
Github Actions provide a few ways to override the execution environment - or technically to start Docker containers inside this VM and perform steps in these Docker containers.
The most simple way to perform custom steps in Actions is to use the run
field. This will run shell commands in the host VM’s shell.
So this is not really an override of the execution environment, but more like the simplest way to use the default.
name: Go
on: [push]
jobs:
my-first-job:
name: My first job
runs-on: ubuntu-latest
steps:
- name: Hello
run: |
echo "Hello world"
echo "Yaml allows me to have multiline commands"
See the reference.
Github Actions - the product - is about the reusable building blocks, called actions.
Actions are Docker containers made to perform one specific task. They accept incoming parameters in the with
field, but don’t allow customized behavior, eg a run
field can’t be used to override behavior.
- name: Check out code
uses: actions/checkout@v1
with:
fetch-depth: 1
Under the hood the runner pulls the actions Docker image and runs it on the host VM.
This is a way to run Docker containers, but with predefined behavior. You can write your own actions too, check out how.
There is a third way to define the exection environment. By using the container
field, you can run custom commands within a specific Docker container.
name: Go
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
container:
image: golang:1.12.4
steps:
- name: Debug
run: |
go version
The above example sets the execution environment to be the golang:1.12.4
container, and all steps will be performed in that image, thus the Go tooling will be available throughout the job.
The runs-on
field is still mandatory as there is always a host machine, but with this approach I can prebake images that have the needed tools installed. Like kubectl
or go
.
This also differs from the canonical examples on the Github Actions page where the actions/setup-go@v1
action is used to install Go - the approach I also used in the first part of this article.
Putting the above in practice, and using the checkout path trick from the first part of this article, here is how I compiled go with Github Actions.
name: Go
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
container:
image: golang:1.12.4
env:
GOPATH: /__w/woodpecker/go/
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v1
with:
fetch-depth: 1
path: go/src/github.com/laszlocph/woodpecker
- name: Test
run: |
go get -u golang.org/x/tools/cmd/cover
go get -u golang.org/x/net/context
go get -u golang.org/x/net/context/ctxhttp
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
go test -cover $(go list ./... | grep -v /vendor/)
First, actions/setup-go@v1
is not ready yet, and setting $GOPATH manually is cumbersome.
Second, I’m a big supporter of the Drone.io CI system which to this day has revolutionary architecture. In Drone each step of the pipeline is performed in a specific Docker image. Replicating that behavior with Actions was my desire and I could achieve some of it.
The jobs.container
field does an okay job setting the runtime environment, but it also differs from Drone as there is only one image to be used in the whole job.
I’m not sure what to think of the Github Actions containerized environment and Github doesn’t seem to be sure either. There are multiple ways to control the runtime as I listed in this article, and the Github tutorials seem to favor the host machine examples, not the container ones.
One thing is clear though, Actions is flexible and the best practices will solidify over time.
Oh and one more thing, did you know that you can run docker-compose up
in Actions? Proof.
Onwards!
Are you running Kubernetes?
You can bootstrap logging, metrics and ingress with my new project, Gimlet Stack. Head over to gimlet.io and see if it helps you.