Skip to content
Snippets Groups Projects
README.md 14 KiB
Newer Older
Pierre Smeyers's avatar
Pierre Smeyers committed
# GitLab CI template for Go

This project implements a GitLab CI/CD template to build, test and analyse your [Go](https://golang.org/) projects.
Pierre Smeyers's avatar
Pierre Smeyers committed

## Usage

This template can be used both as a [CI/CD component](https://docs.gitlab.com/ee/ci/components/#use-a-component-in-a-cicd-configuration) 
or using the legacy [`include:project`](https://docs.gitlab.com/ee/ci/yaml/index.html#includeproject) syntax.

### Use as a CI/CD component

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

```yaml
include:
  # 1: include the component
  - component: gitlab.com/to-be-continuous/golang/gitlab-ci-golang@4.8.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`:
Pierre Smeyers's avatar
Pierre Smeyers committed

```yaml
include:
  # 1: include the template
Pierre Smeyers's avatar
Pierre Smeyers committed
  - project: 'to-be-continuous/golang'
Pierre Smeyers's avatar
Pierre Smeyers committed
    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
Pierre Smeyers's avatar
Pierre Smeyers committed
```

## 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` <br/>:warning: **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` <br/>:warning: **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_          |
Pierre Smeyers's avatar
Pierre Smeyers committed

## 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"
```

Pierre Smeyers's avatar
Pierre Smeyers committed
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"
```

Pierre Smeyers's avatar
Pierre Smeyers committed
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](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies)                   | `-mod=readonly`                               |
| `build-linker-flags` / `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`                                       |
| `build-packages` / `GO_BUILD_PACKAGES` | Packages to build with the [go build command](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies)          | `./...`                                       |
| `test-flags` / `GO_TEST_FLAGS` | Flags used by the [go test command](https://pkg.go.dev/cmd/go#hdr-Test_packages)                                        | `-mod=readonly -v -race`                      |
| `test-packages` / `GO_TEST_PACKAGES` | Packages to test with the [go test command](https://pkg.go.dev/cmd/go#hdr-Test_packages)                                | `./...`                                       |
| `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](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63)           | _none_ (fallback to go docker image `GOOS`)   |
| `target-arch` / `GO_TARGET_ARCH` | The `GOARCH` target [see available values](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63)         | _none_ (fallback to go docker image `GOARCH`) |
| `cobertura-flags` / `GO_COBERTURA_FLAGS` | The `GOFLAGS` to use with `gocover-cobertura` if needed                                                                 | _none_                                        |
Pierre Smeyers's avatar
Pierre Smeyers committed
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)       |
Pierre Smeyers's avatar
Pierre Smeyers committed

### `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:

| 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](https://github.com/golangci/golangci-lint#command-line-options) | `-E gosec,goimports ./...`             |
| `ci-lint-disabled` / `GO_CI_LINT_DISABLED` | Set to `true` to disable this job                                                                        | _none_(enabled)                        |
Pierre Smeyers's avatar
Pierre Smeyers committed
In addition to a textual report in the console, this job produces the following reports, kept for one day:

| Report                                                | Format                                                   | Usage                                                                                                       |
|-------------------------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
Pierre Smeyers's avatar
Pierre Smeyers committed
| `$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/)                        |
Pierre Smeyers's avatar
Pierre Smeyers committed

### `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:

| Input / Variable | Description                                                                                   | Default value     |
|------------------------|-----------------------------------------------------------------------------------------------|-------------------|
| `mod-outdated-args` / `GO_MOD_OUTDATED_ARGS` | `god-mod-outdated` [command line arguments](https://github.com/psampaz/go-mod-outdated#usage) | `-update -direct` |
Pierre Smeyers's avatar
Pierre Smeyers committed

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
Pierre Smeyers's avatar
Pierre Smeyers committed
# 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/**

Pierre Smeyers's avatar
Pierre Smeyers committed
# 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
* [Go language support](https://docs.sonarqube.org/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go)
Pierre Smeyers's avatar
Pierre Smeyers committed
* [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:

| 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](https://github.com/CycloneDX/cyclonedx-gomod#usage) used for SBOM analysis | `-main .` |
:warning: 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:

```yaml
variables:
  GO_SBOM_OPTS: "-main cmd/my_app"
```

### `go-govulncheck` job

This job enables Vulnerability Management with [Govulncheck](https://go.dev/blog/vuln).

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](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck#hdr-Flags) | `./...` |