Building Go project in Codebuild

2021.07.30

Intro

AWS Codebuild is a service allowing to build project, run tests and produce ready to deploy packages in continuous integration manner. It scales continuously and manages concurrent builds. Today we will take a look how to prepare build project for Go with Codebuild.

Input

Codebuild takes your code from specified source, builds it and outputs it in specified location. Supported inputs are AWS S3, AWS Codecommit, Github, Bitbucket and Github Enterprise. The created package is uploaded to S3 bucket. In our example we will use AWS S3 as source.

The input is a zipped project with buildspec.yml file at the top level directory.

Buildspec file is a collection of build commands in YAML format. Without it, Codebuild cannot convert your source code into deployable package.

version: 0.2

env:
  variables:
    GO_VERSION: 1.16.5
phases:
  install:
    commands:
      - yum install -y ***EXAMPLE_PACKAGES***
      - wget https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz
      - tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz
      - export PATH="/usr/local/go/bin:$PATH" && export GOPATH="$HOME/go" && export PATH="$GOPATH/bin:$PATH"
      - go get -v -u ***GO_MODULES***
  pre_build:
    commands:
      - echo Start pre_build...
  build:
    commands:
      - echo Start build...
      - cd $CODEBUILD_SRC_DIR && go build
  post_build:
    commands:
      - echo Start post_build...
      - aws s3 cp $CODEBUILD_SRC_DIR/main s3://bucket-name/

Above is a buildspec.yml we will use for our project. Spec file consists of phases (install, pre_build, build, post_build). In install phase we can run all commands that will prepare the environment for our build. This phase can be skipped if you provide your own docker image for the build, but since we will use AWS managed image, we will run couple commands in this phase.

AWS managed image supports Go environment until 1.15 version, if you want the newest 1.16.5, you need to run above commands to install it. In above example there are two commands (yum install, go get) that our project doesn't need, but are there to demonstrate how to install additional packages or Go modules.

In pre_build phase there is nothing to be done, so we go straight to build phase. We echo Start build... for logging purposes and run the build command. Important point is, Codebuild runs commands separate, if you run cd command and then go build command on different lines, you will get file not found error, or project doesn't exists. Because of that we run cd and go build commands connected with && sign.

The final, post_build phase is where we upload created binary file to destination bucket.

Now we need to zip our project. The zip file should contain the buildspec.yml file in top level directory, so in our case we need to zip the src folder. Then we just upload the zipped file into source bucket.

Creating build project

Having source in AWS bucket now it's time to create the project. Because our example is very simple, we will use default values in most options.

Below we give it a name and optional description. You can also add tags for the build and specify build limits. We will only provide it a name.

Next is source. We choose AWS S3 and specify the bucket where we uploaded the src.zip file. We also need to insert the zip file name.

For environment we choose AWS Linux 2 with all values default.

Not required but helpful in-case something goes wrong are logs. For that we need to provide CloudWatch group name and stream name to be created with our project. Make sure the names don't exist already.

Build

Our project is complete, we are ready to build. Just go to the created project and push Start build button. Having done that, you can go to logs tab and monitor the process. Once build is done, the binary file is uploaded to specified bucket. If something goes wrong, you will see that in the logs screen.

Conclusion

We discovered basics of AWS Codebuild, a service allowing to build your project from specified source and upload the created package to S3. We created buildspec.yml file where we prepare environment for build as well as source files, and created Codebuild build project.