Commit 4d90e5cd authored by Guilhem Bonnefille's avatar Guilhem Bonnefille Committed by Pierre Smeyers
Browse files

feat: reuse $GO_BUILD_MODE for Sbom

parent dc114ab5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ The Go template uses some global configuration used throughout all 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.
+123 −114
Original line number Diff line number Diff line
@@ -128,125 +128,15 @@ stages:
  set -e

  function log_info() {
      echo -e "[\\e[1;94mINFO\\e[0m] $*"
    >&2 echo -e "[\\e[1;94mINFO\\e[0m] $*"
  }

  function log_warn() {
      echo -e "[\\e[1;93mWARN\\e[0m] $*"
    >&2 echo -e "[\\e[1;93mWARN\\e[0m] $*"
  }

  function log_error() {
      echo -e "[\\e[1;91mERROR\\e[0m] $*"
  }

  function output_coverage() {
    coverage_out=reports/go-coverage.native.out
    if [[ -f "$coverage_out" ]]
    then
      log_info "--- \\e[32mCoverage report(s) found\\e[0m (\\e[33;1m${coverage_out}\\e[0m): output"
      percent=$(go tool cover -func="$coverage_out" | tail -1 | awk -F" " '{print $NF}')
      echo "${percent} covered"

      go get github.com/boumenot/gocover-cobertura
      go run github.com/boumenot/gocover-cobertura < "$coverage_out" > reports/go-coverage.cobertura.xml
    else
      log_info "--- \\e[32mCoverage report(s) not found\\e[0m: skip"
    fi
  }

  function go_build() {
    case "${GO_BUILD_MODE}" in
      application)
        go_build_application
        ;;
      modules)
        go_build_modules
        ;;
      auto)
        go_build_auto
        ;;
      *)
        log_error "invalid \\e[94;1mGO_BUILD_MODE\\e[0m (expected values are \\e[96;1mapplication\\e[0m, \\e[96;1mmodules\\e[0m, \\e[96;1mauto\\e[0m)"
        exit 1
        ;;
    esac
  }

  function go_build_auto() {
    log_info "auto build mode, looking up for a \\e[33;1mmain\\e[0m package..."
    if grep -Rw --include "*.go" "^package main"
    then
      go_build_application
    else
      go_build_modules
    fi
  }

  function go_build_application() {
    log_info "building go application"
    GO_TARGET_OS="${GO_TARGET_OS:-$GOOS}"
    GO_TARGET_ARCH="${GO_TARGET_ARCH:-$GOARCH}"
    target_dir="$GOBIN/$GO_TARGET_OS/$GO_TARGET_ARCH"
    mkdir -p "$target_dir"
    # shellcheck disable=SC2086
    GOOS="$GO_TARGET_OS" GOARCH="$GO_TARGET_ARCH" go build -ldflags="$GO_BUILD_LINKER_FLAGS" $GO_BUILD_FLAGS -o "$target_dir" $GO_BUILD_PACKAGES
  }

  function go_build_modules() {
    log_info "building go modules"
    # shellcheck disable=SC2086
    go build -ldflags="$GO_BUILD_LINKER_FLAGS" $GO_BUILD_FLAGS $GO_BUILD_PACKAGES
  }

  function go_test() {
    mkdir -p -m 777 reports
    local go_text_report="reports/go-test.native.txt"

    set +e
    # shellcheck disable=SC2086
    go test $GO_TEST_FLAGS "-coverprofile=reports/go-coverage.native.out" $GO_TEST_PACKAGES > "$go_text_report"
    test_rc=$?
    set -e

    # dump text report in the console
    cat "$go_text_report"

    # compute and dump code coverage in the console
    output_coverage

    # produce JUnit report (for GitLab)
    install_go_junit_report
    "$GOBIN/go-junit-report" < "$go_text_report" > reports/go-test.xunit.xml

    # produce JSON report (for SonarQube)
    go tool test2json < "$go_text_report" > reports/go-test.native.json

    # maybe fail
    if [[ "$test_rc" != "0" ]]; then exit "$test_rc"; fi
  }

  function install_go_junit_report() {
    cd "$(mktemp -d)"
    go mod init go-junit-report
    go install github.com/jstemmer/go-junit-report@latest
    cd -
  }

  function install_go_mod_outdated() {
    cd "$(mktemp -d)"
    go mod init go-mod-outdated
    go install github.com/psampaz/go-mod-outdated@latest
    cd -
  }

  function install_go_govulncheck() {
    if ! command -v govulncheck  > /dev/null
    then
      cd "$(mktemp -d)"
      go mod init govulncheck
      go install golang.org/x/vuln/cmd/govulncheck@latest
      cd -
    fi
    >&2 echo -e "[\\e[1;91mERROR\\e[0m] $*"
  }

  function install_ca_certs() {
@@ -349,6 +239,123 @@ stages:
    log_info "... done"
  }

  function output_coverage() {
    coverage_out=reports/go-coverage.native.out
    if [[ -f "$coverage_out" ]]
    then
      log_info "--- \\e[32mCoverage report(s) found\\e[0m (\\e[33;1m${coverage_out}\\e[0m): output"
      percent=$(go tool cover -func="$coverage_out" | tail -1 | awk -F" " '{print $NF}')
      echo "${percent} covered"

      go get github.com/boumenot/gocover-cobertura
      go run github.com/boumenot/gocover-cobertura < "$coverage_out" > reports/go-coverage.cobertura.xml
    else
      log_info "--- \\e[32mCoverage report(s) not found\\e[0m: skip"
    fi
  }

  # evaluates Go build mode (manages 'auto' mode)
  function go_build_mode() {
    case "$GO_BUILD_MODE" in
      application|modules)
        echo "$GO_BUILD_MODE"
        ;;
      auto)
        go_main_src=$(find . -name "*.go" -exec grep -wl "^package main" {} \;)
        if [[ "$go_main_src" ]]
        then
          log_info "--- build mode auto-detected: \\e[96;1mapplication\\e[0m (main package found)"
          echo "application"
        else
          log_info "--- build mode auto-detected: \\e[96;1mmodules\\e[0m (no main package found)"
          echo "modules"
        fi
        ;;
      *)
        log_error "--- unsupported \\e[94;1m\$GO_BUILD_MODE\\e[0m value (expected values are \\e[96;1mapplication\\e[0m, \\e[96;1mmodules\\e[0m, \\e[96;1mauto\\e[0m)"
        exit 1
        ;;
    esac
  }

  function go_build() {
    case "$(go_build_mode)" in
      application)
        go_build_application
        ;;
      modules)
        go_build_modules
        ;;
    esac
  }

  function go_build_application() {
    log_info "building go application"
    GO_TARGET_OS="${GO_TARGET_OS:-$GOOS}"
    GO_TARGET_ARCH="${GO_TARGET_ARCH:-$GOARCH}"
    target_dir="$GOBIN/$GO_TARGET_OS/$GO_TARGET_ARCH"
    mkdir -p "$target_dir"
    # shellcheck disable=SC2086
    GOOS="$GO_TARGET_OS" GOARCH="$GO_TARGET_ARCH" go build -ldflags="$GO_BUILD_LINKER_FLAGS" $GO_BUILD_FLAGS -o "$target_dir" $GO_BUILD_PACKAGES
  }

  function go_build_modules() {
    log_info "building go modules"
    # shellcheck disable=SC2086
    go build -ldflags="$GO_BUILD_LINKER_FLAGS" $GO_BUILD_FLAGS $GO_BUILD_PACKAGES
  }

  function go_test() {
    mkdir -p -m 777 reports
    local go_text_report="reports/go-test.native.txt"

    set +e
    # shellcheck disable=SC2086
    go test $GO_TEST_FLAGS "-coverprofile=reports/go-coverage.native.out" $GO_TEST_PACKAGES > "$go_text_report"
    test_rc=$?
    set -e

    # dump text report in the console
    cat "$go_text_report"

    # compute and dump code coverage in the console
    output_coverage

    # produce JUnit report (for GitLab)
    install_go_junit_report
    "$GOBIN/go-junit-report" < "$go_text_report" > reports/go-test.xunit.xml

    # produce JSON report (for SonarQube)
    go tool test2json < "$go_text_report" > reports/go-test.native.json

    # maybe fail
    if [[ "$test_rc" != "0" ]]; then exit "$test_rc"; fi
  }

  function install_go_junit_report() {
    cd "$(mktemp -d)"
    go mod init go-junit-report
    go install github.com/jstemmer/go-junit-report@latest
    cd -
  }

  function install_go_mod_outdated() {
    cd "$(mktemp -d)"
    go mod init go-mod-outdated
    go install github.com/psampaz/go-mod-outdated@latest
    cd -
  }

  function install_go_govulncheck() {
    if ! command -v govulncheck  > /dev/null
    then
      cd "$(mktemp -d)"
      go mod init govulncheck
      go install golang.org/x/vuln/cmd/govulncheck@latest
      cd -
    fi
  }

  unscope_variables

  # ENDSCRIPT
@@ -509,7 +516,9 @@ go-sbom:
  needs: []
  script:
    - mkdir -p -m 777 reports
    - cyclonedx-gomod app -json -output reports/go-sbom.cyclonedx.json $GO_SBOM_OPTS
    - go_mode=$(go_build_mode)
    - |
      cyclonedx-gomod "${go_mode:0:3}" -json -output reports/go-sbom.cyclonedx.json $GO_SBOM_OPTS
    - chmod a+r reports/go-sbom.cyclonedx.json
  artifacts:
    name: "SBOM for golang from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"