v0.1.14 #17
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Update Kustomization Files | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Release tag (e.g., v0.1.1)" | |
| required: true | |
| type: string | |
| dry_run: | |
| description: "Dry run (no PR creation)" | |
| required: false | |
| type: boolean | |
| default: false | |
| jobs: | |
| update-kustomizations: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: main | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Extract version from tag | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "release" ]; then | |
| VERSION="${{ github.event.release.tag_name }}" | |
| else | |
| VERSION="${{ inputs.tag }}" | |
| fi | |
| echo "tag=$VERSION" >> $GITHUB_OUTPUT | |
| echo "branch=chore/update-kustomize-$VERSION" >> $GITHUB_OUTPUT | |
| echo "Extracted version: $VERSION" | |
| - name: Get previous release tag for comparison | |
| id: prev_tag | |
| run: | | |
| CURRENT_TAG="${{ steps.version.outputs.tag }}" | |
| echo "Current tag: $CURRENT_TAG" | |
| # Get the previous tag for comparison (excluding the current tag) | |
| PREV_TAG=$(git tag --sort=-v:refname | grep -v "^${CURRENT_TAG}$" | head -n 1) | |
| if [ -z "$PREV_TAG" ]; then | |
| echo "No previous tag found, will compare against initial commit" | |
| PREV_TAG=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| echo "base=$PREV_TAG" >> $GITHUB_OUTPUT | |
| echo "Comparing $PREV_TAG...$CURRENT_TAG to detect changed services" | |
| - name: Detect changed services using path filter | |
| id: filter | |
| uses: dorny/paths-filter@v3 | |
| with: | |
| base: ${{ steps.prev_tag.outputs.base }} | |
| ref: ${{ steps.version.outputs.tag }} | |
| filters: | | |
| api-gateway: | |
| - 'api-gateway/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| auth-service: | |
| - 'auth-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| product-service: | |
| - 'product-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| order-service: | |
| - 'order-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| payment-service: | |
| - 'payment-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| fulfillment-service: | |
| - 'fulfillment-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| notification-service: | |
| - 'notification-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| search-service: | |
| - 'search-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| chat-service: | |
| - 'chat-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| cart-service: | |
| - 'cart-service/**' | |
| - 'pkg/**' | |
| - 'proto/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| - name: Determine services to update | |
| id: services | |
| run: | | |
| CHANGED_SERVICES='${{ steps.filter.outputs.changes }}' | |
| echo "list=$CHANGED_SERVICES" >> $GITHUB_OUTPUT | |
| SERVICE_COUNT=$(echo "$CHANGED_SERVICES" | jq -r 'length') | |
| echo "Detected $SERVICE_COUNT changed services: $(echo "$CHANGED_SERVICES" | jq -r 'join(", ")')" | |
| - name: Create feature branch | |
| run: | | |
| git checkout -b ${{ steps.version.outputs.branch }} | |
| echo "Created branch: ${{ steps.version.outputs.branch }}" | |
| - name: Update all kustomization files | |
| id: update | |
| run: | | |
| VERSION="${{ steps.version.outputs.tag }}" | |
| # Strip 'v' prefix if present to match docker/metadata-action behavior | |
| VERSION_NO_V="${VERSION#v}" | |
| SERVICES='${{ steps.services.outputs.list }}' | |
| UPDATED_SERVICES=() | |
| echo "Updating kustomization files for version $VERSION_NO_V (from git tag: $VERSION)" | |
| echo "Processing $(echo "$SERVICES" | jq -r 'length') services..." | |
| while IFS= read -r service; do | |
| KUSTOMIZATION_PATH="deployments/k8s/workloads/overlays/prod/$service/kustomization.yaml" | |
| if [ -f "$KUSTOMIZATION_PATH" ]; then | |
| echo "Processing $service..." | |
| # Update all newTag fields (service and migration images) | |
| sed -i "s/^\s*newTag: .*/ newTag: $VERSION_NO_V/" "$KUSTOMIZATION_PATH" | |
| # Check if file was actually modified | |
| if ! git diff --quiet "$KUSTOMIZATION_PATH"; then | |
| echo "✓ Updated $service to $VERSION_NO_V" | |
| UPDATED_SERVICES+=("$service") | |
| else | |
| echo "- No changes needed for $service (already at $VERSION_NO_V)" | |
| fi | |
| else | |
| echo "⚠ Warning: Kustomization file not found for $service at $KUSTOMIZATION_PATH" | |
| fi | |
| done < <(echo "$SERVICES" | jq -r '.[]') | |
| # Export results | |
| if [ ${#UPDATED_SERVICES[@]} -eq 0 ]; then | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| echo "No kustomization files needed updating" | |
| else | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "count=${#UPDATED_SERVICES[@]}" >> $GITHUB_OUTPUT | |
| printf -v services_str '%s,' "${UPDATED_SERVICES[@]}" | |
| echo "services=${services_str%,}" >> $GITHUB_OUTPUT | |
| echo "Successfully updated ${#UPDATED_SERVICES[@]} services" | |
| fi | |
| - name: Validate YAML syntax | |
| if: steps.update.outputs.has_changes == 'true' | |
| run: | | |
| echo "Installing yq for YAML validation..." | |
| wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 | |
| chmod +x /usr/local/bin/yq | |
| echo "Validating YAML syntax for all updated files..." | |
| SERVICES='${{ steps.services.outputs.list }}' | |
| VALIDATION_FAILED=0 | |
| while IFS= read -r service; do | |
| KUSTOMIZATION_PATH="deployments/k8s/workloads/overlays/prod/$service/kustomization.yaml" | |
| if [ -f "$KUSTOMIZATION_PATH" ]; then | |
| if yq eval '.' "$KUSTOMIZATION_PATH" > /dev/null 2>&1; then | |
| echo "✓ Valid YAML: $service" | |
| else | |
| echo "✗ Invalid YAML: $service" | |
| VALIDATION_FAILED=1 | |
| fi | |
| fi | |
| done < <(echo "$SERVICES" | jq -r '.[]') | |
| if [ $VALIDATION_FAILED -eq 1 ]; then | |
| echo "ERROR: YAML validation failed for one or more files" | |
| exit 1 | |
| fi | |
| echo "All YAML files are valid" | |
| - name: Commit kustomization changes | |
| if: steps.update.outputs.has_changes == 'true' | |
| run: | | |
| VERSION="${{ steps.version.outputs.tag }}" | |
| SERVICES="${{ steps.update.outputs.services }}" | |
| COUNT="${{ steps.update.outputs.count }}" | |
| # Stage all kustomization files | |
| git add deployments/k8s/workloads/overlays/prod/*/kustomization.yaml | |
| # Create consolidated commit message | |
| cat > commit_msg.txt << EOF | |
| chore(k8s): update kustomization image tags to $VERSION | |
| Updated image tags for $COUNT services: | |
| $(echo "$SERVICES" | tr ',' '\n' | sed 's/^/- /') | |
| This is an automated update from the release workflow. | |
| Release: $VERSION | |
| Workflow: ${{ github.workflow }} | |
| Run: ${{ github.run_id }} | |
| EOF | |
| # Perform commit | |
| git commit -F commit_msg.txt | |
| echo "Commit created successfully" | |
| - name: Push branch | |
| if: steps.update.outputs.has_changes == 'true' && inputs.dry_run != true | |
| run: | | |
| BRANCH="${{ steps.version.outputs.branch }}" | |
| echo "Pushing branch $BRANCH to origin..." | |
| # Check if branch exists on remote | |
| if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then | |
| echo "Branch already exists on remote, force pushing with --force-with-lease" | |
| git push origin "$BRANCH" --force-with-lease | |
| else | |
| echo "New branch, pushing normally" | |
| git push origin "$BRANCH" | |
| fi | |
| echo "Branch pushed successfully" | |
| - name: Check if PR already exists | |
| id: pr_check | |
| if: steps.update.outputs.has_changes == 'true' && inputs.dry_run != true | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| EXISTING_PR=$(gh pr list \ | |
| --head ${{ steps.version.outputs.branch }} \ | |
| --base main \ | |
| --state open \ | |
| --json number \ | |
| --jq '.[0].number' || echo "") | |
| if [ -n "$EXISTING_PR" ]; then | |
| echo "exists=true" >> $GITHUB_OUTPUT | |
| echo "number=$EXISTING_PR" >> $GITHUB_OUTPUT | |
| echo "Found existing PR #$EXISTING_PR" | |
| else | |
| echo "exists=false" >> $GITHUB_OUTPUT | |
| echo "No existing PR found" | |
| fi | |
| - name: Create Pull Request | |
| if: steps.update.outputs.has_changes == 'true' && steps.pr_check.outputs.exists == 'false' && inputs.dry_run != true | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.version.outputs.tag }}" | |
| SERVICES="${{ steps.update.outputs.services }}" | |
| COUNT="${{ steps.update.outputs.count }}" | |
| # Create PR body | |
| cat > pr_body.md << EOF | |
| ## Summary | |
| Automated update of Kustomization image tags following the release of **$VERSION**. | |
| ## Changes | |
| Updated \`newTag\` field in kustomization files for **$COUNT** services: | |
| EOF | |
| echo "$SERVICES" | tr ',' '\n' | while read -r service; do | |
| echo "- \`$service\`: deployments/k8s/workloads/overlays/prod/$service/kustomization.yaml" >> pr_body.md | |
| done | |
| cat >> pr_body.md << EOF | |
| ## Metadata | |
| - **Release**: $VERSION | |
| - **Workflow Run**: ${{ github.run_id }} | |
| - **Triggered By**: ${{ github.actor }} | |
| --- | |
| *This PR was automatically generated by the [Update Kustomization Files](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) workflow.* | |
| EOF | |
| # Create PR using GitHub CLI | |
| echo "Creating pull request..." | |
| PR_URL=$(gh pr create \ | |
| --title "chore(k8s): update kustomization image tags to $VERSION" \ | |
| --body-file pr_body.md \ | |
| --base main \ | |
| --head ${{ steps.version.outputs.branch }}) | |
| echo "Pull request created: $PR_URL" | |
| # Try to add labels, but don't fail if they don't exist | |
| echo "Attempting to add labels..." | |
| gh pr edit "$PR_URL" --add-label "chore,k8s,automated" || \ | |
| echo "⚠ Could not add labels (labels may not exist in repository). PR created successfully without labels." | |
| echo "Pull request created successfully" | |
| - name: Update existing PR | |
| if: steps.update.outputs.has_changes == 'true' && steps.pr_check.outputs.exists == 'true' && inputs.dry_run != true | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "PR #${{ steps.pr_check.outputs.number }} already exists" | |
| echo "Force pushing updates to branch ${{ steps.version.outputs.branch }}..." | |
| git push origin ${{ steps.version.outputs.branch }} --force-with-lease | |
| # Add comment to existing PR | |
| gh pr comment ${{ steps.pr_check.outputs.number }} \ | |
| --body "Updated kustomization files via workflow run [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" | |
| echo "Existing PR updated successfully" | |
| - name: No changes detected | |
| if: steps.update.outputs.has_changes == 'false' | |
| run: | | |
| echo "ℹ No kustomization files needed updating for ${{ steps.version.outputs.tag }}" | |
| echo "" | |
| echo "This might happen if:" | |
| echo " - All files are already at the target version" | |
| echo " - The release doesn't include any service updates" | |
| echo " - Services were manually updated already" | |
| - name: Dry run summary | |
| if: inputs.dry_run == true | |
| run: | | |
| echo "========================================" | |
| echo "DRY RUN MODE - No PR created" | |
| echo "========================================" | |
| echo "Branch created: ${{ steps.version.outputs.branch }}" | |
| echo "Changes detected: ${{ steps.update.outputs.has_changes }}" | |
| if [ "${{ steps.update.outputs.has_changes }}" = "true" ]; then | |
| echo "Services updated: ${{ steps.update.outputs.services }}" | |
| echo "Update count: ${{ steps.update.outputs.count }}" | |
| fi | |
| echo "========================================" | |
| - name: Generate job summary | |
| if: always() | |
| run: | | |
| echo "## Kustomization Update Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Version**: ${{ steps.version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Branch**: ${{ steps.version.outputs.branch }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Changes Detected**: ${{ steps.update.outputs.has_changes }}" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ steps.update.outputs.has_changes }}" = "true" ]; then | |
| echo "- **Services Updated**: ${{ steps.update.outputs.count }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Service List**: ${{ steps.update.outputs.services }}" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ "${{ inputs.dry_run }}" = "true" ]; then | |
| echo "- **Mode**: Dry Run (no PR created)" >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ steps.pr_check.outputs.exists }}" = "true" ]; then | |
| echo "- **PR**: Updated existing PR #${{ steps.pr_check.outputs.number }}" >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ steps.update.outputs.has_changes }}" = "true" ]; then | |
| echo "- **PR**: New PR created" >> $GITHUB_STEP_SUMMARY | |
| fi |