最近、アプリケーションのインフラ改修でTerraformを活用しています。
PRレビューでレビュワーにterraform plan
を実行してもらう手間がなかなか面倒だったので、GitHub Actionsのワークフローでterraform plan
の結果をコメントとして自動投稿する仕組みをつくりました。
ワークフローの概要
このワークフロー(.github/workflows/infrastructure-checks.yml
)は、master向けのPRが作成もしくは更新されるたびに実行されます。
以下がワークフローの中身です。
name: 'Infrastructure Checks'
on:
pull_request:
branches:
- master
types: [opened, synchronize]
jobs:
terraform:
name: 'Terraform Checks'
runs-on: ubuntu-latest
strategy:
matrix:
# stg, prodは未使用のため一旦コメントアウト
# directory: ['environments/dev', 'environments/stg', 'environments/prod']
directory: ['environments/dev']
defaults:
run:
working-directory: ${{ matrix.directory }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
- name: Setup 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
- name: Terraform Format
id: fmt
run: terraform fmt -check
- name: Check if directory is not empty
id: check
run: |
if [ "$(ls -A .)" ]; then
echo "Directory is not empty"
else
echo "Directory is empty"
exit 1
fi
- name: Terraform Init
id: init
run: terraform init
- name: Terraform Plan
id: plan
run: terraform plan -no-color
continue-on-error: true
- name: Comment PR
uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outputs.stdout }}\`
#### Terraform Initialization ⚙️\`${{ steps.init.outputs.stdout }}\`
#### Terraform Plan 📖\`${{ steps.plan.outputs.stdout }}\``;
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Terraform checks in directory '${{ matrix.directory }}'\n` + output
})
ワークフローの詳細
- Checkout: リポジトリをチェックアウトする(コードをGitHubの実行環境にダウンロードする)。
- Setup Terraform: ワークフローがTerraformコマンドを使用できるようにする。
- Setup AWS Credentials: AWSの認証情報をセットアップする。TerraformがAWSのリソースを管理できる。
- Terraform Format: Terraformのフォーマットをチェックする。フォーマットが一貫していることで、コードの可読性と保守性が向上する。
- Check if directory is not empty: ディレクトリ
environments/dev
が空でないことを確認する。 - Terraform Init: Terraformを初期化する。Terraformが後続のステップでリソースを管理できるようになる。
- Terraform Plan:
terraform plan
を実行する。変更内容がPRにコメントとして投稿される。 - Comment PR: Terraformの各ステップの結果をPRにコメントとして投稿する。
補足
PR作成後のプッシュで変更が生じた場合にもワークフローが実行されるようにするために、typesにsynchronize
を追加しています。
on:
pull_request:
branches:
- master
types: [opened, synchronize]
また、環境ごとの構成(dev, stg, prodなど)についてそれぞれTerraformチェックを行いたい場合は、strategy.matrix
を使用して各ディレクトリを列挙します。
terraform:
name: 'Terraform Checks'
runs-on: ubuntu-latest
strategy:
matrix:
directory: ['environments/dev', 'environments/stg', 'environments/prod']
run:
working-directory: ${{ matrix.directory }}
ステップ3で設定しているAWSの認証情報(AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
)は、IAMユーザーの作成後にGitHub Secretsに登録します。
- GitHubで対象のリポジトリに移動する。
- リポジトリのメインページの右上にある「Settings」(設定)タブをクリックする。
- 左側のメニューから「Secrets」を選択する。
- 「New repository secret」ボタンをクリックする。
- 「Name」フィールドにシークレットの名前を入力する。
- 「Value」フィールドにシークレットの値を入力する。
- 「Add secret」ボタンをクリックしてシークレットを保存する。
また、IAMユーザーにアタッチするIAMポリシーは、Terraformで管理するリソースにあわせて設定します。
terraform plan
は読み取り専用の操作となるので、もしEC2のリソースを管理するのであれば、AmazonEC2ReadOnlyAccess
のようなマネージドポリシーをアタッチします。