From d8bd07138b72f0c72c1cdf06526f96a16c26faac Mon Sep 17 00:00:00 2001 From: Max Lobur Date: Thu, 6 Apr 2023 20:13:54 +0300 Subject: [PATCH] Add terratest-command for terraform module ChatOps (#143) * Add terraform-test-command for terraform module ChatOps * fix needs * Rename to terratest, update todos --- .github/workflows/rebuild-readme-command.yml | 1 + .github/workflows/terraform-fmt-command.yml | 1 + .github/workflows/terratest-command.yml | 216 +++++++++++++++++++ .github/workflows/test-command.yml | 1 + 4 files changed, 219 insertions(+) create mode 100644 .github/workflows/terratest-command.yml diff --git a/.github/workflows/rebuild-readme-command.yml b/.github/workflows/rebuild-readme-command.yml index 20198d0a..9bcd769a 100644 --- a/.github/workflows/rebuild-readme-command.yml +++ b/.github/workflows/rebuild-readme-command.yml @@ -1,3 +1,4 @@ +# TODO deprecate by adding a deprecation message back to PR name: Rebuild README on: repository_dispatch: diff --git a/.github/workflows/terraform-fmt-command.yml b/.github/workflows/terraform-fmt-command.yml index a9cc89af..094c1673 100644 --- a/.github/workflows/terraform-fmt-command.yml +++ b/.github/workflows/terraform-fmt-command.yml @@ -1,3 +1,4 @@ +# TODO deprecate by adding a deprecation message back to PR name: Format terraform files on: repository_dispatch: diff --git a/.github/workflows/terratest-command.yml b/.github/workflows/terratest-command.yml new file mode 100644 index 00000000..2c7007b1 --- /dev/null +++ b/.github/workflows/terratest-command.yml @@ -0,0 +1,216 @@ +name: terratest +on: + repository_dispatch: + types: [terratest-command] + +defaults: + run: + # We need -e -o pipefail for consistency with GitHub Actions's default behavior + shell: bash -e -o pipefail {0} + +jobs: + ack: + runs-on: ubuntu-latest + if: github.event.client_payload.github.payload.comment.id != '' + steps: + - name: "Add reaction" + uses: cloudposse/actions/github/create-or-update-comment@0.33.0 + with: + repository: ${{ github.event.client_payload.github.payload.repository.full_name }} + comment-id: ${{ github.event.client_payload.github.payload.comment.id }} + token: ${{ secrets.REPO_ACCESS_TOKEN }} + reactions: '+1' + + terratest: + runs-on: ubuntu-latest + container: cloudposse/test-harness:latest + env: + MAKE_INCLUDES: Makefile + steps: + - name: "Update GitHub Status for pending" + uses: docker://cloudposse/github-status-updater + with: + args: >- + -action update_state + -ref "${{ github.event.client_payload.pull_request.head.sha }}" + -repo "${{ github.event.client_payload.github.payload.repository.name }}" + -state pending + -context "test/terratest" + -description "Tests started by @${{ github.event.client_payload.github.actor }}" + -url "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + -owner "${{ github.event.client_payload.github.payload.repository.owner.login }}" + env: + GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} + + - name: "Checkout code for ChatOps" + uses: actions/checkout@v3 + with: + token: ${{ secrets.REPO_ACCESS_TOKEN }} + repository: ${{ github.event.client_payload.pull_request.head.repo.full_name }} + ref: ${{ github.event.client_payload.pull_request.head.ref }} + + - name: "Determine required terraform version" + shell: bash -x -e -o pipefail {0} + run: | + # Some legacy support is on 0.11 branches and we determine the Terraform version based on the target branch name + VERSION=$(cut -d/ -f1 <<<${BASE_REF}) + if [[ ${VERSION} != '0.11' ]]; then + TF012=0.12.31 + TF013=$(terraform-0.13 version --json | jq -r .terraform_version) + TF014=$(terraform-0.14 version --json | jq -r .terraform_version) + TF015=$(terraform-0.15 version --json | jq -r .terraform_version) + TF1=$(terraform-1 version --json | jq -r .terraform_version) + # vert exits non-zero if any of the versions are not acceptable, so `|| [[ -n "$VERSION" ]]` for a real error check + FULL_VERSION=$(vert -s "$(terraform-config-inspect --json examples/complete | jq -r '.required_core[]')" "$TF012" "$TF013" "$TF014" "$TF015" "$TF1" | head -1) || [[ -n "$VERSION" ]] + VERSION=${FULL_VERSION:0:4} + echo Full version to use is ${FULL_VERSION}, setting VERSION to ${VERSION} + fi + + # Match lables like `terraform/0.12` or nothing (to prevent non-zero exit code) + # Use [0-9] because \d is not standard part of egrep + OVERRIDE_VERSION=$(grep -Eo '(terraform/[0-9]+\.[x0-9]+|)' <<<${LABELS} | cut -d/ -f2) + + if [ -n "${OVERRIDE_VERSION}" ]; then + VERSION=${OVERRIDE_VERSION} + echo "Terraform ${VERSION} is required based on labels..." + else + echo "Terraform ${VERSION} is required for ${BASE_REF}..." + fi + + [[ $VERSION =~ ^1\. ]] && VERSION=1 + + PATH_TO_TERRAFORM="/usr/local/terraform/${VERSION}/bin" + if [ -x "${PATH_TO_TERRAFORM}/terraform" ]; then + echo "${PATH_TO_TERRAFORM}" >> "$GITHUB_PATH" + else + echo "Unable to locate executable for terraform ${VERSION}" >&2 + exit 1 + fi + env: + # Pull request target branch + BASE_REF: ${{ github.event.client_payload.pull_request.base.ref }} + LABELS: ${{ join(github.event.client_payload.pull_request.labels.*.name, '\n') }} + + - name: "Initialize terratest Go project" + run: | + make -C test/src clean init + rm -rf examples/*/.terraform examples/*/.terraform.lock.hcl + - name: "Inject secrets" + env: + USES_GITHUB: >- + ${{ contains(github.event.client_payload.github.payload.repository.name, '-github-') + || contains(github.event.client_payload.pull_request.labels.*.name, 'terraform-github-provider') }} + USES_OPSGENIE: >- + ${{ contains(github.event.client_payload.github.payload.repository.name, 'terraform-opsgenie-') + || contains(github.event.client_payload.pull_request.labels.*.name, 'terraform-opsgenie-provider') }} + USES_AWS: >- + ${{ contains(github.event.client_payload.github.payload.repository.name, 'terraform-aws-') + || contains(github.event.client_payload.pull_request.labels.*.name, 'terraform-aws-provider') }} + USES_SPOTINST: >- + ${{ contains(github.event.client_payload.github.payload.repository.name, '-spotinst-') + || contains(github.event.client_payload.pull_request.labels.*.name, 'terraform-spotinst-provider') }} + USES_DATADOG: >- + ${{ contains(github.event.client_payload.github.payload.repository.name, '-datadog-') + || contains(github.event.client_payload.pull_request.labels.*.name, 'terraform-datadog-provider') }} + USES_TFE: >- + ${{ contains(github.event.client_payload.github.payload.repository.name, '-tfe-') + || contains(github.event.client_payload.pull_request.labels.*.name, 'terraform-tfe-provider') }} + USES_CLOUDFLARE: >- + ${{ contains(github.event.client_payload.github.payload.repository.name, '-cloudflare-') + || contains(github.event.client_payload.pull_request.labels.*.name, 'terraform-cloudflare-provider') }} + + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} + OPSGENIE_API_KEY: ${{ secrets.OPSGENIE_API_KEY }} + DD_API_KEY: ${{ secrets.DD_API_KEY }} + DD_APP_KEY: ${{ secrets.DD_APP_KEY }} + SPOTINST_TOKEN: ${{ secrets.SPOTINST_TOKEN }} + SPOTINST_ACCOUNT: ${{ secrets.SPOTINST_ACCOUNT }} + TFE_TOKEN: ${{ secrets.TFE_TOKEN }} + CLOUDFLARE_EMAIL: ${{ secrets.CLOUDFLARE_EMAIL }} + CLOUDFLARE_API_KEY: ${{ secrets.CLOUDFLARE_API_KEY }} + shell: bash + run: | + if [[ "$USES_AWS" == "true" || "$USES_DATADOG" == "true" || "$USES_SPOTINST" == "true" ]]; then + printf "%s=%s\n" AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID" >> "$GITHUB_ENV" + printf "%s=%s\n" AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY" >> "$GITHUB_ENV" + echo exported AWS + fi + if [[ "$USES_DATADOG" == "true" ]]; then + printf "%s=%s\n" DD_API_KEY "$DD_API_KEY" >> "$GITHUB_ENV" + printf "%s=%s\n" DD_APP_KEY "$DD_APP_KEY" >> "$GITHUB_ENV" + echo exported Datadog + fi + if [[ "$USES_GITHUB" == "true" ]]; then + printf "%s=%s\n" GITHUB_TOKEN "$GITHUB_TOKEN" >> "$GITHUB_ENV" + echo exported GitHub + fi + if [[ "$USES_OPSGENIE" == "true" ]]; then + printf "%s=%s\n" OPSGENIE_API_KEY "$OPSGENIE_API_KEY" >> "$GITHUB_ENV" + echo exported Opsgenie + fi + if [[ "$USES_SPOTINST" == "true" ]]; then + printf "%s=%s\n" SPOTINST_TOKEN "$SPOTINST_TOKEN" >> "$GITHUB_ENV" + printf "%s=%s\n" SPOTINST_ACCOUNT "$SPOTINST_ACCOUNT" >> "$GITHUB_ENV" + echo exported Spotinst + fi + if [[ "$USES_TFE" == "true" ]]; then + printf "%s=%s\n" TFE_TOKEN "$TFE_TOKEN" >> "$GITHUB_ENV" + echo exported Terraform Cloud + fi + if [[ "$USES_CLOUDFLARE" == "true" ]]; then + printf "%s=%s\n" CLOUDFLARE_EMAIL "$CLOUDFLARE_EMAIL" >> "$GITHUB_ENV" + printf "%s=%s\n" CLOUDFLARE_API_KEY "$CLOUDFLARE_API_KEY" >> "$GITHUB_ENV" + echo exported CloudFlare + fi + + - name: "Test `examples/complete` with terratest" + run: make -C test/src + + - name: "Update GitHub Status for failure" + if: ${{ failure() }} + uses: docker://cloudposse/github-status-updater + with: + args: >- + -action update_state + -ref "${{ github.event.client_payload.pull_request.head.sha }}" + -repo "${{ github.event.client_payload.github.payload.repository.name }}" + -state failure + -context "test/terratest" + -description "Tests failed" + -url "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + -owner "${{ github.event.client_payload.github.payload.repository.owner.login }}" + env: + GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} + + - name: "Update GitHub Status for this success" + uses: docker://cloudposse/github-status-updater + with: + args: >- + -action update_state + -ref "${{ github.event.client_payload.pull_request.head.sha }}" + -repo "${{ github.event.client_payload.github.payload.repository.name }}" + -state success + -context "test/terratest" + -description "Tests passed" + -url "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + -owner "${{ github.event.client_payload.github.payload.repository.owner.login }}" + env: + GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} + + - name: "Update GitHub Status for cancelled" + if: ${{ cancelled() }} + uses: docker://cloudposse/github-status-updater + with: + args: >- + -action update_state + -ref "${{ github.event.client_payload.pull_request.head.sha }}" + -repo "${{ github.event.client_payload.github.payload.repository.name }}" + -state error + -context "test/terratest" + -description "Tests cancelled" + -url "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + -owner "${{ github.event.client_payload.github.payload.repository.owner.login }}" + env: + GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} diff --git a/.github/workflows/test-command.yml b/.github/workflows/test-command.yml index a1d2d709..9264fae4 100644 --- a/.github/workflows/test-command.yml +++ b/.github/workflows/test-command.yml @@ -1,3 +1,4 @@ +# TODO deprecate by adding a deprecation message back to PR name: test on: repository_dispatch: