From bafd24de55b17039204e9dbf1a6c9cdbb718a009 Mon Sep 17 00:00:00 2001
From: Timo Furrer <tfurrer@gitlab.com>
Date: Wed, 30 Oct 2024 13:24:54 +0100
Subject: [PATCH] Only sign images on GitLab.com

Changelog: fixed
---
 .gitlab-ci.yml           | 97 +++++++++++++++++++++++-----------------
 tests/unit.gitlab-ci.yml |  2 +-
 2 files changed, 58 insertions(+), 41 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fd18f97..d6214f2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -57,7 +57,7 @@ stages:
   - release
   - cleanup
 
-.image-matrix:
+.image-matrix:build:
   parallel:
     matrix:
       - OPENTOFU_VERSION: !reference [.data, supported_versions]
@@ -65,6 +65,36 @@ stages:
           - 'alpine'
           - 'debian'
 
+.image-matrix:deploy:
+  parallel:
+    # OPENTOFU_VERSION: opentofu version to release in the job (from gitlab-opentofu-image:build)
+    # RELEASE_VERSION:  Tag base for the release image
+    # RELEASE_OPENTOFU_VERSION:  opentofu version to contained in the release tag
+    matrix:
+      - # :{commit-tag}-opentofu{opentofu-version}
+        OPENTOFU_VERSION: !reference [.data, supported_versions]
+        RELEASE_VERSION: $CI_COMMIT_TAG
+        RELEASE_OPENTOFU_VERSION: $OPENTOFU_VERSION
+        RELEASE_BASE_IMAGE_OS: ['alpine', 'debian']
+      - # :latest-opentofu{opentofu-version}
+        OPENTOFU_VERSION: !reference [.data, supported_versions]
+        RELEASE_VERSION: latest
+        RELEASE_OPENTOFU_VERSION: $OPENTOFU_VERSION
+        RELEASE_BASE_IMAGE_OS: ['alpine', 'debian']
+      - # :{commit-tag|latest}{-opentofulatest|}
+        OPENTOFU_VERSION: $LATEST_OPENTOFU_VERSION
+        RELEASE_VERSION: ["${CI_COMMIT_TAG}", latest]
+        RELEASE_OPENTOFU_VERSION: ["", latest]
+        RELEASE_BASE_IMAGE_OS: ['alpine', 'debian']
+
+.image-matrix:deploy:release-name-script: &image-matrix-deploy-release-name-script
+  # 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.
+  - export RELEASE_IMAGE_NAME="$CI_REGISTRY_IMAGE/gitlab-opentofu"
+  - export RELEASE_IMAGE="${RELEASE_IMAGE_NAME}:${RELEASE_VERSION}${RELEASE_OPENTOFU_VERSION:+-opentofu$RELEASE_OPENTOFU_VERSION}${RELEASE_BASE_IMAGE_OS:+-$RELEASE_BASE_IMAGE_OS}"
+
 variables:
   # OpenTofu variables
   LATEST_OPENTOFU_VERSION: !reference [.data, latest_version]
@@ -85,7 +115,7 @@ check-semantic-version:
     - echo -n "$CI_COMMIT_TAG" | ./.gitlab/scripts/check-semantic-version.sh
 
 gitlab-opentofu-image:build:
-  extends: .image-matrix
+  extends: '.image-matrix:build'
   stage: build
   image: quay.io/containers/buildah:v1.37.3
   before_script:
@@ -180,6 +210,7 @@ shellcheck:
 #     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
 
 .gitlab-opentofu-image:deploy:base:
+  extends: '.image-matrix:deploy'
   stage: deploy
   image:
     name: alpine/crane:0.20.2
@@ -187,52 +218,15 @@ shellcheck:
   variables:
     GITLAB_OPENTOFU_BASE_IMAGE_OS: $RELEASE_BASE_IMAGE_OS
   before_script:
+    - *image-matrix-deploy-release-name-script
     - crane auth login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
-    # 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.
-    - export RELEASE_IMAGE_NAME="$CI_REGISTRY_IMAGE/gitlab-opentofu"
-    - export RELEASE_IMAGE="${RELEASE_IMAGE_NAME}:${RELEASE_VERSION}${RELEASE_OPENTOFU_VERSION:+-opentofu$RELEASE_OPENTOFU_VERSION}${RELEASE_BASE_IMAGE_OS:+-$RELEASE_BASE_IMAGE_OS}"
     - 'echo "base image OS: $GITLAB_OPENTOFU_BASE_IMAGE_OS"'
     - echo "Deploying $GITLAB_OPENTOFU_IMAGE_NAME as $RELEASE_IMAGE"
-  parallel:
-    # OPENTOFU_VERSION: opentofu version to release in the job (from gitlab-opentofu-image:build)
-    # RELEASE_VERSION:  Tag base for the release image
-    # RELEASE_OPENTOFU_VERSION:  opentofu version to contained in the release tag
-    matrix:
-      - # :{commit-tag}-opentofu{opentofu-version}
-        OPENTOFU_VERSION: !reference [.data, supported_versions]
-        RELEASE_VERSION: $CI_COMMIT_TAG
-        RELEASE_OPENTOFU_VERSION: $OPENTOFU_VERSION
-        RELEASE_BASE_IMAGE_OS: ['alpine', 'debian']
-      - # :latest-opentofu{opentofu-version}
-        OPENTOFU_VERSION: !reference [.data, supported_versions]
-        RELEASE_VERSION: latest
-        RELEASE_OPENTOFU_VERSION: $OPENTOFU_VERSION
-        RELEASE_BASE_IMAGE_OS: ['alpine', 'debian']
-      - # :{commit-tag|latest}{-opentofulatest|}
-        OPENTOFU_VERSION: $LATEST_OPENTOFU_VERSION
-        RELEASE_VERSION: ["${CI_COMMIT_TAG}", latest]
-        RELEASE_OPENTOFU_VERSION: ["", latest]
-        RELEASE_BASE_IMAGE_OS: ['alpine', 'debian']
 
 gitlab-opentofu-image:deploy:
   extends: ['.gitlab-opentofu-image:deploy:base']
-  variables:
-    COSIGN_YES: "true"  # Used by Cosign to skip confirmation prompts for non-destructive operations
-  id_tokens:
-    SIGSTORE_ID_TOKEN:
-      aud: sigstore
   script:
-    # Install dependencies, can't use before_script because of the job we are extending.
-    - apk add --update cosign
-    # Release image
     - crane copy "$GITLAB_OPENTOFU_IMAGE_NAME" "$RELEASE_IMAGE"
-    # Sign image
-    - cosign sign "$(crane digest --full-ref "$RELEASE_IMAGE")"
-    - export image_digest="$(crane digest $RELEASE_IMAGE)"
-    - 'echo "- \`$RELEASE_IMAGE\` (digest: \`$image_digest\`)" > image$CI_JOB_ID.md'
   artifacts:
     paths:
       - 'image*.md'
@@ -254,6 +248,29 @@ gitlab-opentofu-image:deploy:dry-run:
         - .gitlab-ci.yml
         - src/**/*
 
+gitlab-opentofu-image:sign:
+  extends: '.image-matrix:deploy'
+  image: alpine:3.20.3
+  variables:
+    COSIGN_YES: "true"  # Used by Cosign to skip confirmation prompts for non-destructive operations
+  id_tokens:
+    SIGSTORE_ID_TOKEN:
+      aud: sigstore
+  before_script:
+    - *image-matrix-deploy-release-name-script
+    - apk add --update cosign
+  script:
+    - cosign sign "$(crane digest --full-ref "$RELEASE_IMAGE")"
+    - export image_digest="$(crane digest $RELEASE_IMAGE)"
+    - 'echo "- \`$RELEASE_IMAGE\` (digest: \`$image_digest\`)" > image$CI_JOB_ID.md'
+  artifacts:
+    paths:
+      - 'image*.md'
+  rules:
+    - if: '$CI_SERVER_FQDN != "gitlab.com"'
+      when: never
+    - if: $CI_COMMIT_TAG
+
 .release:base:
   stage: release
   image: registry.gitlab.com/gitlab-org/release-cli:v0.19.0
diff --git a/tests/unit.gitlab-ci.yml b/tests/unit.gitlab-ci.yml
index aa8f462..e35f0b6 100644
--- a/tests/unit.gitlab-ci.yml
+++ b/tests/unit.gitlab-ci.yml
@@ -33,7 +33,7 @@ variables:
 unit-test:gitlab-tofu:
   extends:
     - .unit-test-base
-    - .image-matrix
+    - .image-matrix:build
   script:
     - bats --jobs 8 --report-formatter junit --filter-tags '!source' tests/unit/gitlab-tofu.bats
 
-- 
GitLab