From ff32c542690a05ea81dacc910fa5372b2552f743 Mon Sep 17 00:00:00 2001 From: "Ehsan.Asadi" Date: Tue, 30 Dec 2025 22:08:34 +0330 Subject: [PATCH] feat: smart base image check with docker pull MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use 'docker pull' to check if base exists - If exists: skip build (saves ~10 minutes) ✅ - If not exists: build automatically - Single stage that handles both check and build - No authentication issues (uses docker login) Behavior: ✓ Base exists → Skip (~30 seconds check + 3 min app) ✓ Base missing → Build base (~10 min) + app (~3 min) This is the REAL solution we wanted! --- .woodpecker.yml | 171 ++++++++++++++++++------------------------------ 1 file changed, 63 insertions(+), 108 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 65dbb81..a226c22 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,131 +1,71 @@ # Woodpecker CI/CD Pipeline - Peikarband Landing -# Application build pipeline with auto-build base image fallback +# Application build pipeline variables: - - &python_image 'python:3.11-slim' - &helm_image 'alpine/helm:latest' - - &base_image 'hub.peikarband.ir/peikarband/base:latest' when: - event: [push, pull_request, tag, manual] pipeline: # ============================================ - # Stage 1: Build Base Image (always - with cache) + # Stage 1: Check & Build Base (conditional) # ============================================ - check-base-image: + ensure-base-image: image: alpine:latest commands: - - apk add --no-cache curl + - apk add --no-cache curl docker - | - echo "Checking if base image exists..." - REGISTRY="hub.peikarband.ir" - REPO="peikarband/base" - TAG="latest" + echo "═══════════════════════════════════════" + echo " Checking Base Image" + echo "═══════════════════════════════════════" - if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ - "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then - echo "✓ Base image found: $REGISTRY/$REPO:$TAG" - echo "SKIP_BASE_BUILD=true" > /tmp/base_status - else - echo "⚠️ Base image not found - will build it" - echo "SKIP_BASE_BUILD=false" > /tmp/base_status + REGISTRY="hub.peikarband.ir" + BASE_REPO="peikarband/base" + BASE_TAG="latest" + + # Login to registry + echo "$HARBOR_PASSWORD" | docker login "$REGISTRY" -u "$HARBOR_USERNAME" --password-stdin + + # Try to pull base image + if docker pull "$REGISTRY/$BASE_REPO:$BASE_TAG" 2>/dev/null; then + echo "✅ Base image found in registry" + echo " Skipping base build (saves ~10 minutes)" + exit 0 fi + + echo "⚠️ Base image not found - building it now..." + echo "" + echo "═══════════════════════════════════════" + echo " Building Base Image" + echo "═══════════════════════════════════════" + + # Build base image + docker buildx create --use --name builder || docker buildx use builder + + docker buildx build \ + -f docker/Dockerfile.base \ + -t "$REGISTRY/$BASE_REPO:latest" \ + -t "$REGISTRY/$BASE_REPO:python3.11-node20" \ + --build-arg PYTHON_VERSION=3.11 \ + --build-arg NODE_VERSION=20 \ + --platform linux/amd64 \ + --push \ + . + + echo "✅ Base image built and pushed successfully" + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] - when: - event: [push, tag] - - build-base-image: - image: woodpeckerci/plugin-docker-buildx - settings: - registry: hub.peikarband.ir - repo: hub.peikarband.ir/peikarband/base - username: - from_secret: HARBOR_USERNAME - password: - from_secret: HARBOR_PASSWORD - - dockerfile: docker/Dockerfile.base - context: . - platforms: linux/amd64 - - tags: - - latest - - python3.11-node20 - - build_args: - - PYTHON_VERSION=3.11 - - NODE_VERSION=20 - - labels: - - org.opencontainers.image.created=${CI_PIPELINE_CREATED} - - org.opencontainers.image.source=${CI_REPO_LINK} - - org.opencontainers.image.title=Peikarband Base - - pull: true - provenance: false - push: true - - when: - event: [push, tag, manual] - # فقط در یکی از این موارد build می‌شود: - # 1. وقتی Dockerfile.base تغییر کند - # 2. وقتی در commit message بنویسید: [build-base] - # 3. وقتی manual trigger کنید - path: - include: - - docker/Dockerfile.base - - .woodpecker.yml - - # ============================================ - # Stage 2: Build Application Image - # ============================================ - - build-image: - image: woodpeckerci/plugin-docker-buildx - settings: - registry: hub.peikarband.ir - repo: hub.peikarband.ir/peikarband/landing - username: - from_secret: HARBOR_USERNAME - password: - from_secret: HARBOR_PASSWORD - - dockerfile: docker/Dockerfile - context: . - platforms: linux/amd64 - - build_args: - - BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest - - VERSION=${CI_COMMIT_SHA:0:8} - - BUILD_DATE=${CI_PIPELINE_CREATED} - - tags: - - ${CI_COMMIT_SHA:0:8} - - labels: - - org.opencontainers.image.created=${CI_PIPELINE_CREATED} - - org.opencontainers.image.source=${CI_REPO_LINK} - - org.opencontainers.image.url=${CI_REPO_LINK} - - org.opencontainers.image.revision=${CI_COMMIT_SHA} - - org.opencontainers.image.version=${CI_COMMIT_SHA:0:8} - - org.opencontainers.image.title=Peikarband Landing - - org.opencontainers.image.description=Peikarband hosting platform landing page - - pull: true - provenance: false - push: false - when: event: [push, tag] branch: [main, develop, feature/restructure-project] # ============================================ - # Stage 3: Push Application Image + # Stage 2: Build Application Image # ============================================ - push-image: + build-and-push-app: image: woodpeckerci/plugin-docker-buildx settings: registry: hub.peikarband.ir @@ -167,7 +107,7 @@ pipeline: branch: [main, develop, feature/restructure-project] # ============================================ - # Stage 4: Verify Push + # Stage 3: Verify Push # ============================================ verify-push: @@ -184,7 +124,12 @@ pipeline: if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then - echo "✓ Image verified: $REGISTRY/$REPO:$TAG" + echo "✅ Image verified: $REGISTRY/$REPO:$TAG" + echo "" + echo "Available tags:" + echo " - latest" + echo " - ${CI_COMMIT_SHA:0:8}" + echo " - ${CI_COMMIT_BRANCH}" else echo "❌ Failed to verify image push" exit 1 @@ -201,10 +146,15 @@ pipeline: notify-success: image: alpine:latest commands: - - echo "🎉 Pipeline completed successfully!" + - echo "════════════════════════════════════════" + - echo " 🎉 Pipeline Completed Successfully!" + - echo "════════════════════════════════════════" + - echo "" - echo "Branch:" "${CI_COMMIT_BRANCH}" - echo "Commit:" "${CI_COMMIT_SHA:0:8}" - echo "Image:" "hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}" + - echo "" + - echo "════════════════════════════════════════" when: event: [push, tag] status: success @@ -212,10 +162,15 @@ pipeline: notify-failure: image: alpine:latest commands: - - echo "❌ Pipeline failed!" + - echo "════════════════════════════════════════" + - echo " ❌ Pipeline Failed!" + - echo "════════════════════════════════════════" + - echo "" - echo "Branch:" "${CI_COMMIT_BRANCH}" - echo "Commit:" "${CI_COMMIT_SHA:0:8}" - - echo "Please check the logs above" + - echo "" + - echo "Please check the logs above for details" + - echo "════════════════════════════════════════" when: event: [push, tag] status: failure