- GitHub actions workflow to add at `.github/workflows/lib-terraform-plan.yml` ```yaml --- name: Lib - Terraform Plan on: workflow_call: inputs: WORKING_DIRECTORY: required: true type: string description: "Working directory" TF_VERSION: required: true type: string description: "Terraform version" TF_BACKEND_CONFIG: required: true type: string description: "Terraform backend config" AWS_REGION: required: true type: string description: "AWS region" ROLE_TO_ASSUME: required: true type: string description: "ARN of AWS role to assume" jobs: terraform-plan: name: "Terraform Plan" runs-on: ubuntu-latest defaults: run: shell: bash working-directory: ${{ inputs.WORKING_DIRECTORY }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ inputs.TF_VERSION }} - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-region: ${{ inputs.AWS_REGION }} role-to-assume: ${{ inputs.ROLE_TO_ASSUME }} - run: aws sts get-caller-identity - name: Terraform fmt id: fmt run: terraform fmt -check continue-on-error: true - name: Terraform Init id: init run: terraform init -backend-config=${{ inputs.TF_BACKEND_CONFIG }} -input=false - name: Terraform Validate id: validate run: terraform validate -no-color - name: Terraform Plan id: plan run: terraform plan -input=false -no-color continue-on-error: true - name: Terraform Comment uses: actions/github-script@v7 if: github.event_name == 'pull_request' env: PLAN: "terraform\n${{ steps.plan.outputs.stdout }}" with: github-token: ${{ github.token }} script: | // 1. Retrieve existing bot comments for the PR 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') }) // 2. Prepare format of the comment const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\` #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\` #### Terraform Validation 🤖\`${{ steps.validate.outcome }}\` <details><summary>Validation Output</summary> \`\`\`\n ${{ steps.validate.outputs.stdout }} \`\`\` </details> #### Terraform Plan 📖\`${{ steps.plan.outcome }}\` <details><summary>Show Plan</summary> \`\`\`\n ${process.env.PLAN} \`\`\` </details> *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ inputs.WORKING_DIRECTORY }}\`, Workflow: \`${{ github.workflow }}\`*`; // 3. If we have a comment, update it, otherwise create a new one 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 }) } ``` - GitHub actions workflow to add at `.github/workflows/lib-terraform-apply.yml` ```yaml --- name: Lib - Terraform Apply on: workflow_call: inputs: WORKING_DIRECTORY: required: true type: string description: "Working directory" TF_VERSION: required: true type: string description: "Terraform version" TF_BACKEND_CONFIG: required: true type: string description: "Terraform backend config" AWS_REGION: required: true type: string description: "AWS region" ROLE_TO_ASSUME: required: true type: string description: "ARN of AWS role to assume" jobs: terraform-apply: name: Terraform Apply runs-on: ubuntu-latest defaults: run: shell: bash working-directory: ${{ inputs.WORKING_DIRECTORY }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ inputs.TF_VERSION }} - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-region: ${{ inputs.AWS_REGION }} role-to-assume: ${{ inputs.ROLE_TO_ASSUME }} - run: aws sts get-caller-identity - name: Terraform Init id: init run: terraform init -backend-config=${{ inputs.TF_BACKEND_CONFIG }} -input=false - name: Terraform Apply run: terraform apply -input=false -auto-approve ``` - GitHub actions workflow to add at `.github/workflows/lib-validate-tfsec.yml` ```yaml --- name: Lib - Validate TFSEC on: workflow_call: inputs: WORKING_DIRECTORY: required: true type: string description: "Working directory" jobs: validate_tfsec: name: Tfsec runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Run tfsec uses: aquasecurity/[email protected] with: working_directory: ${{ inputs.WORKING_DIRECTORY }} github_token: ${{ secrets.GITHUB_TOKEN }} ``` - GitHub actions workflow to add at `.github/workflows/prod-networking-pr.yml` ```yaml --- name: Prod Networking PR on: pull_request: branches: - main paths: - 'prod/networking/**' workflow_dispatch: permissions: id-token: write contents: read pull-requests: write jobs: prod_networking_plan: uses: .github/workflows/lib-terraform-plan.yml with: WORKING_DIRECTORY: "prod/networking" TF_VERSION: "1.4.2" TF_BACKEND_CONFIG: "key=prod/networking/terraform.tfstate" AWS_REGION: "us-west-2" ROLE_TO_ASSUME: "arn:aws:iam::xxxxxxxxxxxx:role/github" validate_tfsec: uses: .github/workflows/lib-validate-tfsec.yml with: WORKING_DIRECTORY: "prod/networking" ``` - GitHub actions workflow to add at `.github/workflows/prod-networking.yml` ```yaml --- name: Prod Networking on: push: branches: - main paths: - 'prod/networking/**' workflow_dispatch: permissions: id-token: write contents: read jobs: prod_networking_apply: uses: .github/workflows/lib-terraform-apply.yml@main with: WORKING_DIRECTORY: "prod/networking" TF_VERSION: "1.4.2" TF_BACKEND_CONFIG: "key=prod/networking/terraform.tfstate" AWS_REGION: "us-west-2" ROLE_TO_ASSUME: "arn:aws:iam::xxxxxxxxxxxx:role/github" ``` - GitHub actions workflow to add at `.github/workflows/prod-tenants-pr.yml` ```yaml --- name: Prod tenants PR on: pull_request: branches: - main paths: - '.github/workflows/prod-tenants-pr.yml' - 'prod/tenants/**' workflow_dispatch: env: paths: 'prod/tenants/*/' permissions: id-token: write contents: read pull-requests: write jobs: get_changed: runs-on: ubuntu-latest outputs: triggering_path: ${{ steps.determine_path.outputs.triggering_path }} steps: - name: Checkout code uses: actions/checkout@v3 with: fetch-depth: 0 - name: Get changed files id: changes run: | echo "files=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | xargs)" >> $GITHUB_OUTPUT - name: Determine triggering path id: determine_path shell: bash run: | # Show paths echo "Paths: ${{ env.paths }}" # Get the list of paths being monitored monitored_paths=$(echo "${{ env.paths }}" | tr "," " ") echo "Monitored paths: $monitored_paths" echo "Changed files: ${{ steps.changes.outputs.files }}" echo "If you see here files that you have not modified, please update your branch with changes from main." # Loop through each path for path in $monitored_paths do # Check if the modified files include this path if echo "${{ steps.changes.outputs.files }}" | grep -q "$path"; then # Set the output variable and exit the loop echo "triggering_path is $path" echo "triggering_path=$path" >> $GITHUB_OUTPUT break fi done - name: Echo changed files run: echo ${{ steps.determine_path.outputs.triggering_path }} prod_tenant_plan: needs: get_changed uses: .github/workflows/lib-terraform-plan.yml@main with: WORKING_DIRECTORY: "${{ needs.get_changed.outputs.triggering_path }}" TF_VERSION: "1.4.2" TF_BACKEND_CONFIG: "key=${{ needs.get_changed.outputs.triggering_path }}terraform.tfstate" AWS_REGION: "us-west-2" ROLE_TO_ASSUME: "arn:aws:iam::xxxxxxxxxxxx:role/github" validate_tfsec: needs: get_changed uses: .github/workflows/lib-validate-tfsec.yml with: WORKING_DIRECTORY: ${{ needs.get_changed.outputs.triggering_path }} ``` - GitHub actions workflow to add at `.github/workflows/prod-tenants.yml` ```yaml --- name: Prod tenants on: pull_request: branches: - main paths: - '.github/workflows/prod-tenants.yml' - 'prod/tenants/**' types: ['labeled'] workflow_dispatch: env: paths: 'prod/tenants/*/' permissions: id-token: write contents: read jobs: get_changed: runs-on: ubuntu-latest outputs: triggering_path: ${{ steps.determine_path.outputs.triggering_path }} steps: - name: Checkout code uses: actions/checkout@v3 with: fetch-depth: 0 - name: Get changed files id: changes run: | echo "files=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | xargs)" >> $GITHUB_OUTPUT - name: Determine triggering path id: determine_path shell: bash run: | # Show paths echo "Paths: ${{ env.paths }}" # Get the list of paths being monitored monitored_paths=$(echo "${{ env.paths }}" | tr "," " ") echo "Monitored paths: $monitored_paths" echo "Changed files: ${{ steps.changes.outputs.files }}" echo "If you see here files that you have not modified, please update your branch with changes from main." # Loop through each path for path in $monitored_paths do # Check if the modified files include this path if echo "${{ steps.changes.outputs.files }}" | grep -q "$path"; then # Set the output variable and exit the loop echo "triggering_path is $path" echo "triggering_path=$path" >> $GITHUB_OUTPUT break fi done - name: Echo changed files run: echo ${{ steps.determine_path.outputs.triggering_path }} prod_tenant_apply: if: ${{ github.event.label.name == 'tf-apply' }} needs: get_changed uses: .github/workflows/lib-terraform-apply.yml with: WORKING_DIRECTORY: "${{ needs.get_changed.outputs.triggering_path }}" TF_VERSION: "1.4.2" TF_BACKEND_CONFIG: "key=${{ needs.get_changed.outputs.triggering_path }}terraform.tfstate" AWS_REGION: "us-west-2" ROLE_TO_ASSUME: "arn:aws:iam::xxxxxxxxxxxx:role/github" ```