workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_REF_PROTECTED == "true"

include:
  - component: ${CI_SERVER_FQDN}/gitlab-org/components/danger-review/danger-review@2.0.0
    inputs:
      job_stage: lint
      job_allow_failure: true

stages:
  - lint
  - test
  - deploy

.go:versions:
  parallel:
    matrix:
      - GOLANG_IMAGE_VERSION:
        - '1.22'
        - '1.23'
        - '1.24'

.go:base:
  # From: https://docs.gitlab.com/ee/ci/caching/#cache-go-dependencies
  variables:
    GOPATH: $CI_PROJECT_DIR/.go
    GOLANGCI_LINT_CACHE: $CI_PROJECT_DIR/.golangci-lint
  before_script:
    - mkdir -p "${GOPATH}" "${GOLANGCI_LINT_CACHE}"
  cache:
    paths:
      - $GOPATH/pkg/mod/
      - $GOLANGCI_LINT_CACHE/
    key:
      files:
        - go.sum
  # We want to speed up CI a bit.
  # Community contributors are recommended to use the Community fork
  # which has access to this runners.
  # For other forks to free tier namespaces this might fail,
  # which is a good reminder to use the Community fork and not
  # to accidentally burn to personal compute minutes.
  tags:
    - saas-linux-large-amd64
  # We only need to run Go-related jobs when actual Go files changed
  # or when running either on the default branch or for a tag.
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
    - if: $CI_COMMIT_TAG
    - changes:
        - '**/*.go'
        - testdata/**
        - go.mod
        - go.sum
        - .gitlab-ci.yml

golangci-lint:
  extends:
    - .go:base
  stage: lint
  needs: []
  variables:
    REPORT_FILENAME: 'gl-code-quality-report.json'
  image: golangci/golangci-lint:v1.64.5
  script:
    - golangci-lint run --print-issued-lines=false --out-format code-climate:$REPORT_FILENAME,line-number
  artifacts:
    reports:
      codequality: $REPORT_FILENAME
    paths: [$REPORT_FILENAME]
    when: always

tests:unit:
  extends:
    - .go:base
    - .go:versions
  stage: test
  needs: []
  image: golang:$GOLANG_IMAGE_VERSION
  variables:
    # configure tooling versions
    GOTESTSUM_VERSION: 'v1.12.0'
    GOCOVER_COBERTURA_VERSION: 'v1.2.1-0.20240107185409-0818f3538137'

    # configure artifact files
    JUNIT_FILENAME: tests.xml
    COVERPROFILE_FILENAME: coverage.out
    COVERPROFILE_XML_FILENAME: coverage.xml
  script:
    - go run gotest.tools/gotestsum@${GOTESTSUM_VERSION} --format=standard-quiet --junitfile=$JUNIT_FILENAME -- -race -coverprofile=$COVERPROFILE_FILENAME -covermode=atomic ./...
    - go run github.com/boumenot/gocover-cobertura@${GOCOVER_COBERTURA_VERSION} < $COVERPROFILE_FILENAME > $COVERPROFILE_XML_FILENAME
    - go tool cover -func $COVERPROFILE_FILENAME
  coverage: '/total:.+\(statements\).+\d+\.\d+/'
  artifacts:
    paths:
      - $JUNIT_FILENAME
      - $COVERPROFILE_XML_FILENAME
    reports:
      junit: $JUNIT_FILENAME
      coverage_report:
        path: $COVERPROFILE_XML_FILENAME
        coverage_format: cobertura
    when: always

generate-release-notes:
  stage: deploy
  needs: []
  image: alpine:3.21.2
  before_script:
    - apk add --update jq curl git
  script:
    - |
      if [ -z "$CI_COMMIT_TAG" ]; then
        last_stable_version_sha="$(git tag | grep -E '^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$' | sort -Vr | head -n1)"
        version="${last_stable_version_sha}+${CI_COMMIT_SHA}"
      else
        version="$CI_COMMIT_TAG"
      fi
      urlencoded_version="$(jq -rn --arg x "${version}" '$x|@uri')"
    - echo "Generating release notes for ${version} (urlencoded=${urlencoded_version}) ..."
    - 'curl --fail-with-body --header "JOB-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/changelog?version=${urlencoded_version}" | jq -r .notes > release-notes.md'
    - cat release-notes.md
  artifacts:
    paths:
    - release-notes.md

release:
  stage: deploy
  rules:
    - if: $CI_COMMIT_TAG
  needs:
    - golangci-lint
    - tests:unit
    - job: generate-release-notes
      artifacts: true
  image: registry.gitlab.com/gitlab-org/release-cli:latest
  script:
    - echo "Create release for $CI_COMMIT_TAG"
  release:
    tag_name: '$CI_COMMIT_TAG'
    tag_message: 'Version $CI_COMMIT_TAG'
    name: '$CI_COMMIT_TAG'
    description: release-notes.md
