From 6de9a302ff6dc5e327c378b4a82c2f5218abfe82 Mon Sep 17 00:00:00 2001 From: Watchtek Date: Mon, 25 Aug 2025 00:27:52 +0900 Subject: [PATCH 1/2] Add gitlab CI/CD --- .gitlab-ci.yml | 93 ++++++++++++++++++++++++++++++++++++++- scripts/release.sh | 107 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 scripts/release.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d14b642..79c69ac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,96 @@ -# https://to-be-continuous.biblio19.dev/kicker/ +# https://to-be-continuous.gitlab.io/kicker/ # included templates include: + # Gitleaks template + - component: "$CI_SERVER_FQDN/to-be-continuous/gitleaks/gitlab-ci-gitleaks@2.8" # Python template - component: "$CI_SERVER_FQDN/to-be-continuous/python/gitlab-ci-python@7.11" inputs: - pylint-enabled: true \ No newline at end of file + pylint-enabled: true + +# your pipeline stages +stages: + - build + - test + - package-build + - package-test + - infra + - deploy + - acceptance + - publish + - infra-prod + - production + +variables: + TZ: "Asia/Seoul" + BINARY_NAME: "load_check" # ✅ set only once here + +.default_build_template: &build_template + stage: package-build + needs: ["py-lint"] + script: + - echo "Creating artifact for $TARGET_OS" + - pip install -r requirements.txt + - pyinstaller --onefile ${BINARY_NAME}.py + - export TS=$(date +%Y-%m-%d_%H%M) + - | + if [ "$TARGET_OS" = "windows" ]; then + mv dist/$DIST_FILE "${BINARY_NAME}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHORT_SHA}_${TS}_${TARGET_OS}_amd64.exe" + else + mv dist/$DIST_FILE "${BINARY_NAME}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHORT_SHA}_${TS}_${TARGET_OS}_amd64" + fi + artifacts: + paths: + - "${BINARY_NAME}_*" + expire_in: 1 week + rules: + - if: '$CI_COMMIT_TAG' + when: never + - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' + when: always + - if: '$CI_COMMIT_BRANCH =~ /dev|test|ci|pre|production/' + when: always + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + when: never + - when: manual + +windows_bin: + <<: *build_template + image: + name: batonogov/pyinstaller-windows:latest + entrypoint: [''] + variables: + TARGET_OS: "windows" + DIST_FILE: "${BINARY_NAME}.exe" + +linux_slim_bin: + <<: *build_template + image: + name: batonogov/pyinstaller-linux:latest-slim + entrypoint: [''] + variables: + TARGET_OS: "linux" + DIST_FILE: "${BINARY_NAME}" + +release_job: + stage: publish + image: registry.gitlab.com/gitlab-org/cli + needs: + - job: windows_bin + artifacts: true + - job: linux_slim_bin + artifacts: true + before_script: + - apk add --no-cache curl + script: + - sh scripts/release.sh + rules: + - if: '$CI_COMMIT_TAG' + when: never + - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' + when: always + - if: '$CI_COMMIT_BRANCH =~ /dev|test|ci|pre|production/' + when: always + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + when: never + - when: manual \ No newline at end of file diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100644 index 0000000..98c0afe --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,107 @@ +#!/bin/sh +set -e + +echo "=== 🚀 GitLab Release Script with Package Registry ===" + +# --- Auth setup --- +if [ -n "$GITLAB_TOKEN" ]; then + echo "🔑 Using GITLAB_TOKEN for authentication" +else + echo "❌ GITLAB_TOKEN is required for Release upload (via glab)" + exit 1 +fi + +# GitLab instance +export GITLAB_URI="${CI_SERVER_URL:-https://gitlab.com}" +export GITLAB_HOST="${CI_SERVER_HOST:-gitlab.com}" + +# --- Tags: one for SHA (immutable), one for branch (rolling) --- +SHA_TAG="ci-${CI_COMMIT_SHORT_SHA}" +BRANCH_TAG="${CI_COMMIT_REF_NAME}" +SHORT_TAG="$CI_COMMIT_SHORT_SHA" +BRANCH="$CI_COMMIT_BRANCH" + +echo "📦 Publishing Release for $CI_PROJECT_PATH @ $SHORT_TAG ($BRANCH)" + +# --- Collect build artifacts --- +mkdir -p release_files + +# Copy only artifacts that include the commit SHA +echo "🔍 Collecting build artifacts for commit $CI_COMMIT_SHORT_SHA ..." +cp *_${CI_COMMIT_SHORT_SHA}_* release_files/ 2>/dev/null || true + +# Fail if nothing copied +if [ -z "$(ls -A release_files)" ]; then + echo "❌ No artifacts found matching pattern '*_${CI_COMMIT_SHORT_SHA}_*'" + exit 1 +fi + +echo "📂 Artifacts in release_files/:" +ls -lh release_files/ + +# --- Upload to Package Registry --- +upload_and_add_json () { + file="$1" + base_label="$2" + + # full label includes branch + short sha + label="$base_label ($BRANCH) ($SHORT_TAG)" + + url="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/load-check/${BRANCH_TAG}/$(basename "$file")" + + echo "⬆️ Uploading $file to Package Registry ($BRANCH_TAG) ..." + curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \ + --upload-file "$file" "$url" + + if [ "$ASSETS" != "[" ]; then + ASSETS="$ASSETS," + fi + ASSETS="$ASSETS {\"name\":\"$label\",\"url\":\"$url\",\"link_type\":\"other\"}" +} + +# --- Upload artifacts + checksums --- +ASSETS="[" + +for f in release_files/*; do + case "$f" in + *windows_amd64.exe) + sha_file="${f}.sha256" + sha256sum "$f" > "$sha_file" + + upload_and_add_json "$f" "Windows binary" + upload_and_add_json "$sha_file" "Windows binary checksum" + ;; + *linux_amd64) + sha_file="${f}.sha256" + sha256sum "$f" > "$sha_file" + + upload_and_add_json "$f" "Linux binary" + upload_and_add_json "$sha_file" "Linux binary checksum" + ;; + esac +done + +ASSETS="$ASSETS]" + +# --- Immutable release by commit SHA --- +echo "📝 Creating immutable release $SHA_TAG ..." +glab release create "$SHA_TAG" \ + -R "https://$CI_SERVER_HOST/$CI_PROJECT_PATH" \ + --ref "$CI_COMMIT_SHA" \ + --name "Release $SHA_TAG" \ + --notes "Binaries built from branch $BRANCH @ $SHORT_TAG" \ + --assets-links="$ASSETS" || echo "⚠️ Release $SHA_TAG already exists, skipping." + +# --- Rolling release by branch (always update) --- +echo "📝 Updating rolling release $BRANCH_TAG ..." +glab release delete "$BRANCH_TAG" \ + -R "https://$CI_SERVER_HOST/$CI_PROJECT_PATH" -y || true + +glab release create "$BRANCH_TAG" \ + -R "https://$CI_SERVER_HOST/$CI_PROJECT_PATH" \ + --ref "$CI_COMMIT_SHA" \ + --name "Release $BRANCH_TAG" \ + --notes "Binaries built from branch $BRANCH @ $SHORT_TAG" \ + --assets-links="$ASSETS" + +echo "✅ Release process finished!" -- GitLab From 43f1512ef83fd284c3a7f9779ef3ffd32f04a7fc Mon Sep 17 00:00:00 2001 From: Watchtek Date: Mon, 25 Aug 2025 01:06:59 +0900 Subject: [PATCH 2/2] Prevent tag name as default branch name --- .gitlab-ci.yml | 12 +++++++----- scripts/release.sh | 14 +++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 79c69ac..8a54de9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,7 +27,9 @@ variables: .default_build_template: &build_template stage: package-build - needs: ["py-lint"] + needs: + - job: py-lint + artifacts: false script: - echo "Creating artifact for $TARGET_OS" - pip install -r requirements.txt @@ -47,9 +49,9 @@ variables: - if: '$CI_COMMIT_TAG' when: never - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' - when: always + when: on_success - if: '$CI_COMMIT_BRANCH =~ /dev|test|ci|pre|production/' - when: always + when: on_success - if: $CI_PIPELINE_SOURCE == 'merge_request_event' when: never - when: manual @@ -88,9 +90,9 @@ release_job: - if: '$CI_COMMIT_TAG' when: never - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' - when: always + when: on_success - if: '$CI_COMMIT_BRANCH =~ /dev|test|ci|pre|production/' - when: always + when: on_success - if: $CI_PIPELINE_SOURCE == 'merge_request_event' when: never - when: manual \ No newline at end of file diff --git a/scripts/release.sh b/scripts/release.sh index 98c0afe..bab200e 100644 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -17,20 +17,24 @@ export GITLAB_HOST="${CI_SERVER_HOST:-gitlab.com}" # --- Tags: one for SHA (immutable), one for branch (rolling) --- SHA_TAG="ci-${CI_COMMIT_SHORT_SHA}" -BRANCH_TAG="${CI_COMMIT_REF_NAME}" SHORT_TAG="$CI_COMMIT_SHORT_SHA" BRANCH="$CI_COMMIT_BRANCH" -echo "📦 Publishing Release for $CI_PROJECT_PATH @ $SHORT_TAG ($BRANCH)" +# ✅ Map default branch (main/master) to "latest" +if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then + BRANCH_TAG="latest" +else + BRANCH_TAG="${CI_COMMIT_REF_NAME}" +fi + +echo "📦 Publishing Release for $CI_PROJECT_PATH @ $SHORT_TAG ($BRANCH → $BRANCH_TAG)" # --- Collect build artifacts --- mkdir -p release_files -# Copy only artifacts that include the commit SHA echo "🔍 Collecting build artifacts for commit $CI_COMMIT_SHORT_SHA ..." cp *_${CI_COMMIT_SHORT_SHA}_* release_files/ 2>/dev/null || true -# Fail if nothing copied if [ -z "$(ls -A release_files)" ]; then echo "❌ No artifacts found matching pattern '*_${CI_COMMIT_SHORT_SHA}_*'" exit 1 @@ -44,9 +48,9 @@ upload_and_add_json () { file="$1" base_label="$2" - # full label includes branch + short sha label="$base_label ($BRANCH) ($SHORT_TAG)" + # ✅ Package registry also uses $BRANCH_TAG (latest for main/master) url="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/load-check/${BRANCH_TAG}/$(basename "$file")" echo "⬆️ Uploading $file to Package Registry ($BRANCH_TAG) ..." -- GitLab