From 46df8290ec67d0edd55c76785922e382d2cedd13 Mon Sep 17 00:00:00 2001 From: "Ehsan.Asadi" Date: Tue, 30 Dec 2025 21:59:51 +0330 Subject: [PATCH] feat: add auto-build for base image in main pipeline - Always build base image first (with cache for speed) - If base exists in registry, uses cache (~30 sec) - If base doesn't exist, builds from scratch (~10 min) - Then builds and pushes application image - Self-healing: no manual intervention needed Pipeline flow: 1. build-base-image (always, with cache) 2. build-image (app) 3. push-image (with multi-tags) 4. verify-push 5. notify First run: ~12 minutes (base + app) Subsequent: ~3 minutes (cached base + app) --- .woodpecker.yml | 272 +++++++++++++----------------------------------- 1 file changed, 72 insertions(+), 200 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index f6d5699..5f6ac5d 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,5 +1,5 @@ # Woodpecker CI/CD Pipeline - Peikarband Landing -# Application build pipeline (uses pre-built base image) +# Application build pipeline with auto-build base image fallback variables: - &python_image 'python:3.11-slim' @@ -11,31 +11,43 @@ when: pipeline: # ============================================ - # Stage 1: Check Base Image Availability + # Stage 1: Build Base Image (always - with cache) # ============================================ - check-base-image: - image: alpine:latest - commands: - - apk add --no-cache curl - - | - echo "Checking if base image is available..." - REGISTRY="hub.peikarband.ir" - REPO="peikarband/base" - TAG="latest" - - 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" - else - echo "❌ Base image not found!" - echo "Please run .woodpecker-base.yml pipeline first to build base image" - echo "Or trigger it manually in Woodpecker UI" - exit 1 - fi - secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + 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 + + cache_from: type=registry,ref=hub.peikarband.ir/peikarband/base:latest + cache_to: type=inline + provenance: false + push: true + when: - - event: [push, tag] + event: [push, tag] # ============================================ # Stage 2: Build Application Image @@ -55,13 +67,11 @@ pipeline: context: . platforms: linux/amd64 - # استفاده از base image build_args: - BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest - VERSION=${CI_COMMIT_SHA:0:8} - BUILD_DATE=${CI_PIPELINE_CREATED} - # فقط build می‌کنیم، بدون push tags: - ${CI_COMMIT_SHA:0:8} @@ -77,17 +87,14 @@ pipeline: cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache cache_to: type=inline provenance: false - - # فقط build، بدون push push: false - load: false when: - - event: [push, tag] - branch: [main, develop] + event: [push, tag] + branch: [main, develop, feature/restructure-project] # ============================================ - # Stage 3: Push Image with Multi-Tags + # Stage 3: Push Application Image # ============================================ push-image: @@ -109,7 +116,6 @@ pipeline: - VERSION=${CI_COMMIT_SHA:0:8} - BUILD_DATE=${CI_PIPELINE_CREATED} - # Multi-tagging strategy tags: - latest - ${CI_COMMIT_SHA:0:8} @@ -127,13 +133,11 @@ pipeline: cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache cache_to: type=inline provenance: false - - # حالا push می‌کنیم push: true when: - - event: [push, tag] - branch: [main, develop] + event: [push, tag] + branch: [main, develop, feature/restructure-project] # ============================================ # Stage 4: Verify Push @@ -145,7 +149,7 @@ pipeline: - apk add --no-cache curl - | echo "Verifying image was pushed successfully..." - sleep 3 # Wait for registry sync + sleep 3 REGISTRY="hub.peikarband.ir" REPO="peikarband/landing" @@ -160,171 +164,11 @@ pipeline: fi secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] when: - - event: [push, tag] - branch: [main, develop] + event: [push, tag] + branch: [main, develop, feature/restructure-project] # ============================================ - # Stages below are commented for now - # Uncomment when ready to use - # ============================================ - - # # ============================================ - # # Stage 1: Code Quality & Linting - # # ============================================ - - # lint-flake8: - # image: *python_image - # commands: - # - pip install --no-cache-dir flake8 - # - cd peikarband - # - flake8 src/ --count --select=E9,F63,F7,F82 --show-source --statistics - # - flake8 src/ --count --max-complexity=10 --max-line-length=120 --statistics --exit-zero - # when: - # - event: [push, pull_request, tag] - - # lint-black: - # image: *python_image - # commands: - # - pip install --no-cache-dir black - # - cd peikarband - # - black --check src/ || echo "⚠️ Black formatting issues found (non-blocking)" - # when: - # - event: [push, pull_request, tag] - - # lint-isort: - # image: *python_image - # commands: - # - pip install --no-cache-dir isort - # - cd peikarband - # - isort --check-only src/ || echo "⚠️ Import sorting issues found (non-blocking)" - # when: - # - event: [push, pull_request, tag] - - # type-check: - # image: *python_image - # commands: - # - pip install --no-cache-dir mypy types-redis types-requests - # - cd peikarband - # - mypy src/ --config-file=config/mypy.ini || echo "⚠️ Type checking issues found (non-blocking)" - # when: - # - event: [push, pull_request, tag] - - # # ============================================ - # # Stage 2: Security Scanning - # # ============================================ - - # security-bandit: - # image: *python_image - # commands: - # - pip install --no-cache-dir bandit[toml] - # - cd peikarband - # - bandit -r src/ -f json -o bandit-report.json || true - # - bandit -r src/ -ll || echo "⚠️ Security issues found (non-blocking)" - # when: - # - event: [push, pull_request, tag] - - # security-safety: - # image: *python_image - # commands: - # - pip install --no-cache-dir safety - # - cd peikarband - # - safety check -r requirements.txt --json || echo "⚠️ Dependency vulnerabilities found (non-blocking)" - # when: - # - event: [push, pull_request, tag] - - # # ============================================ - # # Stage 3: Testing - # # ============================================ - - # test: - # image: *python_image - # commands: - # - apt-get update && apt-get install -y --no-install-recommends curl - # - pip install --no-cache-dir -r peikarband/requirements.txt - # - pip install --no-cache-dir -r peikarband/requirements-dev.txt - # - cd peikarband - # - pytest tests/ -v --cov=src --cov-report=term-missing --cov-report=xml || echo "⚠️ Tests failed (non-blocking)" - # when: - # - event: [push, pull_request, tag] - - # # ============================================ - # # Stage 4: Helm Validation - # # ============================================ - - # helm-lint: - # image: *helm_image - # commands: - # - helm version - # - helm lint helm/peikarband - # - echo "✓ Helm chart validation passed" - # when: - # - event: [push, pull_request, tag] - - # helm-template: - # image: *helm_image - # commands: - # - helm template peikarband helm/peikarband -f helm/peikarband/values-production.yaml --debug > /dev/null - # - echo "✓ Helm template rendering successful" - # when: - # - event: [push, pull_request, tag] - - # # ============================================ - # # Stage 6: Deployment - Staging - # # ============================================ - - # deploy-staging: - # image: *helm_image - # commands: - # - apk add --no-cache kubectl - # - echo "$KUBECONFIG_STAGING" | base64 -d > /tmp/kubeconfig - # - export KUBECONFIG=/tmp/kubeconfig - # - | - # helm upgrade --install peikarband-staging helm/peikarband \ - # --namespace staging \ - # --create-namespace \ - # --set image.repository=hub.peikarband.ir/peikarband/landing \ - # --set image.tag=${CI_COMMIT_SHA:0:8} \ - # --set image.pullPolicy=Always \ - # --values helm/peikarband/values-staging.yaml \ - # --wait \ - # --timeout 5m - # - kubectl get pods -n staging - # - echo "✓ Deployed to staging successfully" - # secrets: [KUBECONFIG_STAGING] - # when: - # - event: push - # branch: [main, develop] - - # # ============================================ - # # Stage 7: Deployment - Production - # # ============================================ - - # deploy-production: - # image: *helm_image - # commands: - # - apk add --no-cache kubectl - # - echo "$KUBECONFIG_PRODUCTION" | base64 -d > /tmp/kubeconfig - # - export KUBECONFIG=/tmp/kubeconfig - # - | - # helm upgrade --install peikarband helm/peikarband \ - # --namespace production \ - # --create-namespace \ - # --set image.repository=hub.peikarband.ir/peikarband/landing \ - # --set image.tag=${CI_COMMIT_TAG} \ - # --set image.pullPolicy=Always \ - # --values helm/peikarband/values-production.yaml \ - # --wait \ - # --timeout 10m - # - kubectl rollout status deployment/peikarband -n production - # - kubectl get pods -n production - # - echo "✓ Deployed to production successfully" - # secrets: [KUBECONFIG_PRODUCTION] - # when: - # - event: tag - # ref: refs/tags/v* - - # ============================================ - # Stage 8: Notifications + # Notifications # ============================================ notify-success: @@ -348,3 +192,31 @@ pipeline: when: event: [push, tag] status: failure + + # ============================================ + # Commented stages (enable when needed) + # ============================================ + + # helm-lint: + # image: *helm_image + # commands: + # - helm lint helm/peikarband + # when: + # event: [push, pull_request, tag] + + # deploy-staging: + # image: *helm_image + # commands: + # - apk add --no-cache kubectl + # - echo "$KUBECONFIG_STAGING" | base64 -d > /tmp/kubeconfig + # - export KUBECONFIG=/tmp/kubeconfig + # - helm upgrade --install peikarband-staging helm/peikarband \ + # --namespace staging \ + # --create-namespace \ + # --set image.repository=hub.peikarband.ir/peikarband/landing \ + # --set image.tag=${CI_COMMIT_SHA:0:8} \ + # --wait --timeout 5m + # secrets: [KUBECONFIG_STAGING] + # when: + # event: push + # branch: [main, develop]