stages:
  - test
  - build
  - deploy
  - release

variables:
  DOCKER_TLS_CERTDIR: "/certs"
  CONTAINER_IMAGE_COMMIT: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
  CONTAINER_IMAGE_LATEST: $CI_REGISTRY_IMAGE:latest
  CONTAINER_IMAGE_TEST: $CI_REGISTRY_IMAGE:integration-tests
  IMAGE_TAG: $CI_COMMIT_SHORT_SHA # Image tag for deployment pipeline

# GitLab Secure
# https://docs.gitlab.com/ee/user/application_security/

include:
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/License-Scanning.gitlab-ci.yml
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

# Templates

# Identify if source code changes. This is used to avoid triggering
# a new build or deployment if only documentation or CI files change.
.source_changes: &source_changes
  changes:
    - "Dockerfile"
    - "**/*.py"
    - "**/*.proto"
    - "Pipfile*"

.docker_job:
  image: docker:dind
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY

# Only test/build if source code has changed.
# Unfortunately, due to limitations of "changes" this will always run when a branch
# is first pushed so we only build once an MR is opened or running on $CI_DEFAULT_BRANCH.
#
# see: https://docs.gitlab.com/ee/ci/jobs/job_control.html#jobs-or-pipelines-run-unexpectedly-when-using-changes
.test:
  image: python:3.9
  stage: test
  rules:
    - if: $FORCE_DEPLOY != null
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      <<: *source_changes

.build:
  extends: .docker_job
  stage: build
  rules:
    - if: $FORCE_DEPLOY != null
    - !reference [.test, rules]

# Only deploy if on default branch
.deploy:
  stage: deploy
  rules:
    - if: $DEPLOY_STOP != null
      when: never
    - if: $FORCE_DEPLOY != null
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      <<: *source_changes

# Same rules as deploy but in different stage
.release:
  stage: release
  extends: .deploy

# Jobs

# Ensure VERSION file is updated if source code changes
check version:
  stage: test
  image:
    name: registry.gitlab.com/gitlab-com/gl-security/engineering-and-research/automation-team/docker/check-version:latest
    entrypoint: ['']
  script:
    - git fetch origin $CI_DEFAULT_BRANCH:$CI_DEFAULT_BRANCH
    - check-version
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      <<: *source_changes

lint:
  extends: .test
  script:
    - make lint

test:
  extends: .test
  script:
    - make test
  coverage: '/^TOTAL.+?(\d+\%)$/'

build:
  extends: .build
  script:
    - docker context create spamcheck
    - docker buildx create --use spamcheck
    - if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then PUSH="--push"; else PUSH="${FORCE_DEPLOY:+--push}"; fi
    - docker buildx build --provenance=false $PUSH --pull --platform linux/arm64/v8,linux/amd64 --tag $CONTAINER_IMAGE_COMMIT .

build test image:
  extends: .build
  script:
    - docker build --pull --tag $CONTAINER_IMAGE_TEST -f Dockerfile.test .
    - docker push $CONTAINER_IMAGE_TEST
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes:
        - tests/integration/run.rb
        - Dockerfile.test

deploy:
  extends: .deploy
  trigger:
    project: gitlab-private/gl-security/engineering-and-research/automation-team/kubernetes/spamcheck/spamcheck-py
    strategy: depend

release image:
  extends:
    - .docker_job
    - .release
  script:
    - VERSION="$(head -n1 VERSION | xargs)"
    - docker context create spamcheck
    - docker buildx create --use spamcheck
    - docker buildx build --provenance=false --cache-from $CONTAINER_IMAGE_COMMIT --push --platform linux/arm64/v8,linux/amd64 --tag $CONTAINER_IMAGE_LATEST --tag $CI_REGISTRY_IMAGE:$VERSION .

tag branch:
  extends: .release
  script:
    - VERSION="v$(head -n1 VERSION | xargs)"
    - git config user.name "gitlab-securitybot"
    - git config user.email "securitybot@gitlab.com"
    - git remote set-url origin "https://oauth2:${GITLAB_REPOSITORY_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
    - git tag "$VERSION"
    - git push --tags
