Skip to content

chore(deps): bump hashicorp/setup-terraform from 2 to 3 #184

chore(deps): bump hashicorp/setup-terraform from 2 to 3

chore(deps): bump hashicorp/setup-terraform from 2 to 3 #184

Workflow file for this run

name: "Terraform"
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
jobs:
terraform-plan:
name: "Terraform Plan"
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
outputs:
has_changes: ${{ steps.plan_outcome.outputs.has_changes }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
- name: Configure Terraform Provider Plugin Cache
run: |
plugin_cache_dir="$HOME/.terraform.d/plugin-cache"
printf '\n\nplugin_cache_dir="%s"' "${plugin_cache_dir}" >> ~/.terraformrc
mkdir --parents "${plugin_cache_dir}"
- name: Cache Terraform
uses: actions/cache@v3
with:
path: |
~/.terraform.d/plugin-cache
key: ${{ runner.os }}-terraform-${{ hashFiles('**/.terraform.lock.hcl') }}
restore-keys: |
${{ runner.os }}-terraform-
- name: Terraform Format
id: fmt
run: terraform fmt -no-color -check -diff -recursive
- name: Terraform Init
id: init
run: terraform init -no-color -lockfile=readonly
- name: Terraform Validate
id: validate
run: terraform validate -no-color
- name: Terraform Plan
id: plan
run: |
terraform plan -no-color -input=false -out=tfplan -detailed-exitcode
- name: Check if plan has changes
id: plan_outcome
shell: bash
run: |
exitcode=${{ steps.plan.outputs.exitcode }}
if [ "$exitcode" == "0" ]; then
echo "has_changes=no" >> "$GITHUB_OUTPUT"
echo "::notice::terraform plan has no changes"
elif [ "$exitcode" == "2" ]; then
jq_plan_parser='
(
[.resource_changes[]?.change.actions?] | flatten
) | {
"plan_outcome_add":(map(select(.=="create")) | length),
"plan_outcome_change":(map(select(.=="update")) | length),
"plan_outcome_destroy":(map(select(.=="delete")) | length)
} | to_entries | map("\(.key)=\(.value)") | @sh
'
eval "export $(${TERRAFORM_CLI_PATH}/terraform-bin show -json tfplan | jq -r "${jq_plan_parser}")"
{
printf "has_changes=yes\n";
printf "add=%s\n" "${plan_outcome_add}"
printf "change=%s\n" "${plan_outcome_change}"
printf "destroy=%s\n" "${plan_outcome_destroy}"
} >> "$GITHUB_OUTPUT"
echo "::notice::terraform plan has changes: ${plan_outcome_add} to add, ${plan_outcome_change} to change, ${plan_outcome_destroy} to destroy."
fi
- name: Update Git Step Summary
id: report
if: success() || failure()
env:
fmt_outcome: ${{ steps.fmt.outcome }}
fmt_stdout: ${{ steps.fmt.outputs.stdout }}
fmt_stderr: ${{ steps.fmt.outputs.stderr }}
init_outcome: ${{ steps.init.outcome }}
init_stdout: ${{ steps.init.outputs.stdout }}
init_stderr: ${{ steps.init.outputs.stderr }}
validate_outcome: ${{ steps.validate.outcome }}
validate_stdout: ${{ steps.validate.outputs.stdout }}
validate_stderr: ${{ steps.validate.outputs.stderr }}
plan_outcome: ${{ steps.plan.outcome }}
plan_stdout: ${{ steps.plan.outputs.stdout }}
plan_stderr: ${{ steps.plan.outputs.stderr }}
run: |
{
printf "#### Terraform Format and Style :pencil2: \`%s\`\n\n" "${fmt_outcome}";
if [ "${fmt_outcome}" == "failure" ]; then
printf "<details><summary>Format Error</summary>\n\n";
printf "\`\`\`terraform\n%s%s\n\`\`\`\n\n" "${fmt_stdout}" "${fmt_stderr}";
printf "</details>\n\n";
fi
printf "#### Terraform Initialization :gear: \`%s\`\n\n" "${init_outcome}";
if [ "${init_outcome}" == "failure" ]; then
printf "<details><summary>Initialization Error</summary>\n\n";
printf "\`\`\`terraform\n%s%s\n\`\`\`\n\n" "${init_stdout}" "${init_stderr}";
printf "</details>\n\n";
fi
printf "#### Terraform Validation :clipboard: \`%s\`\n\n" "${validate_outcome}";
if [ "${validate_outcome}" == "failure" ]; then
printf "<details><summary>Validation Error</summary>\n\n";
printf "\`\`\`terraform\n%s%s\n\`\`\`\n\n" "${validate_stdout}" "${validate_stderr}";
printf "</details>\n\n";
fi
printf "#### Terraform Plan :book: \`%s\`\n\n" "${plan_outcome}";
if [ "${plan_outcome}" != "skipped" ] ; then
printf "<details><summary>Show Plan</summary>\n\n";
printf "\`\`\`terraform\n%s%s\n\`\`\`\n\n" "${plan_stdout}" "${plan_stderr}";
printf "</details>\n\n";
fi
} > "$GITHUB_STEP_SUMMARY"
eof=$(head -c15 /dev/urandom | base64)
{
printf "summary<<%s\n" "${eof}";
cat "$GITHUB_STEP_SUMMARY";
printf "%s\n" "${eof}";
} >> "$GITHUB_OUTPUT"
- name: Update Pull Request
uses: actions/github-script@v6
if: (success() || failure()) && github.event_name == 'pull_request'
env:
title: Terraform Plan
summary: ${{ steps.report.outputs.summary }}
with:
script: |
const script = require('./.github/scripts/update_pull_request.js')
script({github, context})
- name: Encrypt plan
if: |
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
contains(fromJSON('["push", "workflow_dispatch"]'), github.event_name) &&
steps.plan_outcome.outputs.has_changes == 'yes'
run: gpg --quiet --symmetric --cipher-algo AES256 --batch --yes --passphrase '${{ secrets.TF_PLAN_PASSPHRASE }}' --output tfplan.gpg tfplan
- name: Upload plan
if: |
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
contains(fromJSON('["push", "workflow_dispatch"]'), github.event_name) &&
steps.plan_outcome.outputs.has_changes == 'yes'
uses: actions/upload-artifact@v3
with:
name: tfplan
path: tfplan.gpg
retention-days: 1
terraform-apply:
name: "Terraform Apply"
runs-on: ubuntu-latest
environment: default
needs: terraform-plan
if: |
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
contains(fromJSON('["push", "workflow_dispatch"]'), github.event_name) &&
needs.terraform-plan.outputs.has_changes == 'yes'
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
- name: Configure Terraform Provider Plugin Cache
run: |
plugin_cache_dir="$HOME/.terraform.d/plugin-cache"
printf '\n\nplugin_cache_dir="%s"' "${plugin_cache_dir}" >> ~/.terraformrc
mkdir --parents "${plugin_cache_dir}"
- name: Cache Terraform
uses: actions/cache@v3
with:
path: |
~/.terraform.d/plugin-cache
key: ${{ runner.os }}-terraform-${{ hashFiles('**/.terraform.lock.hcl') }}
restore-keys: |
${{ runner.os }}-terraform-
- name: Download Plan
uses: actions/download-artifact@v3
with:
name: tfplan
- name: Decrypt plan
run: gpg --quiet --batch --yes --decrypt --passphrase '${{ secrets.TF_PLAN_PASSPHRASE }}' --output tfplan tfplan.gpg
- name: Terraform Init
id: init
run: terraform init -no-color -lockfile=readonly
- name: Terraform Apply
id: apply
run: terraform apply -no-color -input=false tfplan
- name: Update Git Step Summary
id: report
if: success() || failure()
env:
init_outcome: ${{ steps.init.outcome }}
apply_outcome: ${{ steps.apply.outcome }}
apply_stdout: ${{ steps.apply.outputs.stdout }}
apply_stderr: ${{ steps.apply.outputs.stderr }}
run: |
{
printf "#### Terraform Initialization :gear: \`%s\`\n\n" "${init_outcome}";
printf "#### Terraform Apply :rocket: \`%s\`\n\n" "${apply_outcome}";
printf "<details><summary>Show Outcome</summary>\n\n";
printf "\`\`\`terraform\n%s%s\n\`\`\`\n\n" "${apply_stdout}" "${apply_stderr}";
printf "</details>\n\n";
} > "$GITHUB_STEP_SUMMARY"
- name: Check apply changes
if: steps.apply.outcome == 'success'
env:
apply_stdout: ${{ steps.apply.outputs.stdout }}
run: |
match_string="^Apply complete! Resources: "
result=$(echo "${apply_stdout}" | grep "${match_string}" | sed "s/${match_string}//")
echo "::notice::terraform apply complete: ${result}"