include: 
  - local: tests/unit.gitlab-ci.yml
  - local: tests/integration.gitlab-ci.yml
  - component: gitlab.com/components/container-scanning/container-scanning@1.0
    inputs:
      stage: quality
      # FIXME: why is this not the default?
      analyzer_image: "$CI_TEMPLATE_REGISTRY_HOST/security-products/container-scanning:6"
      # FIXME: why do I have to set this, this is weird ...
      force_run: true

stages:
  - build
  - test
  - test-integration
  - quality
  - deploy
  - release
  - cleanup

.opentofu-versions:
  parallel:
    matrix:
      - OPENTOFU_VERSION: '1.6.0'
      - OPENTOFU_VERSION: '1.6.0-rc1'

variables:
  # Pipeline configuration
  DOCKER_DIND_IMAGE: "docker:24.0.7-dind"

  # OpenTofu variables
  LATEST_OPENTOFU_VERSION: '1.6.0'

  # OpenTofu image build variables:
  PLATFORMS: linux/amd64,linux/arm64
  BASE_IMAGE: "alpine:3.19.0"
  GITLAB_OPENTOFU_IMAGE_BASE: "$CI_REGISTRY_IMAGE/internal"
  GITLAB_OPENTOFU_IMAGE_NAME: "$GITLAB_OPENTOFU_IMAGE_BASE/gitlab-opentofu:$CI_COMMIT_SHA-opentofu$OPENTOFU_VERSION"

gitlab-opentofu-image:build:
  extends: .opentofu-versions
  stage: build
  services:
    - "$DOCKER_DIND_IMAGE"
  image: "$DOCKER_DIND_IMAGE"
  before_script:
    # See note on the `build terraform` job about this image
    - docker run --rm --privileged tonistiigi/binfmt
    # Registry auth
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    - docker buildx create --use
    # NOTE: we disable provenance for now
    # because it causes troubles with the registry and older clients.
    # See
    # - https://gitlab.com/gitlab-org/terraform-images/-/issues/104
    # - https://gitlab.com/gitlab-org/terraform-images/-/merge_requests/184#note_1328485943
    - docker buildx build
      --platform "$PLATFORMS"
      --build-arg BASE_IMAGE=$BASE_IMAGE
      --build-arg OPENTOFU_VERSION=$OPENTOFU_VERSION
      --file Dockerfile
      --tag "$GITLAB_OPENTOFU_IMAGE_NAME"
      --provenance=false
      --push
      .

check-readme:
  stage: test
  needs: []
  image: alpine:latest
  before_script:
    - apk add coreutils yq make git
  script:
    - make docs
    - git diff --exit-code

check-backports:
  stage: test
  needs: []
  image: alpine:latest
  before_script:
    - apk add coreutils make git sed
  script:
    - make backports
    - git diff --exit-code

container_scanning:
  extends: .opentofu-versions
  needs: ['gitlab-opentofu-image:build']
  variables:
    CS_IMAGE: $GITLAB_OPENTOFU_IMAGE_NAME
    CS_SCHEMA_MODEL: 15

gitlab-opentofu-image:deploy:with-opentofu-version:
  extends: .opentofu-versions
  stage: deploy
  image:
    name: gcr.io/go-containerregistry/crane:debug
    entrypoint: [""]
  variables:
    RELEASE_IMAGE_NAME: "$CI_REGISTRY_IMAGE/gitlab-opentofu"
    # OCI image tags are not compatible with semver, specifically the build metadata part 
    # indicated with a `+` sign, see https://github.com/distribution/distribution/issues/1201
    # We use a dash `-` here, instead of the `+`.
    # This may be problematic, because it indicates a semver prerelease.
    RELEASE_SEMVER: "${CI_COMMIT_TAG}-opentofu${OPENTOFU_VERSION}"
    RELEASE_IMAGE: "$RELEASE_IMAGE_NAME:$RELEASE_SEMVER"
  before_script:
    - crane auth login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    - crane copy "$GITLAB_OPENTOFU_IMAGE_NAME" "$RELEASE_IMAGE"
    - 'echo "- \`$RELEASE_IMAGE\` (digest: \`$(crane digest $RELEASE_IMAGE)\`)" > image$CI_JOB_ID.txt'
  artifacts:
    paths:
      - 'image*.txt'
  rules:
    - if: $CI_COMMIT_TAG

gitlab-opentofu-image:deploy:latest-with-opentofu-version:
  extends: .opentofu-versions
  stage: deploy
  image:
    name: gcr.io/go-containerregistry/crane:debug
    entrypoint: [""]
  variables:
    RELEASE_IMAGE_NAME: "$CI_REGISTRY_IMAGE/gitlab-opentofu"
    RELEASE_SEMVER: "latest-opentofu${OPENTOFU_VERSION}"
    RELEASE_IMAGE: "$RELEASE_IMAGE_NAME:$RELEASE_SEMVER"
  before_script:
    - crane auth login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    - crane copy "$GITLAB_OPENTOFU_IMAGE_NAME" "$RELEASE_IMAGE"
    - 'echo "- \`$RELEASE_IMAGE\` (digest: \`$(crane digest $RELEASE_IMAGE)\`)" > image$CI_JOB_ID.txt'
  artifacts:
    paths:
      - 'image*.txt'
  rules:
    - if: $CI_COMMIT_TAG

gitlab-opentofu-image:deploy:latest:
  stage: deploy
  image:
    name: gcr.io/go-containerregistry/crane:debug
    entrypoint: [""]
  variables:
    OPENTOFU_VERSION: $LATEST_OPENTOFU_VERSION
    RELEASE_IMAGE_NAME: "$CI_REGISTRY_IMAGE/gitlab-opentofu"
    RELEASE_IMAGE: "$RELEASE_IMAGE_NAME:$RELEASE_IMAGE_TAG"
  before_script:
    - crane auth login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    - crane copy "$GITLAB_OPENTOFU_IMAGE_NAME" "$RELEASE_IMAGE"
    - 'echo "- \`$RELEASE_IMAGE\` (digest: \`$(crane digest $RELEASE_IMAGE)\`)" > image$CI_JOB_ID.txt'
  artifacts:
    paths:
      - 'image*.txt'
  rules:
    - if: $CI_COMMIT_TAG
  parallel:
    matrix:
      - RELEASE_IMAGE_TAG: ${CI_COMMIT_TAG}
      - RELEASE_IMAGE_TAG: ${CI_COMMIT_TAG}-opentofulatest
      - RELEASE_IMAGE_TAG: latest-opentofulatest
      - RELEASE_IMAGE_TAG: latest

# If the pipeline is for a new tag with a semantic version, and all previous jobs succeed,
# create the release.
.create-release:
  stage: release
  image: registry.gitlab.com/gitlab-org/release-cli:latest
  before_script:
    - apk add --update yq envsubst
  script: 
    - echo "Creating release $CI_COMMIT_TAG"
    - AVAILABLE_OPENTOFU_VERSIONS=$(yq -r '.spec.inputs.opentofu_version.options | filter((. | test("\$.*")) == false) | .[] | "- [`" + . + "`](https://github.com/opentofu/opentofu/releases/tag/v" + . + ")"' templates/full-pipeline.yml)
    - export AVAILABLE_OPENTOFU_VERSIONS
    - cat image*.txt | sort
    - 'AVAILABLE_IMAGES=$(cat image*.txt | sort | sed -E "s/(\(digest: .*\))/\n  - \1/")'
    - export AVAILABLE_IMAGES
    - cat .gitlab/release-template.md | envsubst > release-notes.md 

# create-release:dry-run:
#   extends: .create-release
#   script:
#     - !reference [.create-release, script]
#     - cat release-notes.md
#   artifacts:
#     paths:
#       - release-notes.md

create-release:
  extends: .create-release
  rules:
    - if: $CI_COMMIT_TAG =~ /\d+/
  release:
    tag_name: $CI_COMMIT_TAG
    description: './release-notes.md'

old-states:
  image: alpine:latest
  stage: cleanup
  variables:
    REMOVE_STATES_UNTIL: 1 week ago
    GITLAB_TOKEN: $GITLAB_STATE_CLEANER_TOKEN
  before_script:
    - apk add --update coreutils curl jq
    - export FETCH_OLDER_THAN=$(date '+%Y-%m-%dT%H:%M:%SZ' -d "${REMOVE_STATES_UNTIL}")
  script:
    - echo "Going to remove Terraform States older than '$FETCH_OLDER_THAN'"
    - ./.gitlab/scripts/fetch-states.sh | sed -n '1d;p' | ./.gitlab/scripts/remove-states.sh
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $STATE_CLEANER == "true"'
