From b82a232ee86a8e9627c116e3a5357fd451170407 Mon Sep 17 00:00:00 2001
From: Daniel Dehennin <daniel.dehennin@ac-dijon.fr>
Date: Tue, 30 Nov 2021 10:44:01 +0100
Subject: [PATCH] feat(docker): tag images based on release cycle

We want to tag images based on the different steps of the release
cycle:

- `dev` images where developpement is integrated
- `testing` images where releases are stabilised
- `stable` images when the release is done
  - `major` tag with only the first digit of the semantic version,
    this tag will always point to the latest release of the major
    version
  - `minor` tag with only the first 2 digits of the semantic version,
    this tag will always point to the latest release of the minor
    version
  - `release` tag with the full semantic version
  - `latest`/`stable` point to the latest stable image

Define `.tag-docker-image` template used by `*-docker-tag` jobs It tag
the `${IMAGE_NAME}:${SOURCE_TAG}` with the tag `${IMAGE_TAG}`

USAGE
=====

foo-docker-tag-devel:
  extends: .tag-docker-image
  variables:
    IMAGE_TAG: 'devel'

REQUIREMENTS
============

- A `release` stage must be present in your pipeline or it must be
  overriden by the extending job to feet your need.
- The `.not-on-stable` rules template

OPTIONAL VARIABLES
==================

- `IMAGE_NAME`: defaults to `${CI_JOB_NAME}` with any suffix
  `-docker-tag*` removed
- `SOURCE_TAG`: source image tag to retag, defaults to
  `git-${CI_COMMIT_SHORT_SHA}`
- `IMAGE_TAG`: image tag, defaults to `${CI_COMMIT_TAG}` with prefix
  `RELEASE_PREFIX` removed
- `RELEASE_PREFIX`: prefix of the `RELEASE`, defaults to `release/`

USED CI VARIABLES
=================

- `CI_REGISTRY`
- `CI_REGISTRY_USER`
- `CI_REGISTRY_PASSWORD`
- `CI_REGISTRY_IMAGE`
---
 .gitlab-ci.yml        | 59 +++++++++++++++++++++++++++++++++++++++++++
 templates/Docker.yaml | 50 ++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0f3ce46..caca7be 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -26,3 +26,62 @@ build-docker:
   extends:
     - .docker-matrix
     - .build-docker-image
+
+###############################################################################
+# `release` stage: `semantic-release`, `*-docker-tag`
+###############################################################################
+# Suffix all jobs to avoid conflict with other jobs names
+.tag-docker:
+  extends:
+    - .docker-matrix
+    - .tag-docker-image
+
+## dev images
+tag dev:
+  extends:
+    - .tag-docker
+    - .on-dev
+  variables:
+    IMAGE_TAG: dev
+
+## testing images
+tag testing:
+  extends:
+    - .tag-docker
+    - .on-testing
+  variables:
+    IMAGE_TAG: testing
+
+## stable images
+.tag-stable:
+  extends: .tag-docker
+  variables:
+    SOURCE_TAG: testing
+
+tag release:
+  extends: .tag-stable
+
+tag major:
+  extends: .tag-stable
+  before_script:
+    - export RELEASE_PREFIX=${RELEASE_PREFIX:-release/}
+    - export RELEASE=${CI_COMMIT_TAG#${RELEASE_PREFIX}}
+    - export IMAGE_TAG=${RELEASE%%.*}
+
+tag minor:
+  extends:
+    - .tag-stable
+  before_script:
+    - export RELEASE_PREFIX=${RELEASE_PREFIX:-release/}
+    - export RELEASE=${CI_COMMIT_TAG#${RELEASE_PREFIX}}
+    - export IMAGE_TAG=${RELEASE%.${RELEASE##*.}}
+
+tag stable:
+  extends: .tag-stable
+  variables:
+    IMAGE_TAG: stable
+
+tag latest:
+  extends: .tag-stable
+  variables:
+    IMAGE_TAG: latest
diff --git a/templates/Docker.yaml b/templates/Docker.yaml
index e4dd722..e6441f2 100644
--- a/templates/Docker.yaml
+++ b/templates/Docker.yaml
@@ -52,3 +52,53 @@
     - mkdir -p /kaniko/.docker
     - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
     - /kaniko/executor --context ${CI_PROJECT_DIR} --dockerfile $CI_PROJECT_DIR/${DOCKERFILE} --destination ${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:${IMAGE_TAG}
+
+# Define `.tag-docker-image` template used by `*-docker-tag` jobs
+# It tag the `${IMAGE_NAME}:${SOURCE_TAG}` with the tag `${IMAGE_TAG}`
+#
+# USAGE
+# =====
+#
+# foo-docker-tag-devel:
+#   extends: .tag-docker-image
+#   variables:
+#     IMAGE_TAG: 'devel'
+#
+# REQUIREMENTS
+# ============
+#
+# - A `release` stage must be present in your pipeline or it must be
+#   overriden by the extending job to feet your need.
+# - The `.not-on-stable` rules template
+#
+# OPTIONAL VARIABLES
+# ==================
+#
+# - `IMAGE_NAME`: defaults to `${CI_JOB_NAME}` with any suffix `-docker-tag*` removed
+# - `SOURCE_TAG`: source image tag to retag, defaults to `git-${CI_COMMIT_SHORT_SHA}`
+# - `IMAGE_TAG`: image tag, defaults to `${CI_COMMIT_TAG}` with prefix `RELEASE_PREFIX` removed
+# - `RELEASE_PREFIX`: prefix of the `RELEASE`, defaults to `release/`
+#
+# USED CI VARIABLES
+# =================
+#
+# - `CI_REGISTRY`
+# - `CI_REGISTRY_USER`
+# - `CI_REGISTRY_PASSWORD`
+# - `CI_REGISTRY_IMAGE`
+#
+.tag-docker-image:
+  stage: release
+  extends: .on-release-tag
+  image:
+    name: gcr.io/go-containerregistry/crane:debug
+    entrypoint: [""]
+  variables:
+    GIT_STRATEGY: none
+  script:
+    - export IMAGE_NAME=${IMAGE_NAME:-${CI_JOB_NAME%-docker-tag*}}
+    - export SOURCE_TAG=${SOURCE_TAG:-git-${CI_COMMIT_SHORT_SHA}}
+    - export RELEASE_PREFIX=${RELEASE_PREFIX:-release/}
+    - export IMAGE_TAG=${IMAGE_TAG:-${CI_COMMIT_TAG#${RELEASE_PREFIX}}}
+    - crane auth login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
+    - crane tag ${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:${SOURCE_TAG} ${IMAGE_TAG}
-- 
GitLab