222 lines
8.6 KiB
YAML
222 lines
8.6 KiB
YAML
# -----------------------------------------------------------------------------
|
|
# Original/Ref: https://git.price-hk.com/boilerplate-samples-projects/basic-docker-ci
|
|
# -----------------------------------------------------------------------------
|
|
# Generic Gitlab CI for docker project for building and uploading img to Nexus and QCloud
|
|
#
|
|
# This file requires the following variables:
|
|
# See Also: https://git.price-hk.com/admin/application_settings/ci_cd
|
|
# (Requried:)
|
|
# - NAMESPACE: [price|myprice] # It will be prepended to the DOCKER_IMAGE_NAME
|
|
# - PRICE_DOCKER_REPO_HOST # Nexus Repo Host
|
|
# - PRICE_DOCKER_REPO_USER # Nexus Repo User
|
|
# - PRICE_DOCKER_REPO_PWD # Nexus Repo Password
|
|
# - QCLOUD_TKE_TCR_HOST # QCloud TKE TCR (Registry) Host
|
|
# - QCLOUD_TKE_TCR_USER # QCloud TKE TCR (Registry) User
|
|
# - QCLOUD_TKE_TCR_PWD # QCloud TKE TCR (Registry) Password
|
|
#
|
|
# (Optional:)
|
|
# - DOCKER_IMAGE_NAME # It can be overrided if specified
|
|
#
|
|
# Triggering the Pipeline:
|
|
# The pipeline can be triggered by git tagging or running the pipeline manually with CI_COMMIT_TAG var.
|
|
#
|
|
# The pattern of Git tag or CI_COMMIT_TAG should be either:
|
|
# - Image for release purpose => release-{Docker Image Tag}
|
|
# - Docker Image Tag pattern: {semantic version style: x.y.z}[-{Optional text}]
|
|
# - Image for Non-release/Development purpose => dev-{Docker Image Tag}
|
|
# - Docker Image Tag pattern: any text follow docker tag requirements
|
|
#
|
|
|
|
stages:
|
|
- trigger
|
|
- docker-build-push-nexus
|
|
- push-qcloud
|
|
|
|
default:
|
|
interruptible: false
|
|
tags:
|
|
# Note: There may be a performance issue while using dind
|
|
# so that we switch to docker executor.
|
|
- docker-executor
|
|
artifacts:
|
|
reports:
|
|
dotenv: build.env
|
|
# after_script:
|
|
# # Only for debug propose, comment for production
|
|
# - env
|
|
|
|
variables:
|
|
NAMESPACE: price
|
|
DOCKER_IMAGE_NAME: "${NAMESPACE}/${CI_PROJECT_PATH_SLUG}"
|
|
DOCKERFILE_NAME: "Dockerfile"
|
|
|
|
.release_tag_rules:
|
|
rules:
|
|
# Force git-tag trigger only, run-pipeline not support (recommended)
|
|
- if: '$CI_COMMIT_TAG =~ /^release-\d+(\.\d+){0,2}\.\d+(-([a-zA-Z0-9\.\-\_]+)*[a-zA-Z0-9])?$/ && $CI_PIPELINE_SOURCE == "push"'
|
|
# Can use git-tag trigger and run-pipeline (for ci-development only)
|
|
# - if: '$CI_COMMIT_TAG =~ /^release-\d+(\.\d+){0,2}\.\d+(-([a-zA-Z0-9\.\-\_]+)*[a-zA-Z0-9])?$/'
|
|
when: on_success
|
|
|
|
.dev_tag_rules:
|
|
rules:
|
|
# Force git-tag trigger only, run-pipeline not support (recommended)
|
|
- if: '$CI_COMMIT_TAG =~ /^dev-[a-zA-Z0-9\.\-\_]+[a-zA-Z0-9]$/ && $CI_PIPELINE_SOURCE == "push"'
|
|
# Can use git-tag trigger and run-pipeline (for ci-development only)
|
|
# - if: '$CI_COMMIT_TAG =~ /^dev-[a-zA-Z0-9\.\-\_]+[a-zA-Z0-9]$/'
|
|
when: on_success
|
|
|
|
.tag_trigger_save_build_env:
|
|
script:
|
|
# Send to next stages
|
|
- |
|
|
echo "IS_RELEASE_IMAGE=${IS_RELEASE_IMAGE}" >> build.env
|
|
echo "DOCKERFILE_NAME=${DOCKERFILE_NAME}" >> build.env
|
|
echo "DOCKER_IMAGE_TAG=${DOCKER_IMAGE_TAG}" >> build.env
|
|
|
|
.check_get_docker_image_tag:
|
|
script:
|
|
- |
|
|
# Extract the docker image tag from commit tag
|
|
if [ -z $CI_COMMIT_TAG ]; then
|
|
echo "[!] ERROR, missing CI_COMMIT_TAG"
|
|
exit 1
|
|
else
|
|
DOCKER_IMAGE_TAG=$(echo "$CI_COMMIT_TAG" | sed -re 's/^[^-]+-(.*)$/\1/g')
|
|
fi
|
|
|
|
# ---------- JOB ---------
|
|
Tag Trigger for Release:
|
|
stage: trigger
|
|
rules:
|
|
- !reference [.release_tag_rules, rules]
|
|
|
|
script:
|
|
- IS_RELEASE_IMAGE=true
|
|
- !reference [.check_get_docker_image_tag, script]
|
|
- !reference [.tag_trigger_save_build_env, script]
|
|
|
|
# ---------- JOB ---------
|
|
Tag or Manual Trigger for Dev Build:
|
|
stage: trigger
|
|
rules:
|
|
- !reference [.dev_tag_rules, rules]
|
|
|
|
script:
|
|
- IS_RELEASE_IMAGE=false
|
|
- !reference [.check_get_docker_image_tag, script]
|
|
# Append 'dev-' to the docekr tag for the non-release image
|
|
- DOCKER_IMAGE_TAG="dev-${DOCKER_IMAGE_TAG}"
|
|
# Check if Dockerfile.dev exist, then use it for docker build
|
|
# TODO: consider to use filename suffix for other image tag like architecture suffix
|
|
- |
|
|
if [ -f "${DOCKERFILE_NAME}.dev" ]; then
|
|
DOCKERFILE_NAME=${DOCKERFILE_NAME}.dev
|
|
fi
|
|
- !reference [.tag_trigger_save_build_env, script]
|
|
|
|
# ---------- JOB ---------
|
|
Docker Build and Push to Nexus:
|
|
stage: docker-build-push-nexus
|
|
|
|
rules:
|
|
- !reference [.release_tag_rules, rules]
|
|
- !reference [.dev_tag_rules, rules]
|
|
|
|
# Not using 'needs' properly. The following settings cannot restrict only
|
|
# running from below jobs. It can be triggered if the rule passes anyway.
|
|
# Therefore, we still need to govern the trigger by rules.
|
|
# The use of 'needs' is for better flow declaration, for DAG.
|
|
needs:
|
|
- job: Tag or Manual Trigger for Dev Build
|
|
optional: true
|
|
- job: Tag Trigger for Release
|
|
optional: true
|
|
|
|
before_script:
|
|
# Login to Price Registry - Nexus
|
|
- echo "${PRICE_DOCKER_REPO_PWD}" | docker login -u "${PRICE_DOCKER_REPO_USER}" --password-stdin ${PRICE_DOCKER_REPO_HOST}
|
|
# pull latest image for cache-from, if any
|
|
- docker pull ${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME}:latest || true
|
|
|
|
script:
|
|
# ---------- PRE-BUILD ----------
|
|
# Modify the source code version string so that the VERSION_STRING will be added to the application
|
|
# - |
|
|
# sed -i -e "s/const BuildVersion string = .*$/const BuildVersion string = \"${VERSION_STRING}\"/g" cmd/priceuid2server/main.go
|
|
- DOCKER_IMAGE_NAME_WITH_TAG=${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}
|
|
# ---------- BUILD DOCKER IMAGE ----------
|
|
- |
|
|
echo "Using Dockerfile: ${DOCKERFILE_NAME}"
|
|
- >
|
|
docker build
|
|
-f "${DOCKERFILE_NAME}"
|
|
--pull
|
|
--tag ${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG}
|
|
--cache-from ${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME}:latest
|
|
--build-arg org_label_schema_name="${DOCKER_IMAGE_NAME}"
|
|
--build-arg org_label_schema_version="${DOCKER_IMAGE_TAG}"
|
|
--build-arg org_label_schema_description="${CI_PROJECT_TITLE}"
|
|
--build-arg org_label_schema_build_date="${CI_PIPELINE_CREATED_AT}"
|
|
--build-arg org_label_schema_vcs_ref="${CI_COMMIT_SHA}"
|
|
--build-arg org_label_schema_vcs_url="${CI_PROJECT_URL}"
|
|
--build-arg maintainer="${GITLAB_USER_LOGIN}<${GITLAB_USER_EMAIL}>"
|
|
--build-arg APP_VERSION="${DOCKER_IMAGE_TAG}"
|
|
.
|
|
# ---------- PUBLISH DOCKER IMAGE TO NEXUS REGISTRY ----------
|
|
# Push local image to Price's registry
|
|
- docker push ${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG}
|
|
# Tag latest image if it is an image for release
|
|
- |
|
|
if [ "$IS_RELEASE_IMAGE" = true ]; then
|
|
docker tag \
|
|
${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG} \
|
|
${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME}:latest
|
|
docker push ${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME}:latest
|
|
fi
|
|
# Artifacts to next stage
|
|
- !reference [.tag_trigger_save_build_env, script]
|
|
|
|
# ---------- JOB ---------
|
|
Push Image to QCloud:
|
|
stage: push-qcloud
|
|
|
|
rules:
|
|
- !reference [.release_tag_rules, rules]
|
|
- !reference [.dev_tag_rules, rules]
|
|
|
|
needs:
|
|
- Docker Build and Push to Nexus
|
|
|
|
before_script:
|
|
# Login to Price Registry - Nexus
|
|
- echo "${PRICE_DOCKER_REPO_PWD}" | docker login -u "${PRICE_DOCKER_REPO_USER}" --password-stdin ${PRICE_DOCKER_REPO_HOST}
|
|
# Login to QCLOUD TCR (Registry)
|
|
- echo "${QCLOUD_TKE_TCR_PWD}" | docker login -u "${QCLOUD_TKE_TCR_USER}" --password-stdin ${QCLOUD_TKE_TCR_HOST}
|
|
# Because we have no guarantee that this job will be picked up by the same runner
|
|
# that built the image in the previous step, we pull it again locally
|
|
- docker pull ${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}
|
|
|
|
script:
|
|
# ---------- PRE-PUBLISH ----------
|
|
- DOCKER_IMAGE_NAME_WITH_TAG=${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG}
|
|
# ---------- PUBLISH DOCKER IMAGE TO QCLOUD REGISTRY ----------
|
|
- |
|
|
docker tag \
|
|
${PRICE_DOCKER_REPO_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG} \
|
|
${QCLOUD_TKE_TCR_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG}
|
|
docker push ${QCLOUD_TKE_TCR_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG}
|
|
# Tag latest image if it is an image for release
|
|
- |
|
|
if [ "$IS_RELEASE_IMAGE" = true ]; then
|
|
docker tag \
|
|
${QCLOUD_TKE_TCR_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG} \
|
|
${QCLOUD_TKE_TCR_HOST}/${DOCKER_IMAGE_NAME}:latest
|
|
docker push ${QCLOUD_TKE_TCR_HOST}/${DOCKER_IMAGE_NAME}:latest
|
|
docker rmi ${QCLOUD_TKE_TCR_HOST}/${DOCKER_IMAGE_NAME}:latest
|
|
fi
|
|
# Clean up
|
|
- docker rmi ${QCLOUD_TKE_TCR_HOST}/${DOCKER_IMAGE_NAME_WITH_TAG}
|
|
# Artifacts to next stage
|
|
- !reference [.tag_trigger_save_build_env, script]
|