terraformのコードをGitHub Actionsで構文チェックする
はじめに
terraformのコードをgithub-actionsでコードチェック(fmt, validate)する設定を書きました。
ワークフローは github/workflows
にyamlファイルをセットすれば実行されます。
- 今回の実行内容
- mainブランチに対して "pull request" を作成したときに実行
- 連携は "terraform-cloud"
- terraform { fmt | init | validate } を実行
- fmtの結果をPRのCommentに出力
- 複数ディレクトリに対して実行
ソースコード
GitHub Actionsワークフローの構文については以下を参照。
GitHub Actionsのワークフロー構文 - GitHub Docs
■ 利用する "Terraform" の GitHub Actions
以前までは以下を利用していましたが、サポートが終了していたので変更しました。
■ (新) hashicorp/setup-terraform
と (旧) hashicorp/terraform-github-actions
の違い
"hashicorp/terraform-github-actions" は step毎に hashicorp/terraform-github-actions@master
を指定して
"with" で "subcommand" 等を指定して実行していました。
- name: Validate uses: hashicorp/terraform-github-actions@master with: tf_actions_version: ${{ env.TF_VERSION }} tf_actions_subcommand: validate tf_actions_cli_credentials_token: ${{ env.TF_ACTIONS_CLI_CREDENTIALS_TOKEN }}
"hashicorp/setup-terraform" は最初に terraformの実行環境をセットアップしてから実行コマンドを定義していく形に変更になっています。 こっちの方が直感的にわかりやすくて個人的に好きですね。
■ 利用する "checkout" の GItHub Actions
steps: - name: Setup Terraform uses: hashicorp/setup-terraform@v1 with: terraform_version: ${{ env.TF_VERSION }} - name: Configure TF Cloud uses: hashicorp/setup-terraform@v1 with: cli_config_credentials_hostname: ${{ env.TF_HOSTNAME }} cli_config_credentials_token: ${{ env.TF_API_TOKEN }} # terraform fmt - name: Terraform fmt id: fmt working-directory: ${{ matrix.workdir }} run: terraform fmt # run: terraform fmt -recursive -check continue-on-error: true # terraform init - name: Terraform init working-directory: ${{ matrix.workdir }} run: terraform init
■ PRにコメント投稿するために利用する GItHub Actions
- terraform fmtの結果を環境変数にセットする
steps.${id}.outputs.stdout
: stepでid
を指定すると利用できる- "```" は markdown記法のコードで出力する
${process.env.FMT}
で内容を出力する
- uses: actions/github-script@v4 if: ${{ contains(steps.fmt.outputs.stdout, '.tf') }} env: FMT: "```terraform\n${{steps.fmt.outputs.stdout}}```" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const output = `<details><summary>terraform fmt:</summary>\n\n${process.env.FMT}\n\n</details>`; github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output })
■ github actionを複数実行する
今回は workdirの 3ディレクトリをチェックするので、
jobs.<job_id>.strategy.matrix
で単一のジョブの定義内の変数の置き換えを行い複数のジョブを作成する。
strategy: fail-fast: false # default=true matrix: workdir: [ "./terraform/aws", "./terraform/org_a", "./terraform/org_b" ]
jobs.<job_id>.strategy.matrix
を使った結果- それぞれのディレクトリに対してジョブを実行
■ terraform fmtの結果に応じてコメントを入れる
.tf
が含まれる場合にコメントを書き込む処理を実施する
- uses: actions/github-script@v4 if: ${{ contains(steps.fmt.outputs.stdout, '.tf') }}
■ ソースコード全体
.github/workflows/terraform.yaml
name: Terraform on: pull_request: branches: - main paths: - "terraform/**.tf" - ".github/workflows/terraform.yaml" env: TF_HOSTNAME: "app.terraform.io" TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }} TF_VERSION: 1.0.11 jobs: terraform_check: runs-on: ubuntu-latest continue-on-error: true strategy: fail-fast: false # default=true matrix: workdir: [ "./terraform/aws", "./terraform/org_a", "./terraform/org_b" ] steps: - name: Setup Terraform uses: hashicorp/setup-terraform@v1 with: terraform_version: ${{ env.TF_VERSION }} - name: Configure TF Cloud uses: hashicorp/setup-terraform@v1 with: cli_config_credentials_hostname: ${{ env.TF_HOSTNAME }} cli_config_credentials_token: ${{ env.TF_API_TOKEN }} # git checkout - name: Checkout uses: actions/checkout@v2 # terraform fmt - name: Terraform fmt id: fmt working-directory: ${{ matrix.workdir }} run: terraform fmt # run: terraform fmt -recursive -check continue-on-error: true # terraform init - name: Terraform init working-directory: ${{ matrix.workdir }} run: terraform init # terraform validate - name: Terraform validate id: validate working-directory: ${{ matrix.workdir }} run: terraform validate # post fmt results - uses: actions/github-script@v4 if: ${{ contains(steps.fmt.outputs.stdout, '.tf') }} env: FMT: "```terraform\n${{steps.fmt.outputs.stdout}}```" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const output = `<details><summary>terraform fmt:</summary>\n\n${process.env.FMT}\n\n</details>`; github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output })