variables:
  GO_VERSION: "1.19"

# run the pipeline only on MRs, tags, and default branch
workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

default:
  image: golang:${GO_VERSION}

stages:
  - documentation
  - test
  - release

include:
  # remove the `.latest` from the following templates after 16.0 GitLab release
  # the `.latest` indicates the "nightly" version of the job definition
  # when we remove the `.latest`, we'll be using the stable job definition
  # https://gitlab.com/gitlab-org/cli/-/merge_requests/1100#note_1186302003
  - template: Jobs/SAST.latest.gitlab-ci.yml
  - template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml
  - template: Jobs/Secret-Detection.latest.gitlab-ci.yml
  - template: Jobs/License-Scanning.latest.gitlab-ci.yml
  - project: 'gitlab-org/quality/pipeline-common'
    file: '/ci/danger-review.yml'  # danger-review job below


# From: https://docs.gitlab.com/ee/ci/caching/#cache-go-dependencies
.go-cache:
  variables:
    GOPATH: $CI_PROJECT_DIR/.go
    GOLANGCI_LINT_CACHE: $CI_PROJECT_DIR/.golangci-lint
  before_script:
    - mkdir -p .go .golangci-lint
  cache:
    paths:
      - .go/pkg/mod/
      - .golangci-lint/

.documentation:
  stage: documentation
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

check_docs_update:
  extends: .documentation
  script:
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME && git checkout $CI_MERGE_REQUEST_TARGET_BRANCH_NAME && git checkout $CI_COMMIT_SHA
    - make gen-docs
    - |-
        git status
        if [[ $(git add -A --dry-run) ]]; then
          echo '✖ ERROR: Documentation changes detected!';
          echo '✖ These changes require a documentation update. To regenerate the docs, read https://gitlab.com/gitlab-org/cli/-/tree/main/docs#generating-the-docs.';
          exit 1;
        else
          echo '✔ No documentation updates detected.';
          exit 0;
        fi

check_docs_markdown:
  image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.16-vale-2.20.1-markdownlint-0.32.2
  extends: .documentation
  script:
    # Lint prose
    - vale --minAlertLevel error docs *.md
    # Lint Markdown
    - markdownlint --config .markdownlint.yml 'docs/**/*.md' *.md

lint_commit:
  stage: test
  image: node:16-slim
  script:
    - apt-get update && apt-get install -y git
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME && git checkout $CI_MERGE_REQUEST_TARGET_BRANCH_NAME && git checkout $CI_COMMIT_SHA
    - cd scripts/commit-lint && npm ci
    - node lint.js
  rules:
    - if: '$CI_MERGE_REQUEST_IID && $CI_PROJECT_VISIBILITY == "public"' # lint.js script makes an API call without authentication
      when: always

lint:
  extends: .go-cache
  image: registry.gitlab.com/gitlab-org/gitlab-build-images:golangci-lint-1.52-alpine
  stage: test
  script:
    - golangci-lint --version
    # Use default .golangci.yml file from the image if one is not present in the project root.
    - '[ -e .golangci.yml ] || cp /golangci/.golangci.yml .'
    # Write the code coverage report to gl-code-quality-report.json
    # remove `--issues-exit-code 0` or set to non-zero to fail the job if linting issues are detected
    - golangci-lint run --out-format colored-line-number:stdout,code-climate:gl-code-quality-report.json
  artifacts:
    reports:
      codequality: gl-code-quality-report.json
    paths:
      - gl-code-quality-report.json

code_navigation:
  stage: test
  image: golang:latest
  allow_failure: true
  script:
    - go install github.com/sourcegraph/lsif-go/cmd/lsif-go@latest
    - lsif-go
  artifacts:
    reports:
      lsif: dump.lsif

run_tests:
  stage: test
  extends: .go-cache
  parallel:
    matrix:
      - GO_VERSION: ["1.19", "1.20"]
  script:
    # `goreleaser` also uses GITLAB_TOKEN and so we need to distinguish between
    # the GITLAB_TOKEN_TEST with less privilege used for testing and the GITLAB_TOKEN_RELEASE token
    # GITLAB_TEST_HOST is the GitLab instance used for the integration tests
    - GITLAB_TOKEN=$GITLAB_TOKEN_TEST GITLAB_TEST_HOST=$GITLAB_TEST_HOST make test
  after_script:
    - echo -e "\e[0Ksection_start:`date +%s`:coverage[collapsed=true]\r\e[0KRunning coverage report"
    - make coverage
    - echo -e "\e[0Ksection_end:`date +%s`:coverage\r\e[0K"
  coverage: /^total:\t+\(statements\)\t+\d+\.\d+%$/
  artifacts:
    when: always
    paths:
      - test-output.log
    reports:
      junit: coverage.xml

.release:
  stage: release
  image: docker:stable
  services:
    - docker:dind
  variables:
    # Disable shallow cloning so that goreleaser can diff between tags to
    # generate a changelog.
    GIT_DEPTH: 0
  needs: [windows_installer]
  dependencies: [windows_installer]

release_test:
  extends: .release
  rules:
    - if: $CI_COMMIT_TAG
      when: never
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script: |
    docker run --rm --privileged \
      -v $PWD:/go/src/gitlab.com/gitlab-org/cli \
      -w /go/src/gitlab.com/gitlab-org/cli \
      -v /var/run/docker.sock:/var/run/docker.sock \
      goreleaser/goreleaser release --snapshot

build_windows:
  stage: test
  extends: .go-cache
  script:
    - GOOS=windows GOARCH=amd64 make build
    - mv bin/glab bin/glab.exe
  artifacts:
    paths:
      - "bin/glab.exe"
    expire_in: "30 days"

windows_installer:
  stage: release
  image:
    name: amake/innosetup
    entrypoint: [""]
  script:
    - mv scripts/setup_windows.iss .
    - iscc "setup_windows.iss" -DVersion=${CI_COMMIT_TAG//v}
  artifacts:
    paths:
      - "bin/*"
    expire_in: "30 days"
  dependencies: [build_windows]
  needs: [build_windows]

release:
  extends: .release
  rules:
    - if: $CI_COMMIT_TAG
  script: |
    docker run --rm --privileged \
      -v $PWD:/go/src/gitlab.com/gitlab-org/cli \
      -w /go/src/gitlab.com/gitlab-org/cli \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -e GITLAB_TOKEN=$GITLAB_TOKEN_RELEASE \
      --entrypoint "" \
      goreleaser/goreleaser \
      bash -c "
        docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
        docker login -u $DOCKER_IO_USER -p $DOCKER_IO_PASSWORD
        goreleaser release
      "

homebrew-release:
  image: homebrew/ubuntu22.04:latest
  stage: release
  rules:
    - if: $CI_COMMIT_TAG
  script:
    - touch ~/.gitconfig
    - git config --global user.email "$GITHUB_EMAIL"
    - git config --global user.name "$GITHUB_NAME"
    - curl "$CI_PROJECT_URL/-/archive/$CI_COMMIT_TAG/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.gz" --output "$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.gz"
    - brew bump-formula-pr glab --no-browse --url="$CI_PROJECT_URL/-/archive/$CI_COMMIT_TAG/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.gz" --sha256="$(sha256sum $CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.gz | cut -d ' ' -f 1)"

secret_detection:
  dependencies: [] # Don't download artifacts, especially `./public/`
