Chore/observability #6
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: terraform-plan | |
| on: | |
| pull_request: | |
| branches: [ main ] | |
| concurrency: | |
| group: plan-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| id-token: write | |
| contents: read | |
| pull-requests: write | |
| env: | |
| ARM_USE_OIDC: "true" | |
| ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} | |
| ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} | |
| ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| TF_VAR_client_id: ${{ secrets.AZURE_CLIENT_ID }} | |
| TF_VAR_tenant_id: ${{ secrets.AZURE_TENANT_ID }} | |
| TF_VAR_subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| jobs: | |
| plan: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Azure OIDC Login | |
| uses: azure/login@v2 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: Install OpenTofu | |
| uses: opentofu/setup-opentofu@v1 | |
| with: | |
| tofu_version: "1.6.0" | |
| - name: Format check | |
| working-directory: tofu | |
| run: tofu fmt -check -recursive | |
| - name: Tofu Init | |
| working-directory: tofu | |
| run: tofu init -input=false | |
| - name: Validate | |
| working-directory: tofu | |
| run: tofu validate | |
| - name: Plan | |
| working-directory: tofu | |
| run: tofu plan -no-color -input=false -out=tfplan | |
| - name: Plan to JSON | |
| working-directory: tofu | |
| run: tofu show -json tfplan > plan.json | |
| - name: Comment plan on PR | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const plan = JSON.parse(fs.readFileSync('tofu/plan.json', 'utf8')); | |
| // only resources that actually change (skip no-op / read) | |
| const changes = (plan.resource_changes || []).filter(rc => { | |
| const a = rc.change.actions; | |
| return !(a.length === 1 && (a[0] === 'no-op' || a[0] === 'read')); | |
| }); | |
| // map an actions array -> a friendly label (create+delete = replace) | |
| const label = a => | |
| a.includes('create') && a.includes('delete') ? '♻️ replace' | |
| : a[0] === 'create' ? '➕ create' | |
| : a[0] === 'update' ? '📝 update' | |
| : a[0] === 'delete' ? '❌ destroy' | |
| : a.join(','); | |
| // tally for the header line | |
| const c = { add: 0, change: 0, destroy: 0 }; | |
| for (const rc of changes) { | |
| const a = rc.change.actions; | |
| if (a.includes('create')) c.add++; | |
| if (a.includes('delete')) c.destroy++; | |
| if (a.length === 1 && a[0] === 'update') c.change++; | |
| } | |
| const marker = '<!-- tofu-plan -->'; | |
| let body; | |
| if (changes.length === 0) { | |
| body = `${marker}\n#### OpenTofu Plan 📖\n✅ **No changes** — infrastructure matches configuration.`; | |
| } else { | |
| const rows = changes.map(rc => `| ${label(rc.change.actions)} | \`${rc.address}\` |`).join('\n'); | |
| body = `${marker}\n#### OpenTofu Plan 📖\n**${c.add} to add · ${c.change} to change · ${c.destroy} to destroy**\n\n| action | resource |\n|---|---|\n${rows}\n\n_Attribute diff omitted — public repo._`; | |
| } | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, | |
| }); | |
| const prev = comments.find(c => c.body.includes(marker)); | |
| const args = { owner: context.repo.owner, repo: context.repo.repo, body }; | |
| if (prev) await github.rest.issues.updateComment({ ...args, comment_id: prev.id }); | |
| else await github.rest.issues.createComment({ ...args, issue_number: context.issue.number }); | |
| - name: Setup Infracost | |
| uses: infracost/actions/setup@v3 | |
| with: | |
| api-key: ${{ secrets.INFRACOST_API_KEY }} | |
| - name: Infracost breakdown | |
| run: infracost breakdown --path=tofu/plan.json --format=json --out-file=/tmp/infracost.json | |
| - name: Infracost PR comment | |
| run: | | |
| infracost comment github --path=/tmp/infracost.json \ | |
| --repo=$GITHUB_REPOSITORY \ | |
| --pull-request=${{ github.event.pull_request.number }} \ | |
| --github-token=${{ github.token }} \ | |
| --behavior=update |