【NIC x Ops(にこぷす)通信】(Terraform編)環境構築スクリプト(setup.ps1)と pre-commit × AI自律化で実現するコード品質管理ガイド
投稿者:清水
目次
- はじめに:インフラ開発における環境構築と品質維持の課題
- ローカル環境自動構築スクリプト(setup.ps1)の準備
- コード品質とAI自律化の仕組み
- 品質チェックの検証と動作確認テスト(エビデンス)
- まとめ
皆さま、こんにちは!
このテックブログでは、IT運用に関する内容を連載、「にこぷす通信」をお届けしています。
「NIC x Ops(にこぷす)」とは?
『NIC x Ops(にこぷす)』とは、
私たちの会社であるNTTインテグレーション(NI+C)の運用ノウハウと、
IBMさんの強力なソリューションを
Collaboration(コラボレーション)させた、IT運用高度化シリーズ(Ops)のニックネームなんです。
現代のIT運用の現場は、システムの複雑化や人手不足など、課題が山積みです。そんな現場を少しでも楽に、そしてエンジニアの皆さんが笑顔で「攻めの運用」ができるように支えたい。そんな想いがこの「にこぷす」には込められています。
「にこぷす」には、Instana(可観測性)のほかにも、Turbonomic(リソース最適化)やTerraform(インフラ自動化)など、IT運用を劇的に変える製品がたくさんあります。
これからもこの通信を通して、「IT用語は難しいけれど、中身を知ればこんなに便利で面白いんだ!」というテクニカルな内容をご紹介していきますので、どうぞよろしくお願いします。
1.はじめに:インフラ開発における環境構築と品質維持の課題
Terraformを用いたインフラ開発では、メンバーごとの開発環境の違い(ツールのバージョン違いやパス設定など)や、コードフォーマット・静的解析・ドキュメント作成の手動作業による手間や漏れが課題になりがちです。
本記事では、開発メンバーがコマンド一発で標準的な開発環境をセットアップできるローカル自動構築スクリプト(PowerShell)の作成と、pre-commitフックおよびAIエージェントによるコード品質の自律自動化の仕組み、そしてそれらの動作検証テスト結果について詳しく解説します。
💡連載シリーズについて
本シリーズ(全3回)では、この強力な連携による開発効率化を順を追って解説します。
- 第1回:導入編 — 自律型AI「IBM Bob」を使いこなす!基本操作からCLAUDE.mdでのプロジェクト規定、MCP連携でのリアルタイムドキュメント参照まで完全解説
‣ IBM Bobの基本と、Terraform連携を可能にするコア機能の理解 - 第2回(本記事):環境構築編— 環境構築スクリプト(setup.ps1)と pre-commit × AI自律化で実現するコード品質管理ガイド
‣ ワンコマンド環境構築スクリプト(setup.ps1)と pre-commit × AI自律化による品質管理 - 第3回:実践検証編 — 【Terraform × GCP】YAMLドリブンな動的リソース作成!IBM Bobと進めるAI自律デプロイ実践検証
‣ YAMLを活用した動的複数リソース作成の自動化検証
IaC(Terraform)開発における運用の壁
Terraformを用いたクラウドインフラのコード化(IaC)を進める際、以下のような運用上の問題が頻繁に発生します。
-
開発ツールのバージョン不一致:
メンバーごとにterraform、tflint、terraform-docsなどのバージョンが異なり、生成されるコードやドキュメントに不要な差分が生じる。 -
手動チェックの手間と抜け漏れ:
git commit前にterraform fmtやtflintを実行し忘れ、リポジトリの履歴が散らかったりCIでエラーが発生したりする。 -
環境構築・展開コストの増大:
個別でのCLIツールのインストールや環境変数(PATH)の設定手順の案内・作業に時間がかかる。
💡 これらの問題を解決するために、PowerShellスクリプトによる自動環境構築とpre-commitフック+AIエージェントによる二重の品質維持の仕組みを組み込みます。
2.ローカル環境自動構築スクリプト(setup.ps1)の準備
Windows環境での開発において、必要なツールを一括インストールし、環境変数(PATH)の設定およびGitフックの有効化までを自動でおこなうPowerShellスクリプト(setup.ps1)を用意します。
2.1. スクリプトの全容と仕組み
リポジトリのルートに以下の setup.ps1 を配置します。
▶ クリックして setup.ps1 のコード全文を表示する
################################################################################
# setup.ps1
# このリポジトリの開発環境を自動セットアップするスクリプト
#
# 実行方法(リポジトリルートで 1 回だけ実行):
# Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
# .\setup.ps1
################################################################################
$ErrorActionPreference = "Stop"
Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " Terraform 開発環境セットアップ" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
# ------------------------------------------------------------------------------
# 前提条件チェック(Git for Windows / Python+pip)
# ------------------------------------------------------------------------------
Write-Host "[前提確認] 必須ツールの確認..." -ForegroundColor Yellow
$prereqOk = $true
# Git for Windows の確認
$gitPath = "C:\Program Files\Git\bin\git.exe"
if (Test-Path $gitPath) {
$gitVer = & $gitPath --version 2>&1
Write-Host " [OK] Git for Windows: $gitVer" -ForegroundColor Green
} else {
Write-Host " [NG] Git for Windows が見つかりません" -ForegroundColor Red
Write-Host " https://git-scm.com/download/win からインストールしてください" -ForegroundColor Red
$prereqOk = $false
}
# Python + pip の確認
$pythonOk = $false
try {
$pyVer = python --version 2>&1 | Out-String
$pipVer = pip --version 2>&1 | Out-String
if ($pyVer -match "Python \d") {
Write-Host " [OK] $($pyVer.Trim())" -ForegroundColor Green
Write-Host " [OK] $($pipVer.Trim())" -ForegroundColor Green
$pythonOk = $true
}
} catch {}
if (-not $pythonOk) {
Write-Host " [NG] Python / pip が見つかりません" -ForegroundColor Red
Write-Host " https://www.python.org/downloads/ からインストールしてください" -ForegroundColor Red
$prereqOk = $false
}
if (-not $prereqOk) {
Write-Host ""
Write-Host "[!] 前提条件を満たしていません。上記のツールをインストール後、再度実行してください。" -ForegroundColor Red
exit 1
}
Write-Host ""
# 1. ツールのインストール(winget)
Write-Host "[1/4] ツールのインストール..." -ForegroundColor Yellow
$tools = @(
@{ Id = "Hashicorp.Terraform"; Name = "Terraform" },
@{ Id = "TerraformLinters.tflint"; Name = "TFLint" },
@{ Id = "Terraform-docs.Terraform-docs"; Name = "terraform-docs" }
)
foreach ($tool in $tools) {
$installed = winget list --id $tool.Id 2>&1 | Select-String $tool.Id
if ($installed) {
Write-Host " [OK] $($tool.Name) は導入済みです" -ForegroundColor Green
} else {
Write-Host " [..] $($tool.Name) をインストール中..." -ForegroundColor Cyan
winget install $tool.Id --accept-source-agreements --accept-package-agreements
}
}
# 2. pre-commit のインストール(pip)
Write-Host ""
Write-Host "[2/4] pre-commit のインストール..." -ForegroundColor Yellow
$pcInstalled = pip show pre-commit 2>&1 | Select-String "Name: pre-commit"
if ($pcInstalled) {
Write-Host " [OK] pre-commit は導入済みです" -ForegroundColor Green
} else {
Write-Host " [..] pre-commit をインストール中..." -ForegroundColor Cyan
pip install pre-commit
}
# 3. システム PATH への登録
Write-Host ""
Write-Host "[3/4] PATH の設定..." -ForegroundColor Yellow
function Add-ToUserPath($p) {
$cur = [System.Environment]::GetEnvironmentVariable("PATH", "User")
if ($cur -notlike "*$p*") {
[System.Environment]::SetEnvironmentVariable("PATH", "$p;$cur", "User")
Write-Host " [+] PATH に追加: $p" -ForegroundColor Green
} else {
Write-Host " [OK] PATH 登録済み: $p" -ForegroundColor Green
}
}
# Git bash
@("C:\Program Files\Git\bin", "C:\Program Files\Git\usr\bin") | ForEach-Object {
if (Test-Path $_) { Add-ToUserPath $_ }
}
# winget 製ツール
$wingetBase = "$env:LOCALAPPDATA\Microsoft\WinGet\Packages"
$pkgs = @(
@{ Dir = "Hashicorp.Terraform_Microsoft.Winget.Source_8wekyb3d8bbwe"; Exe = "terraform.exe" },
@{ Dir = "TerraformLinters.tflint_Microsoft.Winget.Source_8wekyb3d8bbwe"; Exe = "tflint.exe" },
@{ Dir = "Terraform-docs.Terraform-docs_Microsoft.Winget.Source_8wekyb3d8bbwe"; Exe = "terraform-docs.exe" }
)
foreach ($pkg in $pkgs) {
$dir = Get-ChildItem "$wingetBase\$($pkg.Dir)" -Filter $pkg.Exe -Recurse -ErrorAction SilentlyContinue |
Select-Object -First 1 -ExpandProperty DirectoryName
if ($dir) { Add-ToUserPath $dir }
}
# pip Scripts
$pipMatch = [regex]::Match((pip --version 2>&1 | Out-String), 'from (.+?)\\Lib\\'); $pipScripts = if ($pipMatch.Success) { $pipMatch.Groups[1].Value + '\Scripts' } else { "" }
if ($pipScripts -and (Test-Path $pipScripts)) { Add-ToUserPath $pipScripts }
# 4. pre-commit フックの登録
Write-Host ""
Write-Host "[4/4] pre-commit フックの登録..." -ForegroundColor Yellow
$env:PATH = "$pipScripts;C:\Program Files\Git\bin;" + $env:PATH
if (Test-Path ".pre-commit-config.yaml") {
pre-commit install
Write-Host " [OK] pre-commit フックを登録しました" -ForegroundColor Green
} else {
Write-Host " [!] .pre-commit-config.yaml が見つかりません。スキップします" -ForegroundColor DarkYellow
}
Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " セットアップ完了!" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
.pre-commit-config.yaml を参照し、pre-commit install まで完結させます。
2.2. pre-commit 設定ファイル(.pre-commit-config.yaml)の作成
コミット時に自動実行されるチェック処理を定義します。リポジトリのルートに .pre-commit-config.yaml を配置します。
▶ クリックして .pre-commit-config.yaml のコードを表示する
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.105.0
hooks:
# 1. Terraform コードの自動フォーマット
- id: terraform_fmt
exclude: ^test/
# 2. TFLint による静的解析(.tflint.hcl を使用)
- id: terraform_tflint
exclude: ^test/
args:
- --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
# 3. terraform-docs による README.md 内ドキュメントの自動挿入
- id: terraform_docs
exclude: ^test/
args:
- --args=--config=.terraform-docs.yml
2.3. 実行手順と動作確認
環境を構築・再構築する開発者は、以下の手順を一度実行するだけでセットアップが完了します。
① スクリプトの実行
# スクリプト実行権限の変更(初回のみ)
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
# 自動セットアップ実行
.\setup.ps1
② ターミナルの再起動と動作確認
PATHの設定を現在のシェルに反映させるため、ターミナル(PowerShell / VS Code)を再起動した上で確認を行います。
terraform --version
tflint --version
terraform-docs --version
pre-commit --version
すべて正常にバージョンが表示されれば、環境構築は成功です。
3.コード品質とAI自律化の仕組み
本仕組みでは、手動による品質管理を完全に撤廃し、AIエージェントによる事前の自律品質整形とコミット時のpre-commitフックによる二重チェックを実現します。
.tf ファイル)や変数を変更・追加した際、AI側がタスク完了の直前に自動で terraform fmt や terraform-docs などのチェック・生成コマンドを実行します。これにより、コミットする前にすでにコードが綺麗な状態に保たれます。
git commit コマンドを実行した瞬間に pre-commit が割り込み、フォーマットの乱れや tflint のエラーを即座に検知してコミットをストップさせます。
自動化される品質ツール群(fmt / tflint / terraform-docs)
具体的にどのようなチェックと更新が全自動でおこなわれるかを解説します。
① コードフォーマットの統一(terraform fmt)
インデントのズレ、=(イコール)の位置の揃え、改行ルールなどをTerraform標準の書式へ全自動で修正します。
② 静的解析(tflint)
.tflint.hcl に設定された規則に従い、未使用変数の検出や推奨されない記法、GCP(Google Cloud)リソースの命名規則違反などをチェックします。
# .tflint.hcl の例
plugin "google" {
enabled = true
version = "0.32.0"
source = "github.com/terraform-linters/tflint-ruleset-google"
}
rule "terraform_documented_variables" { enabled = true }
rule "terraform_documented_outputs" { enabled = true }
③ ドキュメントの自動生成・同期(terraform-docs)
variables.tf や outputs.tf に変数や出力値を追加・変更した際、README.md 内に配置された特定マーカー間(<!– BEGIN_TF_DOCS –> 〜 <!– END_TF_DOCS –>)へ、型や説明、デフォルト値の表を自動挿入・更新します。
# .terraform-docs.yml の例
formatter: "markdown table"
output:
file: README.md
mode: inject
template: |-
<!-- BEGIN_TF_DOCS -->
{{ .Content }}
<!-- END_TF_DOCS -->
README.md の変数定義表がリアルタイムで最新化されるため、「コードとドキュメントの不整合」が起きません。
setup.ps1 を実行するだけで誰でも全く同じツール・同じバージョン・同じフック構成で即座に開発を開始できます。
4.品質チェックの検証と動作確認テスト(エビデンス)
組み込んだ pre-commit フックが正常コードに対して期待通り通過し、問題のあるコードを正しくブロックできるかを検証したテスト結果です。
正常動作テスト(パス確認)
本番のTerraformコードに対して各種フックコマンドを実行し、すべてのテストをクリアすることを確認しました。
| フック名 | 実行コマンド | 結果 | 終了コード | 備考 |
|---|---|---|---|---|
| terraform_fmt |
terraform fmt -recursive -check -diff .
|
✅ 合格 | 0 | 全 .tf ファイルにインデント・書式差分なし |
| terraform_tflint |
tflint --config=.tflint.hcl --recursive
|
✅ 合格 | 0 | issue 0件(Warning / Notice なし) |
| terraform_docs |
terraform-docs --config=.terraform-docs.yml .
|
✅ 合格 | 0 | README.md の入力・出力表が自動更新完了 |
違反検知テスト(エラーブロック確認)
あえて意図的な構文エラーやフォーマット違反を含めたテスト用ファイルを配置し、フックが正常に失敗・ブロック処理を行えるか検証しました。
① フォーマット違反検知(terraform_fmt)
インデントをスペース8個にし、代入演算子 = 前後のスペースを抜いたテスト用ファイル(test/fmt_bad.tf)を配置して実行しました。
# test/fmt_bad.tf (テスト用コード)
variable "test_fmt_bad" {
type="string"
description = "インデント・スペース違反のテスト変数"
default="bad-value"
}
- 判定: ✅ 検知成功(終了コード 3)
- 結果: 正規の2スペースインデントとスペース補正が必要な差分として正しく検出されました。
② ルール違反検知(terraform_tflint)
required_version や変数の description を省略したファイル(test/tflint_bad.tf)で検証しました。
# test/tflint_bad.tf (テスト用コード)
variable "undocumented_var" {
type = string
# description を意図的に省略
}
- 判定: ✅ 検知成功(終了コード 2、5件の修正対象を抽出)
- 結果: terraform_required_version 欠如や terraform_documented_variables 違反(説明文欠如)を即座にブロックしました。
③ ドキュメント不正設定検知(terraform_docs)
設定ファイルのテンプレート構文エラーや README.md 内のマーカー欠如の挙動を検証しました。
- テンプレート構文エラー時: 不正な設定ファイル(test/.terraform-docs-bad.yml)で実行した場合、終了コード 1 で明確にエラーを出力。
- マーカー欠如時: <!– BEGIN_TF_DOCS –> マーカーがないファイルに対して実行した場合、エラーにならずファイル末尾に自動追記される仕様であることを確認。マーカーの配置自体はレビュー等で担保すべきポイントとして判明しました。
テスト用ファイルのフック除外設定(exclude: ^test/)
検証用の違反ファイル(test/fmt_bad.tf など)をそのままコミットしようとした際、pre-commit フック自体が起動してコミットを正しくブロックするという動作も確認できました。
テストコードまでフックが拾ってコミット不能になるのを防ぐため、本番用の .pre-commit-config.yaml には以下のように test/ ディレクトリを除外(exclude)する定義を追加しています。
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.105.0
hooks:
- id: terraform_fmt
exclude: ^test/ # テスト用ファイルを除外
- id: terraform_tflint
exclude: ^test/ # テスト用ファイルを除外
args:
- --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
- id: terraform_docs
exclude: ^test/ # テスト用ファイルを除外
args:
- --args=--config=.terraform-docs.yml
この設定により、テストエビデンスをリポジトリ内に保持しつつ、本番のTerraformコードのみを厳格に自動チェックできる運用を実現しています。
5.まとめ
本記事では、Terraform開発において環境のばらつきと品質維持の課題をクリアするための実践的な手法と検証結果を解説しました。
- setup.ps1 によるワンコマンド環境構築: Windowsの winget と pip を活用し、必要ツールの導入とPATH設定、Gitフックの登録までを一括化。
- pre-commit × AI自律実行のダブルガード: コード整形・静的解析・ドキュメント更新を人間任せにせず自動化し、ミスがリポジトリに紛れ込むのを未然に防止。
- 動作確認テストで品質を担保: 正常ケースの自動化だけでなく、違反コードが確実にコミット段階で弾かれることをテストにより検証・実証。
この構成を一度テンプレート化しておけば、新規環境の構築やチーム全体での環境標準化に伴うコストを大幅に削減できます。ぜひお試しください。
🔮 次回予告(シリーズ第3回)
本シリーズの次回(最終回)では、今回整えた環境とAI自律化の仕組みを活用し、実際のクラウドインフラ構築を自動化・デプロイする実践検証を行います!
第3回もお楽しみに!
「にこぷす通信」について
「NIC × Ops(にこぷす)通信」は、隔週で皆さまに情報をお届けします。
このシリーズでは、Instana(可観測性)をはじめ、Turbonomic(リソース最適化)やTerraform(インフラ自動化)など、IT運用を劇的に変える製品をピックアップしていきます。
これからも最新の技術検証をチームで継続し、皆さまの現場ですぐに役立つ「有益な知見」を全力で共有していきます。 次回の連載もお楽しみに!