Terraform × GitHub Actions で作る Dev CI/CD パイプライン
Terraform を使ったインフラ管理は便利だが、運用が進むにつれてこんな悩みが出てくる。
terraform fmtやvalidateを毎回手でやるのが正直めんどくさい- lint やセキュリティチェックを「やったつもり」で終わらせがち
- PR の差分を見ても「結局何が変わるのか」が分かりづらい
これらを人力でカバーし続けるのは、スピードと安全性の両立という点で限界がある。
そこで本記事では、 Terraform + GitHub Actions を使って、lint・静的解析・plan/apply を自動化したCI/CD パイプライン を紹介する。
このパイプラインの目的はシンプルだ。
- 面倒になりがちな lint / 静的解析を強制的に自動化する
- PR 時に 「何が変わるのか」をレビューしやすくする
- main マージ後は 自動的に apply まで実行してmainと実際のインフラの差分をなくす
実際のコード
以下は、本記事で紹介している CI/CD パイプラインの GitHub Actions 定義そのもの。
このコードはGoogle Cloudを使った例である。しかしCI/CD自体は他のクライドプロバイダーでも構築することは可能。
この記事ではGitHub Actions の書き方や各ステップのコードの細かい解説は行わない。
以降では、各工程の役割について解説していく。
ジョブ1:Lint と静的解析
ステップ1:terraform fmt
terraform fmt は、Terraform のコードを 公式ルールに従って整形できる/されているかを判定できるコマンドだ。
このパイプラインでは実際にコードを書き換えるのではなく、 fmt --check を使って 「フォーマットが正しいかどうか」だけを検査している。
これにより、
- フォーマットが崩れたコードは PR の時点で検出される
- CI が自動で書き換えることはせず、修正は開発者に委ねる
- フォーマット差分が紛れ込んだまま main に入ることを防げる
ステップ2:terraform validate
terraform validate は、Terraform の設定が 文法的に正しく、Terraform として解釈可能かを確認するためのコマンドだ。
リソースや変数の参照ミス、型の不整合など、 実行前に必ず潰しておくべき致命的なエラーを検出してくれる。
ステップ3:TFLint
TFLint は、Terraform のコードを 静的に解析し、問題になりやすい記述を早い段階で検出するためのツールだ。
terraform validate が 「文法的に正しいか」「Terraform として解釈できるか」 を確認するのに対し、TFLint はそれより一段踏み込んで、例えば、
- 定義されているが、どこからも参照されていない変数
- 使われていない local や module output
などを検出してくれる。
ステップ4:Checkov
Checkov は、Terraform のコードを対象に セキュリティや設定ミスの観点から静的解析を行うツールだ。
terraform validate や TFLint が 「書けるか」「おかしくないか」を見るのに対し、Checkov は
- パブリック公開すべきでないリソースが開いていないか
- 暗号化やログ設定が不足していないか
- よくあるセキュリティ事故につながる構成になっていないか
といった 運用・セキュリティ寄りの問題を検出する。
コード上は正しく、動作もするが、 「そのまま本番に出すには危険な設定」 を PR の段階で機械的に洗い出せるのが強みだ。
ステップ5:tfsec
tfsec は、checkovと同じくTerraform のコードを対象に セキュリティ観点で静的解析を行うツールだ。
Checkov と役割が重なる部分はあるが、 検出できるルールが完全に同じではない。そのため、このパイプラインでは tfsec も併用している。
セキュリティはインフラで重要な分野なので、冗長に感じるかもしれないが、二重で組み込んでいる。
ジョブ2:Plan
Terraform plan(tfcmt)
このジョブでは、PR 作成時に terraform plan を実行し、 その変更が実際にどのような差分を生むのかを可視化する。
tfcmt を使うことで、 terraform plan の結果が PR のコメントとして投稿され、 レビュー時にコードと変更内容を同時に確認できるようになる。

これにより、
- どのリソースが追加・変更・削除されるのか
- 意図しない変更が含まれていないか
を、レビュアーが把握しやすくなる。
マージの判断と apply のタイミング
このパイプラインでは、 lint・静的解析・plan までのすべてが問題なく通った時点で、 PR を main ブランチにマージする。
この構成ではマージ前に apply を行わず、 main ブランチにマージされた内容だけを apply する。
こうすることで、
- apply 済みの状態と main ブランチの差分が発生しない
という状態を保てる。
以降の apply は、 このマージ判断を前提として自動で実行される。
ジョブ3:Apply
Job3 では、PR が main ブランチにマージされたことをトリガーに terraform apply を実行する。
なお、ここまでのcheckが通ってもterraform apply が失敗する可能性がゼロになるわけではない。
そのため本構成では、 apply 失敗時の運用ルールをあらかじめ決めておくことが重要だと考えている。
例えば、
- 失敗を検知したら、即座に修正パッチを作成する
- 原因を解消したうえで、再度 main にマージする
- 必要であれば変更を巻き戻す
といった対応である。
追加の選択肢:Infracost
Terraform の CI に組み込めるツールとして、 Infracost も有力な選択肢のひとつだ。
Infracost を使うと、
- Terraform の変更によって発生する インフラコストの増減
- 月額ベースでのおおよその料金差分
を、PR の段階で可視化できる。

これにより、
- 意図せず高額なリソースを追加していないか
- 小さな変更のつもりが、コスト的に大きな影響を持たないか
といった点を、 apply 前に確認できるようになる。
本パイプラインでは Infracost は CI には組み込んでいないが、 これは不要だからではなく、 GitHub Apps としてのセットアップが非常に簡単だったためだ。
現在は、PR を作成すると この CI/CD パイプラインとは独立して Infracost が並行して実行され、PR 上に結果が表示される という形で運用している。
ただこれには複数Repositoryで使いまわすには追加で設定する必要があるなどデメリットもある。
CI に直接組み込むか、GitHub Apps として併用するかは、 チームの運用や好みに応じて選べばよい。
まとめ
この CI/CD パイプラインでは、 Terraform 運用で面倒になりがちな工程を自動化しつつ、 レビューと判断のしやすさを重視して設計している。
この構成が、 Terraform を使ったインフラ管理のひとつの参考になれば幸いである。