diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d14b642ac33b387cc98f64ca041a85a4bb7b6a68..8a54de92fdd19f70113b44aa61c8f2358f3c484c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,98 @@ -# 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: + - job: py-lint + artifacts: false + 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: on_success + - if: '$CI_COMMIT_BRANCH =~ /dev|test|ci|pre|production/' + when: on_success + - 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: on_success + - if: '$CI_COMMIT_BRANCH =~ /dev|test|ci|pre|production/' + 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 new file mode 100644 index 0000000000000000000000000000000000000000..bab200e3dfd762b76ec71841de8970c29e7f5932 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,111 @@ +#!/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}" +SHORT_TAG="$CI_COMMIT_SHORT_SHA" +BRANCH="$CI_COMMIT_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 + +echo "🔍 Collecting build artifacts for commit $CI_COMMIT_SHORT_SHA ..." +cp *_${CI_COMMIT_SHORT_SHA}_* release_files/ 2>/dev/null || true + +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" + + 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) ..." + 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!"