From 5ad9bcabea6924030149e6127dd2af0414f8d6a5 Mon Sep 17 00:00:00 2001 From: Lee Chapman Date: Sun, 11 Jan 2026 01:42:50 -0800 Subject: [PATCH 1/3] ci: add release stage with GitLab CLI - Add release stage that runs on main branch - Release creates tags automatically (v0.$CI_PIPELINE_IID) - Publish stage runs on any git tag - Deploy stage runs on semantic version tags only - Uses registry.gitlab.com/gitlab-org/cli:latest for release job --- .gitlab-ci.yml | 217 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 194 insertions(+), 23 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 673ffaf..7ce9396 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,39 +1,210 @@ stages: - build + - docker + - release + - deploy variables: - HARBOR_REGISTRY: harbor.dataknife.net - HARBOR_PROJECT: library IMAGE_NAME: high-command-api + K8S_NAMESPACE: high-command + DEPLOYMENT_NAME: high-command-api -docker-build: +build: stage: build - image: docker:latest - services: - - docker:dind + image: harbor.dataknife.net/dockerhub/library/python:3.14-slim + script: + - apt-get update && apt-get install -y --no-install-recommends make git + - make build + artifacts: + paths: + - dist/ + - build/ + - *.egg-info/ + expire_in: 1 hour + rules: + - if: '$CI_COMMIT_BRANCH == "main"' + - if: '$CI_COMMIT_TAG' + tags: + - kubernetes + +publish: + stage: docker + image: + name: moby/buildkit:rootless + entrypoint: [""] + dependencies: + - build + script: + - | + # Use commit SHA if available, otherwise fall back to pipeline ID + IMAGE_TAG="${CI_COMMIT_SHORT_SHA:-$CI_PIPELINE_ID}" + + # Build and push images with BuildKit rootless (multiple outputs for multiple tags) + OUTPUT_FLAGS="--output type=image,name=$HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:latest,push=true" + OUTPUT_FLAGS="$OUTPUT_FLAGS --output type=image,name=$HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$IMAGE_TAG,push=true" + + # Add version tag if tag exists + if [ -n "$CI_COMMIT_TAG" ]; then + OUTPUT_FLAGS="$OUTPUT_FLAGS --output type=image,name=$HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$CI_COMMIT_TAG,push=true" + fi + + buildctl-daemonless.sh build \ + --frontend dockerfile.v0 \ + --local context=. \ + --local dockerfile=. \ + $OUTPUT_FLAGS + rules: + - if: '$CI_COMMIT_TAG' # Run on any git tag + tags: + - kubernetes + +release: + stage: release + image: registry.gitlab.com/gitlab-org/cli:latest + rules: + - if: $CI_COMMIT_TAG + when: never # Do not run this job when a tag is created manually + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch + script: + - | + echo "Creating release for commit $CI_COMMIT_SHORT_SHA" + echo "Release will create tag automatically" + release: # See https://docs.gitlab.com/ee/ci/yaml/#release for available properties + tag_name: 'v0.$CI_PIPELINE_IID' # The version is incremented per pipeline + description: 'Release v0.$CI_PIPELINE_IID' + ref: '$CI_COMMIT_SHA' # The tag is created from the pipeline SHA + tags: + - kubernetes + +deploy: + stage: deploy + image: harbor.dataknife.net/dockerhub/library/bitnami/kubectl:latest + dependencies: + - publish + variables: + KUBECONFIG: /tmp/kubeconfig before_script: - - echo "$HARBOR_PASSWORD" | docker login -u "$HARBOR_USERNAME" --password-stdin $HARBOR_REGISTRY + - | + # Write kubeconfig from GitLab variable + echo "$PRD_APPS_KUBECONFIG" | base64 -d > $KUBECONFIG + chmod 600 $KUBECONFIG + kubectl config use-context prd-apps || kubectl config get-contexts | head -5 script: - | - # Build image once - docker build -t $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:latest . + # Use semantic version tag if available, otherwise use commit SHA + if [ -n "$CI_COMMIT_TAG" ] && [[ "$CI_COMMIT_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + IMAGE_VERSION="$CI_COMMIT_TAG" + else + IMAGE_VERSION="${CI_COMMIT_SHORT_SHA:-$CI_PIPELINE_ID}" + fi - # Tag with commit SHA - docker tag $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:latest \ - $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA + FULL_IMAGE="$HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$IMAGE_VERSION" - # Push images - docker push $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:latest - docker push $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA + echo "Deploying $DEPLOYMENT_NAME to prd-apps cluster" + echo "Image: $FULL_IMAGE" + echo "Namespace: $K8S_NAMESPACE" - # Tag with version if tag exists - if [ -n "$CI_COMMIT_TAG" ]; then - docker tag $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:latest \ - $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$CI_COMMIT_TAG - docker push $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$CI_COMMIT_TAG + # Create namespace if it doesn't exist + kubectl create namespace $K8S_NAMESPACE --dry-run=client -o yaml | kubectl apply -f - + + # Determine current deployment color (blue or green) + CURRENT_COLOR=$(kubectl get deployment $DEPLOYMENT_NAME -n $K8S_NAMESPACE -o jsonpath='{.spec.template.metadata.labels.deployment-color}' 2>/dev/null || echo "blue") + + if [ "$CURRENT_COLOR" = "blue" ]; then + NEW_COLOR="green" + else + NEW_COLOR="blue" fi + + echo "Current deployment: $CURRENT_COLOR" + echo "New deployment: $NEW_COLOR" + + # Create green/blue deployment + kubectl apply -f - </dev/null | grep -q ${DEPLOYMENT_NAME}-${CURRENT_COLOR}; then + echo "Scaling down old deployment ${DEPLOYMENT_NAME}-${CURRENT_COLOR}..." + kubectl scale deployment ${DEPLOYMENT_NAME}-${CURRENT_COLOR} -n $K8S_NAMESPACE --replicas=0 + fi + + echo "✓ Deployment complete. ${DEPLOYMENT_NAME}-${NEW_COLOR} is now serving traffic." rules: - - if: '$CI_COMMIT_BRANCH == "main"' - - if: '$CI_COMMIT_TAG' + - if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/' # Only run this job when a semantic version tag is created tags: - - docker + - kubernetes From a4bcac2fb446119d1f82947c6e88f4acf9cd89fa Mon Sep 17 00:00:00 2001 From: Lee Chapman Date: Sun, 11 Jan 2026 10:25:57 -0800 Subject: [PATCH 2/3] fix: quote glob pattern in artifacts paths Fix YAML syntax error at line 22 by quoting the glob pattern *.egg-info/ to prevent YAML parser from interpreting * as an alias. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7ce9396..e618cfe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,7 @@ build: paths: - dist/ - build/ - - *.egg-info/ + - "*.egg-info/" expire_in: 1 hour rules: - if: '$CI_COMMIT_BRANCH == "main"' From 8aa5517b5d063f81a642d147dbf6c50e253254c6 Mon Sep 17 00:00:00 2001 From: Lee Chapman Date: Sun, 11 Jan 2026 10:52:13 -0800 Subject: [PATCH 3/3] fix: replace make build with python -m build The repository doesn't have a Makefile 'build' target, so 'make build' was failing. Replace with 'python -m build' which is the standard Python build command. Also replace 'make' package with 'build-essential' which provides the necessary build tools for Python packages. --- .gitlab-ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e618cfe..096118d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,8 +13,9 @@ build: stage: build image: harbor.dataknife.net/dockerhub/library/python:3.14-slim script: - - apt-get update && apt-get install -y --no-install-recommends make git - - make build + - apt-get update && apt-get install -y --no-install-recommends git build-essential + - pip install --upgrade pip build + - python -m build artifacts: paths: - dist/