lesson ── terraform-production ── ~14 мин ── 6 шагов
pre-commit, Python-фреймворк для git-hook'ов. Объявляешь набор проверок
в .pre-commit-config.yaml, запускаешь pre-commit install, и теперь
каждый git commit гоняет fmt/validate/tflint перед тем, как пустить
изменения в репо. Тот же конфиг, в CI: pre-commit run --all-files.
интерактивный sandbox
Поднимется пара контейнеров: terraform 1.9 и localstack 3.8 в одной сети. В браузере откроется терминал, можно сразу terraform init. Каждый шаг проверяется автоматически. TTL 45 минут, без регистрации.
stack ── terraform · localstack · 1 GB RAM · самоуничтожается через 45 мин простоя
cd /home/student/tf-precommit
git init -q
git config user.email "student@linuxlab.local"
git config user.name "student"
cat > main.tf <<'EOF'
resource "aws_s3_bucket" "demo" {bucket = "linuxlab-precommit-demo"
tags = {Owner = "student"
}
}
EOF
terraform fmt
git add .
git commit -q -m "init: clean hcl"
git log --oneline
В репо один чистый коммит, baseline.
✓ Git инициализирован, чистый baseline закоммичен.
cat > .pre-commit-config.yaml <<'EOF'
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.95.0
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_tflint
args:
- --args=--init
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
EOF
Заметь: hook ID, terraform_fmt, не просто fmt. Это
имя из репо antonbabenko/pre-commit-terraform, де-факто
стандарт для Terraform.
Установи hook'и в git:
pre-commit install
ls .git/hooks/pre-commit
Файл .git/hooks/pre-commit появился, это wrapper, который при
каждом commit запустит pre-commit.
✓ Hook установлен, теперь git commit пройдёт через pre-commit.
Положи нарочно нечистый файл:
cat > badly.tf <<'EOF'
resource "aws_s3_bucket" "another" {bucket="bad-format"
}
EOF
git add badly.tf
set +e
git commit -m "feat: add another bucket"
echo "exit: $?"
set -e
Commit упал, потому что terraform_fmt нашёл проблему. Pre-commit
сам сделал auto-fix, но файлы остались unstaged.
Проверь:
git status
cat badly.tf
badly.tf теперь отформатирован, но git его уже видит как
«modified», pre-commit изменил после git add.
✓ Hook auto-fix'нул формат. Без него commit бы прошёл с грязным HCL.
git add badly.tf
git commit -m "feat: add another bucket"
git log --oneline
Теперь pre-commit прошёл, файл уже чист. Commit принят.
В реальной работе цикл такой: commit → hook fix → re-add → commit. Чем чище код dev писал, тем реже re-add.
✓ Чистый коммит прошёл pre-commit gate.
Положи ссылку на несуществующий ресурс:
cat >> main.tf <<'EOF'
output "broken" {value = aws_s3_bucket.does_not_exist.arn
}
EOF
git add main.tf
set +e
git commit -m "feat: broken reference"
code=$?
set -e
echo "exit: $code"
Должно упасть на terraform_validate, ссылка на несуществующий
ресурс. Это не format-issue, который auto-fix; это semantic-issue,
требует ручного исправления.
Откати:
git restore --staged main.tf
sed -i '/output "broken"/,/^}$/d' main.tf
cat main.tf
✓ validate отбил битый HCL. Без pre-commit это бы дошло до plan'а в CI.
OpenTofu держит CLI и state совместимыми с Terraform по командам
этого шага: миграция обычно проходит через mv .terraform .terraform.bak; tofu init -upgrade. Но при первом переходе
сделай backup state и прогон на feature-branch - расхождения
концентрируются в новых фичах (variables в backend,
state-encryption, OCI registry-backed модули). См.
tf-opentofu-parity для полной матрицы.
Локально hook'и срабатывают на ИЗМЕНЁННЫЕ файлы. В CI нужно прогнать всё, старые файлы тоже могут не соответствовать политике (особенно сразу после adoption pre-commit'а в legacy-репо).
pre-commit run --all-files
echo "exit: $?"
Должно показать pass'ы. Если бы кто-то закоммитил bypass'нув hook
(--no-verify), --all-files это поймал бы.
Это финальный CI-шаг: pre-commit run --all-files, exit 1 на
любую проблему.
✓ pre-commit gate работает. Дальше, функциональные тесты.
Что ещё есть в antonbabenko/pre-commit-terraform и зачем:
terraform_docs, автогенерация README.md с inputs/outputs.
Удобно для модулей; запускается в CI с --args=--output-file,
чтобы README обновлялся при изменении variables.terraform_checkov, checkov в pre-commit. Медленно;
обычно только в CI.terraform_trivy, то же, что checkov, но trivy. Выбор один
из двух.terraform_tfsec, устаревший, см. tf-trivy-tfsec.terragrunt_fmt / terragrunt_validate, если у тебя
terragrunt-обвязка.infracost_breakdown, оценка стоимости. Требует API-токен.Правило: чем дольше hook, тем меньше его в local-precommit, и больше в CI. Локально хочется проверки за <5 секунд.
pre-commit подключается к git через pre-commit install, читает
.pre-commit-config.yaml, гоняет hook'и при коммите. Hook'и под
Terraform, антибабенко/pre-commit-terraform: terraform_fmt,
terraform_validate, terraform_tflint, terraform_docs.
команды
pre-commit installподключить hook'и в .git/hooks. Один раз после clone.pre-commit run --all-filesпрогнать всё репо. Использовать для bootstrap'а на старом проекте.SKIP=terraform_fmt git commitпропустить один hook. Только осознанно.pre-commit autoupdateподнять версии rev: в конфиге.концепции