LoginSignup
8
5

More than 3 years have passed since last update.

[Terraform]GithubActionsでTerraformリポジトリのCIを行う

Last updated at Posted at 2020-10-17

概要

Github Actionsを使って、Terraformリポジトリの継続的インテグレーションが行えるようになるまでの設定手順をハンズオンライクに記載します。
Githubに機密情報を預けたくないという方には向きません。

前提

  • Githubでtfファイルを管理している
  • AWSアカウントを保持している

CIでチェックする内容

こちらの記事を参照ください。

Github Actionsの設定

完成形はこちらを参照ください。

特徴

CodeBuildでの設定と比べ以下のような特徴があります。

○ 設定方法が容易
○ 並列実行も可能
△ AWSやTerraform CloudのCredentialをGithubに記録する必要がある

CredentialsをGithub上に管理する必要がある点が引っかかる方は、CodeBuildによるCIをおすすめします。AWS上で実行するので、AWSのCredentialsは不要であり、その他のCredentialsはSSM Parameter-StoreでKMSを用いて機密データを保管することが可能です。

ディレクトリ構成

リポジトリのディレクトリ構成は以下のようにします。

├── .github/
│  └── workflows/
│     └── terraform_ci.yml # Actionsの設定ファイル
├── environments/          # CIの対象ファイル群
│  └── aws/
│     ├── development/
│     └── practice/
└── scripts/
   └── ci/                 # スクリプト群

設定ファイルの記述

GithubActionsはワークフロー実行のファイルを記載するだけで設定は完了となります。
しかもTerraform CI/CDやAWS/GCP等のパブリッククラウドへのデプロイなどワークフローテンプレートが用意されているため、これをベースに多少カスタマイズするだけで使用開始することができます。
今回もGithubで用意されているテンプレートをベースにカスタマイズしていきましょう。
テンプレートを取得するためには、リポジトリのActionsタブを押下し、Terraformを選択します。
スクリーンショット 2020-07-06 0.11.51.png
テンプレートが表示されるため、いったん右上のStart Commitでファイルを作成しましょう。

テンプレートの設定概要

ここで作成したテンプレートは以下の前提で作られています。

  • masterブランチへのpushおよびPR作成・更新時にワークフローが実行される
  • リポジトリのルートディレクトリに対象のtfファイルが存在する
  • ステートファイルをTerraform Cloudで管理している、またplan等のコマンドをTerraform Cloud上で実行する
  • fmtplanを実行する
  • masterブランチへのpushを契機に、applyを実行する

今回、この前提とは異なる部分に対してカスタマイズを行っていきます。すなわち、

  • AWSのcredentialsを読み込む
  • コマンドはGithub上で実行する
  • applyは実行しない
  • validate tflintも実行する
  • environmentsディレクトリ以下の各環境別にCIを実行する

の変更を加えていきます。

AWSのcredentialsを読み込む

まずリポジトリにAWSとTerraformCloud(ステート管理で使用している場合)のcredentialsを登録します。
リポジトリの Settings → Secretsより、以下の環境変数名で登録します。

シークレット名称 概要
AWS_ACCESS_KEY_ID AWSのアクセスキーID
AWS_SECRET_ACCESS_KEY AWSのシークレットアクセスキー
TF_API_TOKEN Terraform Cloudの認証トークン

このままではAWS認証情報は読み込まれないので、checkoutstepの次にcredentialsをセットするstepを追加します。

terraform_ci.yml
- name: Configure AWS Credentials
  uses: aws-actions/configure-aws-credentials@v1
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: ap-northeast-1

コマンドはGithub上で実行する

これはTerraform Cloudでステート管理している場合に限ります。(S3やGCSで管理している場合は必然的にGithub Actions上でコマンドが実行されるため、気にする必要がありません。)
Settings → General より Execution ModeをLocalに設定します。(デフォルトだとRemote

スクリーンショット 2020-07-06 0.27.38.png

applyは実行しない

CIにフォーカスするという意味でです。単純に以下のapplyの行を削除、またはコメントアウトするだけです。

terraform_ci.yml
- name: Terraform Apply
  if: github.ref == 'refs/heads/master' && github.event_name == 'push'
  run: terraform apply -auto-approve

validate tflintも実行する

validateはterraform validateで実行可能なので、これは(initより下に)stepとして追加するだけで完了です。

terraform_ci.yml
- name: Terraform Validate
  id: validate
  run: terraform validate -no-color

tflintterraformのコマンドではないため、reviewdog/action-tflintを利用します。こちらは誤りのある部分をPRにレビューコメントしてくれるという機能もついています。せっかくなので利用する設定にしてみます。
スクリーンショット 2020-07-06 0.38.26.png

コマンドがinit前提のためinitより下にstepを追加します。

terraform_ci.yml
- name: TFLint
  uses: reviewdog/action-tflint@master
  with:
    github_token: ${{ secrets.github_token }}
    reporter: github-pr-review                 # PRにコメントする
    fail_on_error: true

environmentsディレクトリ以下の各環境別にCIを実行する

Github Actionsに用意されているstrategy.matrixを利用して、複数ディレクトリのCIを実現します。
なお、この場合、ワークフローはmatrixに設定した数分だけ(並列して)実行されます。
matrix部分が直書きのため、対象環境が増えた場合に書き足す必要があります。この部分をうまく解決する方法を思いつきませんでした。。。
特定のディレクトリのみ実施したい場合は、strategy.matrixは必要なく、working-directoryを対象ディレクトリに設定すればよいです。

terraform_ci.yml
terraform-ci:
  name: Terraform
  strategy:
    matrix:
      env: [practice, development]  # ここに対象環境名を羅列

  runs-on: ubuntu-latest

  defaults:
    run:
      shell: bash
      working-directory: ./environments/aws/${{ matrix.env }}  # このディレクトリでこれ以下のコマンドを実行していく

変更をpush

ここまででカスタマイズは完了です。設定ファイルの変更をコミットしてみましょう。
Actionsタブにてワークフローが実行されていることを確認できたら、正常に稼働しています!

Options1. CIの結果をPRにコメントする

上記までの設定でCIが実行されるようになりましたが、その結果はActionsタブの実施結果→対象stepを見る必要があります。しかしPR上でその確認まで済ませたいというケースもあるでしょう。そこで、CI実行結果をPRにコメントとして記載するような設定を追加してみます。また、一度のワークフローですべてのチェックを行うことができる点も魅力です。
ただし、fmt等に失敗しても、CIの実行ステータス自体はCompleteとなる点に注意してください。(うまく実行結果をチェックする機構をとれば可能かもしれません。)トレードオフで導入有無を選択ください。

各コマンドで失敗しても、ワークフローを中断しない

すべての結果を一度に見たいため、ワークフローを最後まで走らせる必要があります。そこでfmtvalidateplanにエラー時も次へ進む設定を追記します。また、stepのidも振っておきましょう。

terraform_ci.yml
- name: Terraform Validate
  id: validate                      # ここを追記
  run: terraform validate -no-color
  continue-on-error: true           # ここを追記

コメント通知の実装

公式ReadmeOutputs can be used in subsequent steps to comment on the pull requestの例をほぼそのまま利用します。
steps.<STEP>.outcomeはそのstepの実行結果(success、failure、cancelled、skippedのいずれか)、steps.<STEP>.outputs.stdoutはそのコマンドの実行結果標準出力を表しています。

terraform_ci.yml
# 一番最後のstepとして定義
- uses: actions/github-script@0.9.0
  if: github.event_name == 'pull_request'  # PR作成・更新時だけ実行する
  env:
    PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    script: |
      const output = `## \`${{ matrix.env }}\`
      #### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
      #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
      #### Terraform Validation 🤖${{ steps.validate.outputs.stdout }}
      #### Terraform Plan 📖\`${{ steps.plan.outcome }}\`

      <details><summary>Show Plan</summary>

      \`\`\`${process.env.PLAN}\`\`\`

      </details>

      *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Workflow: \`${{ github.workflow }}\`*`;

      github.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: output
      })

次のようにPRに実行結果がコメントされるようになります。
スクリーンショット 2020-07-06 1.16.55.png

Options2. strategy.matrixを使わずに複数ディレクトリのCI

これはCodeBuild実行時に使用した方法と同様で、ラッパースクリプトを作成し、その中で対象のディレクトリを列挙、コマンドを実行するといった流れです。以下のような特徴があります。

  • ワークフローは単一のものとなる
  • 対象ディレクトリが増えた場合も、CI設定の変更は不要
  • ラッパースクリプトを作成する必要がある
  • tfnotifyを利用する場合、pull_requestイベントではうまく発火されない(これは設定が悪いのかもしれません)

なお、ラッパースクリプトはこちらの記事で作成したものとほぼ同様なので参照ください。本記事では差分のみを記載します。

GithubActions設定ファイル作成

基本の流れは変わりません。以下の点を変更する程度となります。

  • strategy.matrixは使用しない
  • 各stepではラッパースクリプトを実行する
terraform_ci2.yml
runs-on: ubuntu-latest
defaults:
  run:
    shell: bash
    working-directory: .
############## 中略 ##############
- name: Install Dependent Packages
    run: ./scripts/ci/install_packages.sh

- name: Terraform Format Check
    run: ./scripts/ci/format.sh
############## 以下同様 ##############

tfnotifyをGithubActions対応とする

1行目のciの記述を変更するのみです。それ以外は、そのままで使いまわしが可能です。

terraform_ci2.yml
ci: github-actions

また、これはtfnotify側の問題なのかこちらの設定が悪いのかが不明ですが、pull_request実行の場合だとうまくPRにコメントがつきませんでした。また、label設定もうまく機能しませんでした。こちら情報ありましたら提供願います。:pray:

terraform_ci2.yml
on:
  push:
  # どうもGithub-Actions上でtfnotifyはpushでないと動かない様子
  #   branches:
  #     - master
  #     - development
  # pull_request:

PRにnotifyはされるようになるので、最低限やりたいことはクリアできていると思います。
スクリーンショット 2020-07-06 1.41.07.png

References

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5