Skip to content

Fix/change exclusions #19

Fix/change exclusions

Fix/change exclusions #19

Workflow file for this run

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:
name: terraform-plan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Azure OIDC Login
if: github.actor != 'dependabot[bot]'
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # 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@9d84900f3238fab8cd84ce47d658d25dd008be2f # v1
with:
tofu_version: "1.6.0"
- name: Format check
working-directory: tofu
run: tofu fmt -check -recursive
- name: Tofu Init
if: github.actor != 'dependabot[bot]'
working-directory: tofu
run: tofu init -input=false
- name: Validate
if: github.actor != 'dependabot[bot]'
working-directory: tofu
run: tofu validate
- name: Plan
if: github.actor != 'dependabot[bot]'
working-directory: tofu
run: tofu plan -no-color -input=false -out=tfplan
- name: Plan to JSON
if: github.actor != 'dependabot[bot]'
working-directory: tofu
run: tofu show -json tfplan > plan.json
- name: Comment plan on PR
if: github.actor != 'dependabot[bot]'
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # 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
if: github.actor != 'dependabot[bot]'
uses: infracost/actions/setup@e9d6e6cd65e168e76b0de50ff9957d2fe8bb1832 # v3
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Infracost breakdown
if: github.actor != 'dependabot[bot]'
run: infracost breakdown --path=tofu/plan.json --format=json --out-file=/tmp/infracost.json
- name: Infracost PR comment
if: github.actor != 'dependabot[bot]'
run: |
infracost comment github --path=/tmp/infracost.json \
--repo=$GITHUB_REPOSITORY \
--pull-request=${{ github.event.pull_request.number }} \
--github-token=${{ github.token }} \
--behavior=update