Skip to content

commit

commit #102

Workflow file for this run

name: Terraform
on:
pull_request:
branches:
- "*"
push:
branches:
- "*"
permissions:
contents: read
env:
TERRAFORM_VERSION: 1.4.6
AWS_REGION: ${{ vars.AWS_REGION }}
AWS_ROLE_TO_ASSUME: ${{ secrets.AWS_ROLE_TO_ASSUME }}
DEFAULT_BRANCH_CONFIG: |
{
"TERRAFORM_DIR": ".",
"BRANCHES": [
{
"WORKSPACE": "default",
"VARFILES": [
"terraform.tfvars"
],
"SHOULD_PLAN": true,
"SHOULD_APPLY": true
}
]
}
jobs:
setup:
runs-on: ubuntu-latest
outputs:
workspace: ${{ steps.parse-config.outputs.workspace }}
varfile: ${{ steps.parse-config.outputs.varfile }}
should_plan: ${{ steps.parse-config.outputs.should_plan }}
should_apply: ${{ steps.parse-config.outputs.should_apply }}
terraform_dir: ${{ steps.parse-config.outputs.terraform_dir }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Parse Configuration
id: parse-config
run: |
export BRANCH_NAME="${{ github.head_ref || github.ref_name }}"
if [[ $BRANCH_NAME == *"/"* ]]; then
export BRANCH_PREFIX="${BRANCH_NAME%/*}/"
else
export BRANCH_PREFIX=$BRANCH_NAME
fi
function fetch_config() {
local FILE=$1
TERRAFORM_DIR=$(cat $FILE | yq eval '.TERRAFORM_DIR')
BRANCH_CONFIG=$(cat $FILE | yq eval -o=json | jq '.BRANCHES[] | select(.BRANCH | startswith("'"$BRANCH_PREFIX"'"))')
}
if [ -f "tf-cfg.yaml" ]; then
fetch_config "tf-cfg.yaml"
elif [ -f "tf-cfg.json" ]; then
fetch_config "tf-cfg.json"
else
TERRAFORM_DIR=$(echo "${{ env.DEFAULT_BRANCH_CONFIG }}" | yq eval '.TERRAFORM_DIR')
BRANCH_CONFIG=$(echo "${{ env.DEFAULT_BRANCH_CONFIG }}" | yq eval '.BRANCHES[0]')
fi
WORKSPACE=$(echo "$BRANCH_CONFIG" | yq eval '.WORKSPACE' -)
VARFILE=$(echo "$BRANCH_CONFIG" | yq eval '.VARFILES' -)
SHOULD_PLAN=$(echo "$BRANCH_CONFIG" | yq eval '.SHOULD_PLAN' -)
SHOULD_APPLY=$(echo "$BRANCH_CONFIG" | yq eval '.SHOULD_APPLY' -)
echo "workspace=$WORKSPACE" >> $GITHUB_OUTPUT
echo "varfile=$VARFILE" >> $GITHUB_OUTPUT
echo "should_plan=$SHOULD_PLAN" >> $GITHUB_OUTPUT
echo "should_apply=$SHOULD_APPLY" >> $GITHUB_OUTPUT
echo "terraform_dir=$TERRAFORM_DIR" >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
terraform-format-checks:
name: Terraform Format Checks
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
fmt_outcome: ${{ steps.fmt.outcome }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Terraform Format
id: fmt
run: terraform fmt -list=true -check=true -recursive
terraform-plan:
if: needs.setup.outputs.should_plan == 'true'
needs: [terraform-format-checks, setup]
name: Terraform Plan
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
id-token: write
env:
#BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
WORKSPACE: "${{ needs.setup.outputs.workspace }}"
VARFILES: "${{ needs.setup.outputs.varfile }}"
TERRAFORM_DIR: "${{ needs.setup.outputs.terraform_dir }}"
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
terraform_wrapper: false
- name: Terraform Init
id: init
working-directory: ${{ env.TERRAFORM_DIR }}
continue-on-error: true
run: terraform init
- name: Set Terraform Workspace
id: set-workspace
working-directory: ${{ env.TERRAFORM_DIR }}
run: |
echo "Workspace: $WORKSPACE"
terraform workspace new $WORKSPACE || terraform workspace select $WORKSPACE
- name: Terraform Validate
id: validate
working-directory: ${{ env.TERRAFORM_DIR }}
continue-on-error: true
run: |
OUTPUT=$(terraform validate -no-color)
echo $OUTPUT
echo "output=$OUTPUT" >> $GITHUB_OUTPUT
- name: Terraform Plan
id: plan
working-directory: ${{ env.TERRAFORM_DIR }}
continue-on-error: true
run: |
VARFILES_CMD=$(echo "$VARFILES" | jq -r '.[] | "-var-file=" + .' | tr '\n' ' ')
terraform plan -no-color -input=false $VARFILES_CMD -out=plan.tfplan
OUTPUT=$(terraform show plan.tfplan | sed -r "s/\x1B\[[0-?]*[ -/]*[@-~]//g") # remove ansi escape sequences.
OUTPUT="$(echo "${OUTPUT}" | grep -v "Refreshing state")"
OUTPUT="$(echo -n "$OUTPUT" | tail -c 59000)"
OUTPUT=$(echo "$OUTPUT" | jq -R -s -c .)
echo "output=$OUTPUT" >> $GITHUB_OUTPUT
- name: Upload Terraform Plan as Artifact
id: upload-plan
uses: actions/upload-artifact@v3
with:
name: terraform-plan
path: ${{ env.TERRAFORM_DIR }}/plan.tfplan
retention-days: 1
- name: Setup Graphviz
id: setup-graphviz
uses: ts-graphviz/setup-graphviz@v1
- name: Generate Terraform Graph
id: generate-graph
working-directory: ${{ env.TERRAFORM_DIR }}
run: |
terraform graph -draw-cycles -type=plan-refresh-only -plan=plan.tfplan | dot -Tsvg > plan.svg
- name: Upload Terraform Graph as Artifact
id: upload-graph
uses: actions/upload-artifact@v3
with:
name: graph.svg
path: ${{ env.TERRAFORM_DIR }}/plan.svg
retention-days: 1
- name: Pull Request Comment
uses: actions/github-script@v6
if: github.event_name == 'pull_request'
env:
PLAN: "${{ steps.plan.outputs.output }}"
VALIDATE: "${{ steps.validate.outputs.output }}"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const planOutput = JSON.parse(process.env.PLAN);
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
})
const botComment = comments.find(comment => {
return comment.user.type === 'Bot' && comment.body.includes('Terraform Format and Style')
})
const output = `#### Terraform Workspace 🏗️ \`${{ needs.setup.outputs.workspace }}\`
#### Terraform Format and Style 🖌 \`${{ needs.terraform-format-checks.outputs.fmt_outcome }}\`
#### Terraform Initialization ⚙️ \`${{ steps.init.outcome }}\`
#### Terraform Validation 🤖 \`${{ steps.validate.outcome }}\`
<details><summary>Validation Output</summary>
\`\`\`\n
${process.env.VALIDATE}
\`\`\`
</details>
#### Terraform Plan 📖 \`${{ steps.plan.outcome }}\`
<details><summary>Show Plan</summary>
\`\`\`terraform\n
${planOutput}
\`\`\`
</details>
[Download](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) plan graph (Artifacts/plan.svg)`;
if (botComment) {
github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: output
})
} else {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
}
- name: Terraform Status
if: steps.init.outcome == 'failure' || steps.plan.outcome == 'failure'
run: exit 1
terraform-apply:
if: needs.setup.outputs.should_apply == 'true' && github.event_name != 'pull_request'
needs: [terraform-format-checks, terraform-plan, setup]
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
env:
WORKSPACE: "${{ needs.setup.outputs.workspace }}"
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}