From cc700a2fde52e91cce2b38f94181ae223182a0ac Mon Sep 17 00:00:00 2001 From: MxNxPx Date: Tue, 29 Oct 2024 14:56:20 -0400 Subject: [PATCH] ci: add tofu ci checks --- .github/actions/terraform-test/action.yaml | 20 ++++++ .github/actions/tofu-format/action.yaml | 78 ++++++++++++++++++++++ .github/actions/tofu-scan/action.yaml | 27 ++++++++ .github/workflows/validate.yaml | 25 +++++++ .gitignore | 44 +++++++++++- 5 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 .github/actions/terraform-test/action.yaml create mode 100644 .github/actions/tofu-format/action.yaml create mode 100644 .github/actions/tofu-scan/action.yaml create mode 100644 .github/workflows/validate.yaml diff --git a/.github/actions/terraform-test/action.yaml b/.github/actions/terraform-test/action.yaml new file mode 100644 index 0000000..5bddb89 --- /dev/null +++ b/.github/actions/terraform-test/action.yaml @@ -0,0 +1,20 @@ +name: Terraform Validate +description: Runs a test on the terraform + +inputs: + target: + description: Target directory + required: true + +runs: + using: composite + steps: + - name: Tofu Format + uses: ./.github/actions/tofu-format + with: + target: ${{ inputs.target }} + + - name: Tofu Scanning + uses: ./.github/actions/tofu-scan + with: + target: ${{ inputs.target }} diff --git a/.github/actions/tofu-format/action.yaml b/.github/actions/tofu-format/action.yaml new file mode 100644 index 0000000..b52bf05 --- /dev/null +++ b/.github/actions/tofu-format/action.yaml @@ -0,0 +1,78 @@ +name: Tofu Format +description: Ensures proper Tofu formatting + +inputs: + target: + description: Target directory + required: true + +runs: + using: composite + steps: + - uses: opentofu/setup-opentofu@ae80d4ecaab946d8f5ff18397fbf6d0686c6d46a # v1.0.3 + with: + tofu_version: 1.6.2 + + - name: Tofu Format + id: fmt + run: tofu fmt + shell: bash + working-directory: './${{ inputs.target }}/' + continue-on-error: true + + # Use the GraphQL API to commit changes, so we get automatic commit signing + # The REST contents API can't be used as easily because it only supports making single file commits + - name: Commit and push changes + shell: bash + env: + GITHUB_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + additions=() + removed=() + while IFS= read -r -d $'\0' status_line; do + filename="${status_line:3}" + git_status="${status_line:0:2}" + if [ "$git_status" = "D " ]; then + removed+=("$filename") + else + additions+=("$filename") + fi + done < <(git status --porcelain=v1 -z) + if [ "${#additions[@]}" -eq 0 ] ; then + echo "No files updated, skipping commit" + exit 0 + fi + commitMessage="chore: tofu fmt" + # for now, we ignore $removed files, but they could be handled similarly (it's just harder to send two lists of positional input files into jq) + # jq's iteration over inputs will skip over files with 0 lines (empty files) + jq \ + --null-input \ + --raw-input \ + --arg repositoryNameWithOwner "${{ github.event.client_payload.github.payload.repository.full_name || github.event.repository.full_name }}" \ + --arg branchName "${{ github.event.client_payload.pull_request.head.ref || github.event.pull_request.head.ref || github.ref_name }}" \ + --arg expectedHeadOid "${{ github.event.client_payload.pull_request.head.sha || github.event.pull_request.head.sha || github.sha }}" \ + --arg commitMessage "$commitMessage" \ + ' + { + "query": "mutation ($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { url } } }", + "variables": { + "input": { + "branch": { + "repositoryNameWithOwner": $repositoryNameWithOwner, + "branchName": $branchName + }, + "message": { + "headline": $commitMessage + }, + "fileChanges": { + "additions": [reduce inputs as $line ({}; .[input_filename] += [$line]) | map_values(join("\n")) | to_entries[] | {path: .key, contents: .value | @base64}] + }, + "expectedHeadOid": $expectedHeadOid + } + } + }' "${additions[@]}" | curl https://api.github.com/graphql \ + --silent \ + --fail-with-body \ + --oauth2-bearer "$(gh auth token)" \ + --data @- diff --git a/.github/actions/tofu-scan/action.yaml b/.github/actions/tofu-scan/action.yaml new file mode 100644 index 0000000..9e24635 --- /dev/null +++ b/.github/actions/tofu-scan/action.yaml @@ -0,0 +1,27 @@ +name: Tofu Scan +description: Scan using common checks in Tofu + +inputs: + target: + description: Target directory + required: true + +runs: + using: composite + steps: + - uses: terraform-linters/setup-tflint@19a52fbac37dacb22a09518e4ef6ee234f2d4987 # v4.0.0 + name: Setup TFLint + with: + tflint_version: latest + + - name: Init TFLint + run: tflint --init + shell: bash + env: + # https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/plugins.md#avoiding-rate-limiting + GITHUB_TOKEN: ${{ github.token }} + + - name: Run TFLint + run: tflint --recursive -f compact + working-directory: './${{ inputs.target }}/' + shell: bash diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml new file mode 100644 index 0000000..b3cda80 --- /dev/null +++ b/.github/workflows/validate.yaml @@ -0,0 +1,25 @@ +# This reusable workflow plans a given environment (IAC + Validate Bundle availability) +name: Validate +on: + pull_request: + types: + - opened + - reopened + - synchronize + branches: + - main + +permissions: + contents: write + id-token: write + pull-requests: write + packages: read + +jobs: + terraform_checks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/terraform-test + with: + target: modules diff --git a/.gitignore b/.gitignore index 0d7d247..86bc5e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,42 @@ -**/.terraform* -**/*.tfstate* +# Local .terraform directories +**/.terraform +**/.terraform.lock.hcl + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json +!*ci-*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# Ignore any key material +*.der +*.pem +*.csr +*.srl