Skip to content

GitLab CI template for Go

This project implements a GitLab CI/CD template to build, test and analyse your Go projects.

Usage

This template can be used both as a CI/CD component or using the legacy include:project syntax.

Use as a CI/CD component

Add the following to your .gitlab-ci.yml:

include:
  # 1: include the component
  - component: $CI_SERVER_FQDN/to-be-continuous/golang/gitlab-ci-golang@4.11.0
    # 2: set/override component inputs
    inputs:
      image: "registry.hub.docker.com/library/golang:buster" # ⚠ this is only an example

Use as a CI/CD template (legacy)

Add the following to your .gitlab-ci.yml:

include:
  # 1: include the template
  - project: 'to-be-continuous/golang'
    ref: '4.11.0'
    file: '/templates/gitlab-ci-golang.yml'

variables:
  # 2: set/override template variables
  GO_IMAGE: "registry.hub.docker.com/library/golang:buster" # ⚠ this is only an example

Global configuration

The Go template uses some global configuration used throughout all jobs.

Input / Variable Description Default value
image / GO_IMAGE The Docker image used to run Go for go-build
⚠ set the version required by your project
registry.hub.docker.com/library/golang:bookworm
test-image / GO_TEST_IMAGE The Docker image used to run Go for go-test
⚠ set the version required by your project
none
project-dir / GO_PROJECT_DIR Go project root directory .
goproxy / GOPROXY URL of Go module proxy none

Jobs

go generate job

The Go template supports code generation with go generate. It is disable by default and can be enabled by setting the GO_GENERATE_MODULES variable.

Input / Variable Description Default value
generate-modules / GO_GENERATE_MODULES Space separated list of Go code generator modules (ex: stringer mockery) none (disabled)

Capture generated files as job artifacts

Using go generate actually generates source files, that have to be captured and promoted all the way down to the build & test jobs.

In its default configuration, the template captures the following:

  • any folder named mock/ wherever in the file tree (entire content),
  • any folder named mocks/ wherever in the file tree (entire content),
  • any file matching *mock*.go pattern wherever in the file tree.

If this default doesn't suit your needs, you'll have to override the artifact path patterns (YAML). An example of this is given in the next chapter.

Example

variables:
  # list all required generate modules (including mockery)
  GO_GENERATE_MODULES: >
    github.com/vektra/mockery/v2@v2.38.0 
    github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latest 
    mockery

# override the artifact path patterns
go-generate:
  artifacts:
    paths:
      # list all the matchers to capture generated code
      - "**/*mockery.go"
      - "myapi/client/"

build & test jobs

You can specify if you want the template to build an application or modules with the GO_BUILD_MODE variable. It may have the following values:

  • application will make the build output the binaries (use -o build option, won't work if there is no main.go file)
  • modules won't output the binaries (no use of the -o option)
  • auto the template will rely on the presence of a main.go file to detect if it should output the binaries.

The build target platform is the one defined by the docker image but it can be overriden using the GO_TARGET_OS and GO_TARGET_ARCH variables.

variables:
  GO_TARGET_OS: "windows"
  GO_TARGET_ARCH: "amd64"

Build and tests can be done in separate jobs. If GO_TEST_IMAGE is not set (default), the go-build-test job will run build and tests at once. If GO_TEST_IMAGE is set, separate go-build and go-test jobs will be run in the build phase in parallel.

Separating build and test jobs can be useful to use different images (and hence different tools) or if you want to build muli-platform binaries.

Here is a .gitlab-ci.yml example that triggers a build on 3 target platforms using the parallel matrix jobs pattern:

variables:
  GO_IMAGE: "registry.hub.docker.com/library/golang:1.17-buster"
  GO_TEST_IMAGE: "registry.hub.docker.com/library/golang:1.17-buster"

go-build:
  parallel:
    matrix:
      - GO_TARGET_OS: "windows"
        GO_TARGET_ARCH: "amd64"
      - GO_TARGET_OS: "linux"
        GO_TARGET_ARCH: "amd64"
      - GO_TARGET_OS: "linux"
        GO_TARGET_ARCH: "arm"

These jobs use the following variable:

Input / Variable Description Default value
build-mode / GO_BUILD_MODE The template build mode (accepted values are application, modules and auto) auto
build-flags / GO_BUILD_FLAGS Flags used by the go build command -mod=readonly
build-linker-flags / GO_BUILD_LINKER_FLAGS Linker flags used by the go build command -ldflags -s -w
build-packages / GO_BUILD_PACKAGES Packages to build with the go build command ./...
test-flags / GO_TEST_FLAGS Flags used by the go test command -mod=readonly -v -race
test-packages / GO_TEST_PACKAGES Packages to test with the go test command ./...
list-args / GO_LIST_ARGS Arguments used by the list command list -u -m -mod=readonly -json all
target-os / GO_TARGET_OS The GOOS target see available values none (fallback to go docker image GOOS)
target-arch / GO_TARGET_ARCH The GOARCH target see available values none (fallback to go docker image GOARCH)
cobertura-flags / GO_COBERTURA_FLAGS The GOFLAGS to use with gocover-cobertura if needed none

In addition to a textual report in the console, the test jobs produce the following reports, kept for one day:

Report Format Usage
$GO_PROJECT_DIR/reports/go-test.native.txt native Go test report (text) N/A
$GO_PROJECT_DIR/reports/go-test.native.json native Go test report (json) SonarQube integration
$GO_PROJECT_DIR/reports/go-test.xunit.xml xUnit test report(s) GitLab integration
$GO_PROJECT_DIR/reports/go-coverage.native.out native Go coverage N/A
$GO_PROJECT_DIR/reports/go-coverage.cobertura.xml Cobertura XML coverage report GitLab integration

go-ci-lint job

This job enables a manual GolangCI-Lint analysis.

It is bound to the build stage, and uses the following variables:

Input / Variable Description Default value
ci-lint-image / GO_CI_LINT_IMAGE The Docker image used to run golangci-lint registry.hub.docker.com/golangci/golangci-lint:latest-alpine
ci-lint-args / GO_CI_LINT_ARGS golangci-lint command line arguments -E gosec,goimports ./...
ci-lint-disabled / GO_CI_LINT_DISABLED Set to true to disable this job none (enabled)

In addition to a textual report in the console, this job produces the following reports, kept for one day:

Report Format Usage
$GO_PROJECT_DIR/reports/go-ci-lint.codeclimate.json Code Climate GitLab integration
$GO_PROJECT_DIR/reports/go-ci-lint.checkstyle.xml Checkstyle SonarQube integration

go-semgrep job

This job performs a Semgrep analysis.

It is bound to the test stage, and uses the following variables:

Input / Variable Description Default Value
semgrep-disabled / GO_SEMGREP_DISABLED Set to true to disable this job none
semgrep-image / GO_SEMGREP_IMAGE The Docker image used to run Semgrep registry.hub.docker.com/semgrep/semgrep:latest
semgrep-args / GO_SEMGREP_ARGS Semgrep scan options --metrics off --disable-version-check
semgrep-rules / GO_SEMGREP_RULES Space-separated list of Semgrep rules.
Can be both local YAML files or remote rules from the Segmrep Registry (denoted by the p/ prefix).
p/golang p/gosec
semgrep-download-rules-enabled / GO_SEMGREP_DOWNLOAD_RULES_ENABLED Download Semgrep remote rules true

ℹ Semgrep may collect some metrics, especially when using rules from the Semgrep Registry. To protect your privacy and let you run Semgrep in air-gap environments, this template disables all Semgrep metrics by default:

  • rules from the Semgrep registry are pre-downloaded and passed to Semgrep as local rule files (can be disabled by setting semgrep-download-rules-enabled / GO_SEMGREP_DOWNLOAD_RULES_ENABLED to false),
  • the --metrics option is set to off,
  • the --disable-version-check option is set.

In addition to a textual report in the console, this job produces the following reports, kept for one week:

Report Format Usage
$GO_PROJECT_DIR/reports/golang-semgrep.gitlab.json GitLab's SAST format GitLab integration
$GO_PROJECT_DIR/reports/golang-semgrep.native.json Semgrep's JSON format DefectDojo integration
This report is generated only if DefectDojo template is detected

go-mod-outdated job

This job enables a manual Go-mod-outdated analysis.

It is bound to the test stage, and uses the following variables:

Input / Variable Description Default value
mod-outdated-args / GO_MOD_OUTDATED_ARGS god-mod-outdated command line arguments -update -direct

Checking outdated modules can be a long operation and therefore the job is configured to be ran manually by default (overridable).

SonarQube analysis

If you're using the SonarQube template to analyse your Go code, here is a sample sonar-project.properties file:

# see: https://docs.sonarqube.org/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go
# set your source directory(ies) here (relative to the sonar-project.properties file)
sonar.sources=.
# exclude unwanted directories and files from being analysed
sonar.exclusions=bin/**,**/*_test.go,**/vendor/**

# set your tests directory(ies) here (relative to the sonar-project.properties file)
sonar.tests=.
sonar.test.inclusions=**/*_test.go
sonar.test.exclusions=**/vendor/**

# tests report: JSON native format
sonar.go.tests.reportPaths=reports/go-test.native.json
# coverage report: native format
sonar.go.coverage.reportPaths=reports/go-coverage.native.out
# golanci-lint: checkstyle report (if enabled)
sonar.go.golangci-lint.reportPaths=reports/go-ci-lint.checkstyle.xml

More info:

⚠ an unsolved issue may prevent SonarQube Go plugin from importing your test reports.

go-sbom job

This job generates a SBOM file listing installed packages using @cyclonedx/cyclonedx-gomod.

It is bound to the test stage, and uses the following variables:

Input / Variable Description Default value
sbom-disabled / GO_SBOM_DISABLED Set to true to disable this job none
sbom-image / GO_SBOM_IMAGE Image of cyclonedx-gomod used for SBOM analysis registry.hub.docker.com/cyclonedx/cyclonedx-gomod:latest
sbom-opts / GO_SBOM_OPTS @cyclonedx/cyclonedx-gomod options used for SBOM analysis -main .

⚠ if you don't have your main class located at the root of your GO_PROJECT_DIR, then you will need to override the -main option in GO_SBOM_OPTS and define your real main class location.

Example:

variables:
  GO_SBOM_OPTS: "-main cmd/my_app"

go-govulncheck job

This job enables Vulnerability Management with Govulncheck.

It is bound to the test stage, and uses the following variables:

Input / Variable Description Default value
vulncheck-disabled / GO_VULNCHECK_DISABLED Set to true to disable this job none
vulncheck-args / GO_VULNCHECK_ARGS govulncheck command line arguments ./...