# GitLab CI template for Go This project implements a GitLab CI/CD template to build, test and analyse your [Go](https://golang.org/) projects. ## Usage In order to include this template in your project, add the following to your `gitlab-ci.yml`: ```yaml include: - project: 'to-be-continuous/golang' ref: '4.1.2' file: '/templates/gitlab-ci-golang.yml' ``` ## Global configuration The Go template uses some global configuration used throughout all jobs. | Name | description | default value | |------------------|------------------------------------------------------------------------------------------------------------|-----------------| | `GO_IMAGE` | The Docker image used to run Go for `go-build` <br/>:warning: **set the version required by your project** | `registry.hub.docker.com/library/golang:buster` | | `GO_TEST_IMAGE` | The Docker image used to run Go for `go-test` <br/>:warning: **set the version required by your project** | _none_ | | `GO_PROJECT_DIR` | Go project root directory | `.` | | `GOPROXY` | URL of Go module proxy | _none_ | ## Jobs ### 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. ```yaml 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](https://docs.gitlab.com/ee/ci/yaml/#parallel-matrix-jobs) pattern: ```yaml 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: | Name | description | default value | |-------------------------|-------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------| | `GO_BUILD_MODE` | The template build mode (accepted values are `application`, `modules` and `auto`) | `auto` | | `GO_BUILD_FLAGS` | Flags used by the [go build command](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies) | `-mod=readonly` | | `GO_BUILD_LINKER_FLAGS` | Linker flags used by the [go build command](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies) `-ldflags` | `-s -w` | | `GO_BUILD_PACKAGES` | Packages to build with the [go build command](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies) | `./...` | | `GO_TEST_FLAGS` | Flags used by the [go test command](https://pkg.go.dev/cmd/go#hdr-Test_packages) | `-mod=readonly -v -race` | | `GO_TEST_PACKAGES` | Packages to test with the [go test command](https://pkg.go.dev/cmd/go#hdr-Test_packages) | `./...` | | `GO_LIST_ARGS` | Arguments used by the list command | `list -u -m -mod=readonly -json all` | | `GO_TARGET_OS` | The `GOOS` target [see available values](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63) | _none_ (fallback to go docker image `GOOS`) | | `GO_TARGET_ARCH` | The `GOARCH` target [see available values](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63) | _none_ (fallback to go docker image `GOARCH`) | 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](https://docs.sonarqube.org/latest/analysis/test-coverage/test-execution-parameters/#header-8) | | `$GO_PROJECT_DIR/reports/go-test.xunit.xml` | [xUnit](https://en.wikipedia.org/wiki/XUnit) test report(s) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsjunit) | | `$GO_PROJECT_DIR/reports/go-coverage.native.out` | native Go coverage | N/A | | `$GO_PROJECT_DIR/reports/go-coverage.cobertura.xml` | [Cobertura XML](https://gcovr.com/en/stable/output/cobertura.html) coverage report | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report) | ### `go-ci-lint` job This job enables a manual [GolangCI-Lint](https://github.com/golangci/golangci-lint) analysis. It is bound to the `build` stage, and uses the following variables: | Name | description | default value | |-----------------------|----------------------------------------------------------------------------------------------------------|----------------------------------------| | `GO_CI_LINT_IMAGE` | The Docker image used to run `golangci-lint` | `registry.hub.docker.com/golangci/golangci-lint:latest-alpine` | | `GO_CI_LINT_ARGS` | `golangci-lint` [command line arguments](https://github.com/golangci/golangci-lint#command-line-options) | `-E gosec,goimports ./...` | | `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](https://docs.codeclimate.com/docs/pylint) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscodequality) | | `$GO_PROJECT_DIR/reports/go-ci-lint.checkstyle.xml` | Checkstyle | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/external-issues/) | ### `go-mod-outdated` job This job enables a manual [Go-mod-outdated](https://github.com/psampaz/go-mod-outdated) analysis. It is bound to the `test` stage, and uses the following variables: | Name | description | default value | |------------------------|-----------------------------------------------------------------------------------------------|-------------------| | `GO_MOD_OUTDATED_ARGS` | `god-mod-outdated` [command line arguments](https://github.com/psampaz/go-mod-outdated#usage) | `-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: ```properties # 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: * [Go language support](https://docs.sonarqube.org/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go) * [test coverage & execution parameters](https://docs.sonarqube.org/latest/analysis/coverage/) * [third-party issues](https://docs.sonarqube.org/latest/analysis/external-issues/) :warning: an [unsolved issue](https://jira.sonarsource.com/browse/SONARSLANG-450) may prevent SonarQube Go plugin from importing your test reports. ### `go-sbom` job This job generates a [SBOM](https://cyclonedx.org/) file listing installed packages using [@cyclonedx/cyclonedx-gomod](https://github.com/CycloneDX/cyclonedx-gomod). It is bound to the `test` stage, and uses the following variables: | Name | description | default value | | --------------------- | -------------------------------------- | ----------------- | | `GO_SBOM_DISABLED` | Set to `true` to disable this job | _none_ | | `GO_SBOM_IMAGE` | Image of cyclonedx-gomod used for SBOM analysis | `registry.hub.docker.com/cyclonedx/cyclonedx-gomod:latest` | | `GO_SBOM_OPTS` | [@cyclonedx/cyclonedx-gomod options](https://github.com/CycloneDX/cyclonedx-gomod#usage) used for SBOM analysis | `-main .` |