Add new infra architecture
This commit is contained in:
154
infrastructure/cicd/tekton/tasks/detect-changes.yaml
Normal file
154
infrastructure/cicd/tekton/tasks/detect-changes.yaml
Normal file
@@ -0,0 +1,154 @@
|
||||
# Tekton Detect Changed Services Task for Bakery-IA CI/CD
|
||||
# This task identifies which services have changed in the repository
|
||||
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: detect-changed-services
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: detect
|
||||
spec:
|
||||
workspaces:
|
||||
- name: source
|
||||
description: Source code workspace
|
||||
params:
|
||||
- name: base-ref
|
||||
type: string
|
||||
description: Base reference for comparison (default HEAD~1)
|
||||
default: "HEAD~1"
|
||||
results:
|
||||
- name: changed-services
|
||||
description: Comma-separated list of changed services
|
||||
- name: changed-files-count
|
||||
description: Number of files changed
|
||||
steps:
|
||||
- name: detect
|
||||
image: alpine/git:2.43.0
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
SOURCE_PATH="$(workspaces.source.path)"
|
||||
BASE_REF="$(params.base-ref)"
|
||||
|
||||
cd "$SOURCE_PATH"
|
||||
|
||||
echo "============================================"
|
||||
echo "Detect Changed Services"
|
||||
echo "============================================"
|
||||
echo "Base ref: $BASE_REF"
|
||||
echo "============================================"
|
||||
|
||||
# Get list of changed files compared to base reference
|
||||
echo ""
|
||||
echo "Detecting changed files..."
|
||||
|
||||
# Try to get diff, fall back to listing all files if this is the first commit
|
||||
CHANGED_FILES=$(git diff --name-only "$BASE_REF" HEAD 2>/dev/null || git ls-tree -r HEAD --name-only)
|
||||
|
||||
FILE_COUNT=$(echo "$CHANGED_FILES" | grep -c "." || echo "0")
|
||||
echo "Found $FILE_COUNT changed files"
|
||||
echo "$FILE_COUNT" > $(results.changed-files-count.path)
|
||||
|
||||
if [ "$FILE_COUNT" = "0" ]; then
|
||||
echo "No files changed"
|
||||
echo "none" > $(results.changed-services.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Changed files:"
|
||||
echo "$CHANGED_FILES" | head -20
|
||||
if [ "$FILE_COUNT" -gt 20 ]; then
|
||||
echo "... and $((FILE_COUNT - 20)) more files"
|
||||
fi
|
||||
|
||||
# Map files to services using simple shell (no bash arrays)
|
||||
echo ""
|
||||
echo "Mapping files to services..."
|
||||
|
||||
CHANGED_SERVICES=""
|
||||
|
||||
# Process each file
|
||||
echo "$CHANGED_FILES" | while read -r file; do
|
||||
if [ -z "$file" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check services directory
|
||||
if echo "$file" | grep -q "^services/"; then
|
||||
SERVICE=$(echo "$file" | cut -d'/' -f2)
|
||||
if [ -n "$SERVICE" ] && ! echo "$CHANGED_SERVICES" | grep -q "$SERVICE"; then
|
||||
if [ -z "$CHANGED_SERVICES" ]; then
|
||||
CHANGED_SERVICES="$SERVICE"
|
||||
else
|
||||
CHANGED_SERVICES="$CHANGED_SERVICES,$SERVICE"
|
||||
fi
|
||||
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check frontend
|
||||
if echo "$file" | grep -q "^frontend/"; then
|
||||
if ! echo "$CHANGED_SERVICES" | grep -q "frontend"; then
|
||||
if [ -z "$CHANGED_SERVICES" ]; then
|
||||
CHANGED_SERVICES="frontend"
|
||||
else
|
||||
CHANGED_SERVICES="$CHANGED_SERVICES,frontend"
|
||||
fi
|
||||
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check gateway
|
||||
if echo "$file" | grep -q "^gateway/"; then
|
||||
if ! echo "$CHANGED_SERVICES" | grep -q "gateway"; then
|
||||
if [ -z "$CHANGED_SERVICES" ]; then
|
||||
CHANGED_SERVICES="gateway"
|
||||
else
|
||||
CHANGED_SERVICES="$CHANGED_SERVICES,gateway"
|
||||
fi
|
||||
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check infrastructure
|
||||
if echo "$file" | grep -q "^infrastructure/"; then
|
||||
if ! echo "$CHANGED_SERVICES" | grep -q "infrastructure"; then
|
||||
if [ -z "$CHANGED_SERVICES" ]; then
|
||||
CHANGED_SERVICES="infrastructure"
|
||||
else
|
||||
CHANGED_SERVICES="$CHANGED_SERVICES,infrastructure"
|
||||
fi
|
||||
echo "$CHANGED_SERVICES" > /tmp/services.txt
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Read the accumulated services
|
||||
if [ -f /tmp/services.txt ]; then
|
||||
CHANGED_SERVICES=$(cat /tmp/services.txt)
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
|
||||
# Output result
|
||||
if [ -z "$CHANGED_SERVICES" ]; then
|
||||
echo "No service changes detected"
|
||||
echo "none" > $(results.changed-services.path)
|
||||
else
|
||||
echo "Detected changes in services: $CHANGED_SERVICES"
|
||||
echo "$CHANGED_SERVICES" > $(results.changed-services.path)
|
||||
fi
|
||||
|
||||
echo "============================================"
|
||||
resources:
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
95
infrastructure/cicd/tekton/tasks/git-clone.yaml
Normal file
95
infrastructure/cicd/tekton/tasks/git-clone.yaml
Normal file
@@ -0,0 +1,95 @@
|
||||
# Tekton Git Clone Task for Bakery-IA CI/CD
|
||||
# This task clones the source code repository
|
||||
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: git-clone
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: source
|
||||
spec:
|
||||
workspaces:
|
||||
- name: output
|
||||
description: Workspace to clone the repository into
|
||||
params:
|
||||
- name: url
|
||||
type: string
|
||||
description: Repository URL to clone
|
||||
- name: revision
|
||||
type: string
|
||||
description: Git revision to checkout
|
||||
default: "main"
|
||||
- name: depth
|
||||
type: string
|
||||
description: Git clone depth (0 for full history)
|
||||
default: "1"
|
||||
results:
|
||||
- name: commit-sha
|
||||
description: The commit SHA that was checked out
|
||||
- name: commit-message
|
||||
description: The commit message
|
||||
steps:
|
||||
- name: clone
|
||||
image: alpine/git:2.43.0
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
URL="$(params.url)"
|
||||
REVISION="$(params.revision)"
|
||||
DEPTH="$(params.depth)"
|
||||
OUTPUT_PATH="$(workspaces.output.path)"
|
||||
|
||||
echo "============================================"
|
||||
echo "Git Clone Task"
|
||||
echo "============================================"
|
||||
echo "URL: $URL"
|
||||
echo "Revision: $REVISION"
|
||||
echo "Depth: $DEPTH"
|
||||
echo "============================================"
|
||||
|
||||
# Clone with depth for faster checkout
|
||||
if [ "$DEPTH" = "0" ]; then
|
||||
echo "Cloning full repository..."
|
||||
git clone "$URL" "$OUTPUT_PATH"
|
||||
else
|
||||
echo "Cloning with depth $DEPTH..."
|
||||
git clone --depth "$DEPTH" "$URL" "$OUTPUT_PATH"
|
||||
fi
|
||||
|
||||
cd "$OUTPUT_PATH"
|
||||
|
||||
# Fetch the specific revision if needed
|
||||
if [ "$REVISION" != "main" ] && [ "$REVISION" != "master" ]; then
|
||||
echo "Fetching revision: $REVISION"
|
||||
git fetch --depth 1 origin "$REVISION" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Checkout the revision
|
||||
echo "Checking out: $REVISION"
|
||||
git checkout "$REVISION" 2>/dev/null || git checkout "origin/$REVISION"
|
||||
|
||||
# Get commit info
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
COMMIT_MSG=$(git log -1 --pretty=format:"%s")
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Clone Complete"
|
||||
echo "============================================"
|
||||
echo "Commit: $COMMIT_SHA"
|
||||
echo "Message: $COMMIT_MSG"
|
||||
echo "============================================"
|
||||
|
||||
# Write results
|
||||
echo -n "$COMMIT_SHA" > $(results.commit-sha.path)
|
||||
echo -n "$COMMIT_MSG" > $(results.commit-message.path)
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
200
infrastructure/cicd/tekton/tasks/kaniko-build.yaml
Normal file
200
infrastructure/cicd/tekton/tasks/kaniko-build.yaml
Normal file
@@ -0,0 +1,200 @@
|
||||
# Tekton Kaniko Build Task for Bakery-IA CI/CD
|
||||
# This task builds and pushes container images using Kaniko
|
||||
# Supports building multiple services from a comma-separated list
|
||||
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: kaniko-build
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: build
|
||||
spec:
|
||||
workspaces:
|
||||
- name: source
|
||||
description: Source code workspace
|
||||
- name: docker-credentials
|
||||
description: Docker registry credentials
|
||||
params:
|
||||
- name: services
|
||||
type: string
|
||||
description: Comma-separated list of services to build
|
||||
- name: registry
|
||||
type: string
|
||||
description: Container registry URL
|
||||
- name: git-revision
|
||||
type: string
|
||||
description: Git revision for image tag
|
||||
default: "latest"
|
||||
results:
|
||||
- name: built-images
|
||||
description: List of successfully built images
|
||||
- name: build-status
|
||||
description: Overall build status (success/failure)
|
||||
steps:
|
||||
# Step 1: Setup docker credentials
|
||||
- name: setup-docker-config
|
||||
image: alpine:3.18
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
echo "Setting up Docker credentials..."
|
||||
mkdir -p /kaniko/.docker
|
||||
|
||||
# Check if credentials secret is mounted
|
||||
if [ -f "$(workspaces.docker-credentials.path)/config.json" ]; then
|
||||
cp "$(workspaces.docker-credentials.path)/config.json" /kaniko/.docker/config.json
|
||||
echo "Docker config copied from secret"
|
||||
elif [ -f "$(workspaces.docker-credentials.path)/.dockerconfigjson" ]; then
|
||||
cp "$(workspaces.docker-credentials.path)/.dockerconfigjson" /kaniko/.docker/config.json
|
||||
echo "Docker config copied from .dockerconfigjson"
|
||||
else
|
||||
echo "Warning: No docker credentials found, builds may fail for private registries"
|
||||
echo '{}' > /kaniko/.docker/config.json
|
||||
fi
|
||||
volumeMounts:
|
||||
- name: docker-config
|
||||
mountPath: /kaniko/.docker
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 32Mi
|
||||
|
||||
# Step 2: Build each service iteratively
|
||||
- name: build-services
|
||||
image: gcr.io/kaniko-project/executor:v1.23.0
|
||||
script: |
|
||||
#!/busybox/sh
|
||||
set -e
|
||||
|
||||
SERVICES="$(params.services)"
|
||||
REGISTRY="$(params.registry)"
|
||||
REVISION="$(params.git-revision)"
|
||||
SOURCE_PATH="$(workspaces.source.path)"
|
||||
BUILT_IMAGES=""
|
||||
FAILED_SERVICES=""
|
||||
|
||||
echo "============================================"
|
||||
echo "Starting build for services: $SERVICES"
|
||||
echo "Registry: $REGISTRY"
|
||||
echo "Tag: $REVISION"
|
||||
echo "============================================"
|
||||
|
||||
# Skip if no services to build
|
||||
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||
echo "No services to build, skipping..."
|
||||
echo "none" > $(results.built-images.path)
|
||||
echo "skipped" > $(results.build-status.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Convert comma-separated list to space-separated
|
||||
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||
|
||||
for SERVICE in $SERVICES_LIST; do
|
||||
# Trim whitespace
|
||||
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||
|
||||
# Skip infrastructure changes (not buildable)
|
||||
if [ "$SERVICE" = "infrastructure" ]; then
|
||||
echo "Skipping infrastructure (not a buildable service)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "--------------------------------------------"
|
||||
echo "Building service: $SERVICE"
|
||||
echo "--------------------------------------------"
|
||||
|
||||
# Determine Dockerfile path based on service type
|
||||
if [ "$SERVICE" = "frontend" ]; then
|
||||
DOCKERFILE_PATH="$SOURCE_PATH/frontend/Dockerfile"
|
||||
CONTEXT_PATH="$SOURCE_PATH/frontend"
|
||||
elif [ "$SERVICE" = "gateway" ]; then
|
||||
DOCKERFILE_PATH="$SOURCE_PATH/gateway/Dockerfile"
|
||||
CONTEXT_PATH="$SOURCE_PATH/gateway"
|
||||
else
|
||||
DOCKERFILE_PATH="$SOURCE_PATH/services/$SERVICE/Dockerfile"
|
||||
CONTEXT_PATH="$SOURCE_PATH"
|
||||
fi
|
||||
|
||||
# Check if Dockerfile exists
|
||||
if [ ! -f "$DOCKERFILE_PATH" ]; then
|
||||
echo "Warning: Dockerfile not found at $DOCKERFILE_PATH, skipping $SERVICE"
|
||||
FAILED_SERVICES="$FAILED_SERVICES $SERVICE"
|
||||
continue
|
||||
fi
|
||||
|
||||
IMAGE_NAME="$REGISTRY/bakery/$SERVICE:$REVISION"
|
||||
IMAGE_NAME_LATEST="$REGISTRY/bakery/$SERVICE:latest"
|
||||
|
||||
echo "Dockerfile: $DOCKERFILE_PATH"
|
||||
echo "Context: $CONTEXT_PATH"
|
||||
echo "Image: $IMAGE_NAME"
|
||||
|
||||
# Run Kaniko build
|
||||
/kaniko/executor \
|
||||
--dockerfile="$DOCKERFILE_PATH" \
|
||||
--context="$CONTEXT_PATH" \
|
||||
--destination="$IMAGE_NAME" \
|
||||
--destination="$IMAGE_NAME_LATEST" \
|
||||
--cache=true \
|
||||
--cache-ttl=24h \
|
||||
--verbosity=info \
|
||||
--snapshot-mode=redo \
|
||||
--use-new-run
|
||||
|
||||
BUILD_EXIT_CODE=$?
|
||||
|
||||
if [ $BUILD_EXIT_CODE -eq 0 ]; then
|
||||
echo "Successfully built and pushed: $IMAGE_NAME"
|
||||
if [ -z "$BUILT_IMAGES" ]; then
|
||||
BUILT_IMAGES="$IMAGE_NAME"
|
||||
else
|
||||
BUILT_IMAGES="$BUILT_IMAGES,$IMAGE_NAME"
|
||||
fi
|
||||
else
|
||||
echo "Failed to build: $SERVICE (exit code: $BUILD_EXIT_CODE)"
|
||||
FAILED_SERVICES="$FAILED_SERVICES $SERVICE"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Build Summary"
|
||||
echo "============================================"
|
||||
echo "Built images: $BUILT_IMAGES"
|
||||
echo "Failed services: $FAILED_SERVICES"
|
||||
|
||||
# Write results
|
||||
if [ -z "$BUILT_IMAGES" ]; then
|
||||
echo "none" > $(results.built-images.path)
|
||||
else
|
||||
echo "$BUILT_IMAGES" > $(results.built-images.path)
|
||||
fi
|
||||
|
||||
if [ -n "$FAILED_SERVICES" ]; then
|
||||
echo "partial" > $(results.build-status.path)
|
||||
echo "Warning: Some services failed to build: $FAILED_SERVICES"
|
||||
else
|
||||
echo "success" > $(results.build-status.path)
|
||||
fi
|
||||
volumeMounts:
|
||||
- name: docker-config
|
||||
mountPath: /kaniko/.docker
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
volumes:
|
||||
- name: docker-config
|
||||
emptyDir: {}
|
||||
14
infrastructure/cicd/tekton/tasks/kustomization.yaml
Normal file
14
infrastructure/cicd/tekton/tasks/kustomization.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- git-clone.yaml
|
||||
- detect-changes.yaml
|
||||
- run-tests.yaml
|
||||
- kaniko-build.yaml
|
||||
- update-gitops.yaml
|
||||
- pipeline-summary.yaml
|
||||
# Production deployment tasks
|
||||
- verify-images.yaml
|
||||
- pre-deploy-validation.yaml
|
||||
- prod-deployment-summary.yaml
|
||||
62
infrastructure/cicd/tekton/tasks/pipeline-summary.yaml
Normal file
62
infrastructure/cicd/tekton/tasks/pipeline-summary.yaml
Normal file
@@ -0,0 +1,62 @@
|
||||
# Tekton Pipeline Summary Task for Bakery-IA CI/CD
|
||||
# This task runs at the end of the pipeline and provides a summary
|
||||
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: pipeline-summary
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: summary
|
||||
spec:
|
||||
params:
|
||||
- name: changed-services
|
||||
type: string
|
||||
description: List of changed services
|
||||
default: "none"
|
||||
- name: git-revision
|
||||
type: string
|
||||
description: Git revision that was built
|
||||
default: "unknown"
|
||||
steps:
|
||||
- name: summary
|
||||
image: alpine:3.18
|
||||
script: |
|
||||
#!/bin/sh
|
||||
|
||||
SERVICES="$(params.changed-services)"
|
||||
REVISION="$(params.git-revision)"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Pipeline Execution Summary"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Git Revision: $REVISION"
|
||||
echo "Changed Services: $SERVICES"
|
||||
echo ""
|
||||
echo "Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||
echo "No services were changed in this commit."
|
||||
echo "Pipeline completed without building any images."
|
||||
else
|
||||
echo "The following services were processed:"
|
||||
echo "$SERVICES" | tr ',' '\n' | while read service; do
|
||||
echo " - $service"
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 32Mi
|
||||
76
infrastructure/cicd/tekton/tasks/pre-deploy-validation.yaml
Normal file
76
infrastructure/cicd/tekton/tasks/pre-deploy-validation.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
# Task for pre-deployment validation
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: pre-deploy-validation
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: validation
|
||||
spec:
|
||||
workspaces:
|
||||
- name: source
|
||||
description: Source code workspace
|
||||
params:
|
||||
- name: services
|
||||
type: string
|
||||
description: Comma-separated list of services to validate
|
||||
- name: environment
|
||||
type: string
|
||||
description: Target environment (staging/production)
|
||||
default: "production"
|
||||
results:
|
||||
- name: validation-status
|
||||
description: Status of validation (passed/failed)
|
||||
steps:
|
||||
- name: validate
|
||||
image: registry.k8s.io/kustomize/kustomize:v5.3.0
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
SOURCE_PATH="$(workspaces.source.path)"
|
||||
SERVICES="$(params.services)"
|
||||
ENVIRONMENT="$(params.environment)"
|
||||
|
||||
echo "============================================"
|
||||
echo "Pre-Deployment Validation"
|
||||
echo "============================================"
|
||||
echo "Environment: $ENVIRONMENT"
|
||||
echo "Services: $SERVICES"
|
||||
echo "============================================"
|
||||
|
||||
cd "$SOURCE_PATH"
|
||||
|
||||
# Validate kustomization can be built
|
||||
KUSTOMIZE_DIR="infrastructure/environments/$ENVIRONMENT"
|
||||
|
||||
if [ -d "$KUSTOMIZE_DIR" ]; then
|
||||
echo ""
|
||||
echo "Validating kustomization..."
|
||||
if kustomize build "$KUSTOMIZE_DIR" > /dev/null 2>&1; then
|
||||
echo " ✓ Kustomization is valid"
|
||||
else
|
||||
echo " ✗ Kustomization validation failed"
|
||||
echo "failed" > $(results.validation-status.path)
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Additional validation checks can be added here
|
||||
# - Schema validation
|
||||
# - Policy checks (OPA/Gatekeeper)
|
||||
# - Security scanning
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "All validations passed"
|
||||
echo "============================================"
|
||||
echo "passed" > $(results.validation-status.path)
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
@@ -0,0 +1,57 @@
|
||||
# Task for production deployment summary
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: prod-deployment-summary
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: summary
|
||||
spec:
|
||||
params:
|
||||
- name: services
|
||||
type: string
|
||||
description: List of deployed services
|
||||
- name: git-revision
|
||||
type: string
|
||||
description: Git revision that was deployed
|
||||
- name: approver
|
||||
type: string
|
||||
description: Name of the approver
|
||||
- name: approval-ticket
|
||||
type: string
|
||||
description: Approval ticket number
|
||||
steps:
|
||||
- name: summary
|
||||
image: alpine:3.18
|
||||
script: |
|
||||
#!/bin/sh
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Production Deployment Summary"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Git Revision: $(params.git-revision)"
|
||||
echo "Services: $(params.services)"
|
||||
echo "Approved By: $(params.approver)"
|
||||
echo "Approval Ticket: $(params.approval-ticket)"
|
||||
echo "Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Deployment to production initiated."
|
||||
echo "Flux CD will reconcile the changes."
|
||||
echo ""
|
||||
echo "Monitor deployment status with:"
|
||||
echo " kubectl get kustomization -n flux-system"
|
||||
echo " kubectl get pods -n bakery-ia"
|
||||
echo ""
|
||||
echo "============================================"
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 32Mi
|
||||
205
infrastructure/cicd/tekton/tasks/run-tests.yaml
Normal file
205
infrastructure/cicd/tekton/tasks/run-tests.yaml
Normal file
@@ -0,0 +1,205 @@
|
||||
# Tekton Test Task for Bakery-IA CI/CD
|
||||
# This task runs unit tests and linting for changed services
|
||||
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: run-tests
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: test
|
||||
spec:
|
||||
workspaces:
|
||||
- name: source
|
||||
description: Source code workspace
|
||||
params:
|
||||
- name: services
|
||||
type: string
|
||||
description: Comma-separated list of services to test
|
||||
- name: skip-lint
|
||||
type: string
|
||||
description: Skip linting if "true"
|
||||
default: "false"
|
||||
- name: skip-tests
|
||||
type: string
|
||||
description: Skip tests if "true"
|
||||
default: "false"
|
||||
results:
|
||||
- name: test-status
|
||||
description: Overall test status (passed/failed/skipped)
|
||||
- name: tested-services
|
||||
description: List of services that were tested
|
||||
- name: failed-services
|
||||
description: List of services that failed tests
|
||||
steps:
|
||||
- name: run-tests
|
||||
image: python:3.11-slim
|
||||
script: |
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SOURCE_PATH="$(workspaces.source.path)"
|
||||
SERVICES="$(params.services)"
|
||||
SKIP_LINT="$(params.skip-lint)"
|
||||
SKIP_TESTS="$(params.skip-tests)"
|
||||
|
||||
TESTED_SERVICES=""
|
||||
FAILED_SERVICES=""
|
||||
OVERALL_STATUS="passed"
|
||||
|
||||
cd "$SOURCE_PATH"
|
||||
|
||||
echo "============================================"
|
||||
echo "Running Tests"
|
||||
echo "============================================"
|
||||
echo "Services: $SERVICES"
|
||||
echo "Skip Lint: $SKIP_LINT"
|
||||
echo "Skip Tests: $SKIP_TESTS"
|
||||
echo "============================================"
|
||||
|
||||
# Skip if no services to test
|
||||
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||
echo "No services to test, skipping..."
|
||||
echo "skipped" > $(results.test-status.path)
|
||||
echo "none" > $(results.tested-services.path)
|
||||
echo "none" > $(results.failed-services.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install common test dependencies
|
||||
echo ""
|
||||
echo "Installing test dependencies..."
|
||||
pip install --quiet pytest pytest-cov pytest-asyncio ruff mypy 2>/dev/null || true
|
||||
|
||||
# Convert comma-separated list to space-separated
|
||||
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||
|
||||
for SERVICE in $SERVICES_LIST; do
|
||||
# Trim whitespace
|
||||
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||
|
||||
# Skip infrastructure changes
|
||||
if [ "$SERVICE" = "infrastructure" ]; then
|
||||
echo "Skipping infrastructure (not testable)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "--------------------------------------------"
|
||||
echo "Testing service: $SERVICE"
|
||||
echo "--------------------------------------------"
|
||||
|
||||
# Determine service path
|
||||
if [ "$SERVICE" = "frontend" ]; then
|
||||
SERVICE_PATH="$SOURCE_PATH/frontend"
|
||||
elif [ "$SERVICE" = "gateway" ]; then
|
||||
SERVICE_PATH="$SOURCE_PATH/gateway"
|
||||
else
|
||||
SERVICE_PATH="$SOURCE_PATH/services/$SERVICE"
|
||||
fi
|
||||
|
||||
# Check if service exists
|
||||
if [ ! -d "$SERVICE_PATH" ]; then
|
||||
echo "Warning: Service directory not found: $SERVICE_PATH"
|
||||
continue
|
||||
fi
|
||||
|
||||
cd "$SERVICE_PATH"
|
||||
SERVICE_FAILED=false
|
||||
|
||||
# Install service-specific dependencies if requirements.txt exists
|
||||
if [ -f "requirements.txt" ]; then
|
||||
echo "Installing service dependencies..."
|
||||
pip install --quiet -r requirements.txt 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Run linting (ruff)
|
||||
if [ "$SKIP_LINT" != "true" ]; then
|
||||
echo ""
|
||||
echo "Running linter (ruff)..."
|
||||
if [ -d "app" ]; then
|
||||
ruff check app/ --output-format=text 2>&1 || {
|
||||
echo "Linting failed for $SERVICE"
|
||||
SERVICE_FAILED=true
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Run tests
|
||||
if [ "$SKIP_TESTS" != "true" ]; then
|
||||
echo ""
|
||||
echo "Running tests (pytest)..."
|
||||
if [ -d "tests" ]; then
|
||||
pytest tests/ -v --tb=short 2>&1 || {
|
||||
echo "Tests failed for $SERVICE"
|
||||
SERVICE_FAILED=true
|
||||
}
|
||||
elif [ -d "app/tests" ]; then
|
||||
pytest app/tests/ -v --tb=short 2>&1 || {
|
||||
echo "Tests failed for $SERVICE"
|
||||
SERVICE_FAILED=true
|
||||
}
|
||||
else
|
||||
echo "No tests directory found, skipping tests"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Track results
|
||||
if [ -z "$TESTED_SERVICES" ]; then
|
||||
TESTED_SERVICES="$SERVICE"
|
||||
else
|
||||
TESTED_SERVICES="$TESTED_SERVICES,$SERVICE"
|
||||
fi
|
||||
|
||||
if [ "$SERVICE_FAILED" = true ]; then
|
||||
OVERALL_STATUS="failed"
|
||||
if [ -z "$FAILED_SERVICES" ]; then
|
||||
FAILED_SERVICES="$SERVICE"
|
||||
else
|
||||
FAILED_SERVICES="$FAILED_SERVICES,$SERVICE"
|
||||
fi
|
||||
fi
|
||||
|
||||
cd "$SOURCE_PATH"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Test Summary"
|
||||
echo "============================================"
|
||||
echo "Tested services: $TESTED_SERVICES"
|
||||
echo "Failed services: $FAILED_SERVICES"
|
||||
echo "Overall status: $OVERALL_STATUS"
|
||||
|
||||
# Write results
|
||||
echo "$OVERALL_STATUS" > $(results.test-status.path)
|
||||
|
||||
if [ -z "$TESTED_SERVICES" ]; then
|
||||
echo "none" > $(results.tested-services.path)
|
||||
else
|
||||
echo "$TESTED_SERVICES" > $(results.tested-services.path)
|
||||
fi
|
||||
|
||||
if [ -z "$FAILED_SERVICES" ]; then
|
||||
echo "none" > $(results.failed-services.path)
|
||||
else
|
||||
echo "$FAILED_SERVICES" > $(results.failed-services.path)
|
||||
fi
|
||||
|
||||
# Exit with error if tests failed
|
||||
if [ "$OVERALL_STATUS" = "failed" ]; then
|
||||
echo ""
|
||||
echo "ERROR: Some tests failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "All tests passed!"
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 2Gi
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
302
infrastructure/cicd/tekton/tasks/update-gitops.yaml
Normal file
302
infrastructure/cicd/tekton/tasks/update-gitops.yaml
Normal file
@@ -0,0 +1,302 @@
|
||||
# Tekton Update GitOps Manifests Task for Bakery-IA CI/CD
|
||||
# This task updates Kubernetes manifests with new image tags using Kustomize
|
||||
# It uses a safer approach than sed for updating image references
|
||||
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: update-gitops
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: gitops
|
||||
spec:
|
||||
workspaces:
|
||||
- name: source
|
||||
description: Source code workspace with Git repository
|
||||
- name: git-credentials
|
||||
description: Git credentials for pushing changes
|
||||
optional: true
|
||||
params:
|
||||
- name: services
|
||||
type: string
|
||||
description: Comma-separated list of services to update
|
||||
- name: registry
|
||||
type: string
|
||||
description: Container registry URL
|
||||
- name: git-revision
|
||||
type: string
|
||||
description: Git revision for image tag
|
||||
- name: git-branch
|
||||
type: string
|
||||
description: Target branch for GitOps updates
|
||||
default: "main"
|
||||
- name: dry-run
|
||||
type: string
|
||||
description: If "true", only show what would be changed without committing
|
||||
default: "false"
|
||||
results:
|
||||
- name: updated-services
|
||||
description: List of services that were updated
|
||||
- name: commit-sha
|
||||
description: Git commit SHA of the update (empty if dry-run)
|
||||
steps:
|
||||
- name: update-manifests
|
||||
# Use alpine with curl to install kustomize
|
||||
image: alpine:3.19
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Install kustomize
|
||||
echo "Installing kustomize..."
|
||||
wget -q "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -O - | sh
|
||||
mv kustomize /usr/local/bin/
|
||||
echo "Kustomize version: $(kustomize version)"
|
||||
|
||||
SOURCE_PATH="$(workspaces.source.path)"
|
||||
SERVICES="$(params.services)"
|
||||
REGISTRY="$(params.registry)"
|
||||
REVISION="$(params.git-revision)"
|
||||
DRY_RUN="$(params.dry-run)"
|
||||
UPDATED_SERVICES=""
|
||||
|
||||
cd "$SOURCE_PATH"
|
||||
|
||||
echo "============================================"
|
||||
echo "GitOps Manifest Update"
|
||||
echo "============================================"
|
||||
echo "Services: $SERVICES"
|
||||
echo "Registry: $REGISTRY"
|
||||
echo "Revision: $REVISION"
|
||||
echo "Dry Run: $DRY_RUN"
|
||||
echo "============================================"
|
||||
|
||||
# Skip if no services to update
|
||||
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||
echo "No services to update, skipping..."
|
||||
echo "none" > $(results.updated-services.path)
|
||||
echo "" > $(results.commit-sha.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Define the kustomization directory
|
||||
KUSTOMIZE_DIR="infrastructure/environments/prod"
|
||||
|
||||
# Check if kustomization.yaml exists, create if not
|
||||
if [ ! -f "$KUSTOMIZE_DIR/kustomization.yaml" ]; then
|
||||
echo "Creating kustomization.yaml in $KUSTOMIZE_DIR"
|
||||
mkdir -p "$KUSTOMIZE_DIR"
|
||||
printf '%s\n' \
|
||||
"apiVersion: kustomize.config.k8s.io/v1beta1" \
|
||||
"kind: Kustomization" \
|
||||
"" \
|
||||
"resources:" \
|
||||
" - ../base" \
|
||||
"" \
|
||||
"images: []" \
|
||||
> "$KUSTOMIZE_DIR/kustomization.yaml"
|
||||
fi
|
||||
|
||||
# Convert comma-separated list to space-separated
|
||||
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||
|
||||
# Build the images section for kustomization
|
||||
echo ""
|
||||
echo "Updating image references..."
|
||||
|
||||
for SERVICE in $SERVICES_LIST; do
|
||||
# Trim whitespace
|
||||
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||
|
||||
# Skip infrastructure changes
|
||||
if [ "$SERVICE" = "infrastructure" ]; then
|
||||
echo "Skipping infrastructure (not a deployable service)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Processing: $SERVICE"
|
||||
|
||||
# Determine the image name based on service
|
||||
NEW_IMAGE="$REGISTRY/bakery/$SERVICE:$REVISION"
|
||||
|
||||
# Use kustomize to set the image
|
||||
# This is safer than sed as it understands the YAML structure
|
||||
cd "$SOURCE_PATH/$KUSTOMIZE_DIR"
|
||||
|
||||
# Check if this service has a deployment
|
||||
SERVICE_DEPLOYMENT=""
|
||||
if [ "$SERVICE" = "frontend" ]; then
|
||||
SERVICE_DEPLOYMENT="frontend"
|
||||
elif [ "$SERVICE" = "gateway" ]; then
|
||||
SERVICE_DEPLOYMENT="gateway"
|
||||
else
|
||||
SERVICE_DEPLOYMENT="$SERVICE-service"
|
||||
fi
|
||||
|
||||
# Update the kustomization with the new image
|
||||
# Using kustomize edit to safely modify the file
|
||||
kustomize edit set image "bakery/$SERVICE=$NEW_IMAGE" 2>/dev/null || \
|
||||
kustomize edit set image "$SERVICE=$NEW_IMAGE" 2>/dev/null || \
|
||||
echo "Note: Could not set image via kustomize edit, will use alternative method"
|
||||
|
||||
# Track updated services
|
||||
if [ -z "$UPDATED_SERVICES" ]; then
|
||||
UPDATED_SERVICES="$SERVICE"
|
||||
else
|
||||
UPDATED_SERVICES="$UPDATED_SERVICES,$SERVICE"
|
||||
fi
|
||||
|
||||
cd "$SOURCE_PATH"
|
||||
done
|
||||
|
||||
# Alternative: Update images in kustomization.yaml directly if kustomize edit didn't work
|
||||
# This creates/updates an images section in the kustomization
|
||||
echo ""
|
||||
echo "Ensuring image overrides in kustomization.yaml..."
|
||||
|
||||
# Create a patch file for image updates
|
||||
IMAGES_FILE="$KUSTOMIZE_DIR/images.yaml"
|
||||
printf '%s\n' \
|
||||
"# Auto-generated by CI/CD pipeline" \
|
||||
"# Commit: $REVISION" \
|
||||
"# Updated: $(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
|
||||
"images:" \
|
||||
> "$IMAGES_FILE"
|
||||
|
||||
for SERVICE in $SERVICES_LIST; do
|
||||
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||
if [ "$SERVICE" != "infrastructure" ]; then
|
||||
printf '%s\n' \
|
||||
" - name: bakery/$SERVICE" \
|
||||
" newName: $REGISTRY/bakery/$SERVICE" \
|
||||
" newTag: \"$REVISION\"" \
|
||||
>> "$IMAGES_FILE"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Generated images.yaml:"
|
||||
cat "$IMAGES_FILE"
|
||||
|
||||
# Validate the kustomization
|
||||
echo ""
|
||||
echo "Validating kustomization..."
|
||||
cd "$SOURCE_PATH/$KUSTOMIZE_DIR"
|
||||
if kustomize build . > /dev/null 2>&1; then
|
||||
echo "Kustomization is valid"
|
||||
else
|
||||
echo "Warning: Kustomization validation failed, but continuing..."
|
||||
fi
|
||||
cd "$SOURCE_PATH"
|
||||
|
||||
# Write results
|
||||
echo "$UPDATED_SERVICES" > $(results.updated-services.path)
|
||||
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "DRY RUN - Changes not committed"
|
||||
echo "============================================"
|
||||
echo "Would update services: $UPDATED_SERVICES"
|
||||
git diff --stat || true
|
||||
echo "" > $(results.commit-sha.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Committing changes..."
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
|
||||
- name: commit-and-push
|
||||
image: alpine/git:2.43.0
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
SOURCE_PATH="$(workspaces.source.path)"
|
||||
SERVICES="$(params.services)"
|
||||
REVISION="$(params.git-revision)"
|
||||
BRANCH="$(params.git-branch)"
|
||||
DRY_RUN="$(params.dry-run)"
|
||||
|
||||
cd "$SOURCE_PATH"
|
||||
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Dry run mode - skipping commit"
|
||||
echo "" > $(results.commit-sha.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$SERVICES" = "none" ] || [ -z "$SERVICES" ]; then
|
||||
echo "No services to commit"
|
||||
echo "" > $(results.commit-sha.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if there are changes to commit
|
||||
if git diff --quiet && git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
echo "" > $(results.commit-sha.path)
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Configure git
|
||||
git config --global user.name "bakery-ia-ci"
|
||||
git config --global user.email "ci@bakery-ia.local"
|
||||
git config --global --add safe.directory "$SOURCE_PATH"
|
||||
|
||||
# Setup git credentials if provided
|
||||
if [ -d "$(workspaces.git-credentials.path)" ]; then
|
||||
if [ -f "$(workspaces.git-credentials.path)/username" ] && [ -f "$(workspaces.git-credentials.path)/password" ]; then
|
||||
GIT_USER=$(cat "$(workspaces.git-credentials.path)/username")
|
||||
GIT_PASS=$(cat "$(workspaces.git-credentials.path)/password")
|
||||
|
||||
# Get the remote URL and inject credentials
|
||||
REMOTE_URL=$(git remote get-url origin)
|
||||
# Handle both http and https
|
||||
if echo "$REMOTE_URL" | grep -q "^http"; then
|
||||
REMOTE_URL=$(echo "$REMOTE_URL" | sed "s|://|://$GIT_USER:$GIT_PASS@|")
|
||||
git remote set-url origin "$REMOTE_URL"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Stage changes
|
||||
git add -A
|
||||
|
||||
# Create commit with detailed message
|
||||
COMMIT_MSG=$(printf 'ci: Update image tags to %s\n\nServices updated: %s\n\nThis commit was automatically generated by the CI/CD pipeline.\nPipeline run triggered by commit: %s' "$REVISION" "$SERVICES" "$REVISION")
|
||||
|
||||
git commit -m "$COMMIT_MSG"
|
||||
|
||||
# Get the commit SHA
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
echo "$COMMIT_SHA" > $(results.commit-sha.path)
|
||||
|
||||
echo "Created commit: $COMMIT_SHA"
|
||||
|
||||
# Push changes
|
||||
echo "Pushing to origin/$BRANCH..."
|
||||
git push origin HEAD:"$BRANCH"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "GitOps Update Complete"
|
||||
echo "============================================"
|
||||
echo "Commit: $COMMIT_SHA"
|
||||
echo "Branch: $BRANCH"
|
||||
echo "Services: $SERVICES"
|
||||
resources:
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
91
infrastructure/cicd/tekton/tasks/verify-images.yaml
Normal file
91
infrastructure/cicd/tekton/tasks/verify-images.yaml
Normal file
@@ -0,0 +1,91 @@
|
||||
# Task to verify images exist in the registry before deploying
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: verify-images
|
||||
namespace: tekton-pipelines
|
||||
labels:
|
||||
app.kubernetes.io/name: bakery-ia-cicd
|
||||
app.kubernetes.io/component: validation
|
||||
spec:
|
||||
params:
|
||||
- name: services
|
||||
type: string
|
||||
description: Comma-separated list of services to verify
|
||||
- name: registry
|
||||
type: string
|
||||
description: Container registry URL
|
||||
- name: git-revision
|
||||
type: string
|
||||
description: Git revision/tag to verify
|
||||
results:
|
||||
- name: verification-status
|
||||
description: Status of image verification (success/failed)
|
||||
- name: missing-images
|
||||
description: List of images that were not found
|
||||
steps:
|
||||
- name: verify
|
||||
image: gcr.io/go-containerregistry/crane:latest
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
SERVICES="$(params.services)"
|
||||
REGISTRY="$(params.registry)"
|
||||
REVISION="$(params.git-revision)"
|
||||
MISSING=""
|
||||
|
||||
echo "============================================"
|
||||
echo "Verifying Images in Registry"
|
||||
echo "============================================"
|
||||
echo "Registry: $REGISTRY"
|
||||
echo "Revision: $REVISION"
|
||||
echo "Services: $SERVICES"
|
||||
echo "============================================"
|
||||
|
||||
# Convert comma-separated list to space-separated
|
||||
SERVICES_LIST=$(echo "$SERVICES" | tr ',' ' ')
|
||||
|
||||
for SERVICE in $SERVICES_LIST; do
|
||||
SERVICE=$(echo "$SERVICE" | tr -d ' ')
|
||||
|
||||
if [ "$SERVICE" = "infrastructure" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
IMAGE="$REGISTRY/bakery/$SERVICE:$REVISION"
|
||||
echo ""
|
||||
echo "Checking: $IMAGE"
|
||||
|
||||
if crane manifest "$IMAGE" > /dev/null 2>&1; then
|
||||
echo " ✓ Found"
|
||||
else
|
||||
echo " ✗ NOT FOUND"
|
||||
if [ -z "$MISSING" ]; then
|
||||
MISSING="$SERVICE"
|
||||
else
|
||||
MISSING="$MISSING,$SERVICE"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
|
||||
if [ -n "$MISSING" ]; then
|
||||
echo "ERROR: Missing images: $MISSING"
|
||||
echo "failed" > $(results.verification-status.path)
|
||||
echo "$MISSING" > $(results.missing-images.path)
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All images verified successfully"
|
||||
echo "success" > $(results.verification-status.path)
|
||||
echo "none" > $(results.missing-images.path)
|
||||
resources:
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
Reference in New Issue
Block a user