# 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