# Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
default:
  image: docker
  services:
    - name: docker:dind
      command: ["--experimental"]

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  BUILD_MULTI_ARCH_IMAGES: "true"

stages:
  - trigger
  - image
  - lint
  - go-checks
  - go-build
  - unit-tests
  - package-build
  - image-build
  - test
  - scan
  - release
  - sign

.pipeline-trigger-rules:
  rules:
    # We trigger the pipeline if started manually
    - if: $CI_PIPELINE_SOURCE == "web"
    # We trigger the pipeline on the main branch
    - if: $CI_COMMIT_BRANCH == "main"
    # We trigger the pipeline on the release- branches
    - if: $CI_COMMIT_BRANCH =~ /^release-.*$/
    # We trigger the pipeline on tags
    - if: $CI_COMMIT_TAG && $CI_COMMIT_TAG != ""

workflow:
  rules:
    # We trigger the pipeline on a merge request
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    # We then add all the regular triggers
    - !reference [.pipeline-trigger-rules, rules]

# The main or manual job is used to filter out distributions or architectures that are not required on
# every build.
.main-or-manual:
  rules:
    - !reference [.pipeline-trigger-rules, rules]
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: manual

# The trigger-pipeline job adds a manualy triggered job to the pipeline on merge requests.
trigger-pipeline:
  stage: trigger
  script:
    - echo "starting pipeline"
  rules:
    - !reference [.main-or-manual, rules]
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: manual
      allow_failure: false
    - when: always

# Define the distribution targets
.dist-centos7:
  rules:
    - !reference [.main-or-manual, rules]
  variables:
    DIST: centos7

.dist-centos8:
  variables:
    DIST: centos8

.dist-ubi8:
  rules:
    - !reference [.main-or-manual, rules]
  variables:
    DIST: ubi8

.dist-ubuntu18.04:
  variables:
    DIST: ubuntu18.04

.dist-ubuntu20.04:
  variables:
    DIST: ubuntu20.04

.dist-packaging:
  variables:
    DIST: packaging

# Define architecture targets
.arch-aarch64:
  variables:
    ARCH: aarch64

.arch-amd64:
  variables:
    ARCH: amd64

.arch-arm64:
  variables:
    ARCH: arm64

.arch-ppc64le:
  rules:
    - !reference [.main-or-manual, rules]
  variables:
    ARCH: ppc64le

.arch-x86_64:
  variables:
    ARCH: x86_64

# Define the platform targets
.platform-amd64:
  variables:
    PLATFORM: linux/amd64

.platform-arm64:
  variables:
    PLATFORM: linux/arm64

# Define test helpers
.integration:
  stage: test
  variables:
    IMAGE_NAME: "${CI_REGISTRY_IMAGE}/container-toolkit"
    VERSION: "${CI_COMMIT_SHORT_SHA}"
  before_script:
    - apk add --no-cache make bash jq
    - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}"
    - docker pull "${IMAGE_NAME}:${VERSION}-${DIST}"
  script:
    - make -f deployments/container/Makefile test-${DIST}

# Define the test targets
test-packaging:
  extends:
    - .integration
    - .dist-packaging
  needs:
    - image-packaging

# Download the regctl binary for use in the release steps
.regctl-setup:
  before_script:
    - export REGCTL_VERSION=v0.4.5
    - apk add --no-cache curl
    - mkdir -p bin
    - curl -sSLo bin/regctl https://github.com/regclient/regclient/releases/download/${REGCTL_VERSION}/regctl-linux-amd64
    - chmod a+x bin/regctl
    - export PATH=$(pwd)/bin:${PATH}

# .release forms the base of the deployment jobs which push images to the CI registry.
# This is extended with the version to be deployed (e.g. the SHA or TAG) and the
# target os.
.release:
  stage: release
  variables:
    # Define the source image for the release
    IMAGE_NAME: "${CI_REGISTRY_IMAGE}/container-toolkit"
    VERSION: "${CI_COMMIT_SHORT_SHA}"
    # OUT_IMAGE_VERSION is overridden for external releases
    OUT_IMAGE_VERSION: "${CI_COMMIT_SHORT_SHA}"
  before_script:
    - !reference [.regctl-setup, before_script]

    # We ensure that the OUT_IMAGE_VERSION is set
    - 'echo Version: ${OUT_IMAGE_VERSION} ; [[ -n "${OUT_IMAGE_VERSION}" ]] || exit 1'

    # In the case where we are deploying a different version to the CI_COMMIT_SHA, we
    # need to tag the image.
    # Note: a leading 'v' is stripped from the version if present
    - apk add --no-cache make bash
  script:
    # Log in to the "output" registry, tag the image and push the image
    - 'echo "Logging in to CI registry ${CI_REGISTRY}"'
    - regctl registry login "${CI_REGISTRY}" -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}"
    - '[ ${CI_REGISTRY} = ${OUT_REGISTRY} ] || echo "Logging in to output registry ${OUT_REGISTRY}"'
    - '[ ${CI_REGISTRY} = ${OUT_REGISTRY} ] || regctl registry login "${OUT_REGISTRY}" -u "${OUT_REGISTRY_USER}" -p "${OUT_REGISTRY_TOKEN}"'

    # Since OUT_IMAGE_NAME and OUT_IMAGE_VERSION are set, this will push the CI image to the
    # Target
    - make -f deployments/container/Makefile push-${DIST}

# Define a staging release step that pushes an image to an internal "staging" repository
# This is triggered for all pipelines (i.e. not only tags) to test the pipeline steps
# outside of the release process.
.release:staging:
  extends:
    - .release
  variables:
    OUT_REGISTRY_USER: "${CI_REGISTRY_USER}"
    OUT_REGISTRY_TOKEN: "${CI_REGISTRY_PASSWORD}"
    OUT_REGISTRY: "${CI_REGISTRY}"
    OUT_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/staging/container-toolkit"

# Define an external release step that pushes an image to an external repository.
# This includes a devlopment image off main.
.release:external:
  extends:
    - .release
  variables:
    FORCE_PUBLISH_IMAGES: "yes"
  rules:
    - if: $CI_COMMIT_TAG
      variables:
        OUT_IMAGE_VERSION: "${CI_COMMIT_TAG}"
    - if: $CI_COMMIT_BRANCH == $RELEASE_DEVEL_BRANCH
      variables:
        OUT_IMAGE_VERSION: "${DEVEL_RELEASE_IMAGE_VERSION}"

# Define the release jobs
release:staging-ubi8:
  extends:
    - .release:staging
    - .dist-ubi8
  needs:
    - image-ubi8

release:staging-ubuntu20.04:
  extends:
    - .release:staging
    - .dist-ubuntu20.04
  needs:
    - test-toolkit-ubuntu20.04
    - test-containerd-ubuntu20.04
    - test-crio-ubuntu20.04
    - test-docker-ubuntu20.04

release:staging-packaging:
  extends:
    - .release:staging
    - .dist-packaging
  needs:
    - test-packaging