# terraform fmt: каноничное форматирование HCL _Workflow · TerraformLab Knowledge Base_ **TL;DR:** `terraform fmt` приводит HCL к каноничному виду: одинаковые отступы, выровненные `=`, без лишних пустых строк. Запускается на одной папке по умолчанию, рекурсивно, с флагом `-recursive`. В CI используют `-check -diff` чтобы упасть на неформатированных файлах. ## Что делает fmt `terraform fmt`, это `gofmt` для HCL. Он не меняет смысл вашего кода, только приводит его к одному стилю: одинаковые отступы (два пробела), выровненные `=` в блоках аргументов, схлопнутые пустые строки, одинаковые кавычки. Цель, снять с код-ревью обсуждения «здесь четыре пробела, там два» и держать diff'ы в PR про логику, а не про пробелы. ## Базовое использование Без флагов, форматирует все `.tf` и `.tfvars` файлы в текущей папке **и пишет изменения на диск**: ```bash cd ~/myproject terraform fmt ``` В выводе, список изменённых файлов: ``` main.tf variables.tf ``` Если ничего не выведено, всё уже было отформатировано. ## Рекурсивно по всей папке По умолчанию `fmt` смотрит только в текущую директорию. Чтобы пройтись по всем подпапкам: ```bash terraform fmt -recursive ``` Это нужно в репозиториях с модулями (`modules/vpc/`, `modules/alb/`): без `-recursive` они не отформатируются. ## Что fmt делает с HCL До: ```hcl resource "aws_s3_bucket" "demo" { bucket="my-bucket" tags={ Owner="student" Env ="dev" } } ``` После `terraform fmt`: ```hcl resource "aws_s3_bucket" "demo" { bucket = "my-bucket" tags = { Owner = "student" Env = "dev" } } ``` Заметьте: `Owner` и `Env` теперь выровнены по `=`. Это автоматика, не ручной труд. ## Режимы для CI Локально вы хотите чтобы `fmt` исправлял файлы. В CI, чтобы он проваливал сборку, если кто-то закоммитил неформатированный код. ```bash # упасть с ненулевым exit code, если что-то не отформатировано terraform fmt -check -recursive # то же самое + показать diff что именно не так terraform fmt -check -diff -recursive ``` Флаги: - `-check`, не писать на диск, exit 0 = всё ок, exit 3 = есть неотформатированные. - `-diff`, показать построчный diff. - `-write=false`, синоним «не писать», обычно его не используют отдельно. ## Pre-commit hook Самое практичное применение, поставить `fmt` в pre-commit, чтобы не пропускать unformatted код в git вообще: ```yaml # .pre-commit-config.yaml repos: - repo: https://github.com/antonbabenko/pre-commit-terraform rev: v1.88.0 hooks: - id: terraform_fmt ``` Тогда `git commit` сам отформатирует tf-файлы перед коммитом. Если в репозиторий попал кривой стиль, это была сознательная попытка обойти hook, не «забыли запустить fmt». ## Что fmt НЕ делает - **Не проверяет синтаксис.** Битый HCL fmt не починит. Для синтаксиса есть [tf-validate](/terraform/kb/tf-validate.md). - **Не переписывает имена.** `Resource` вместо `resource`, это ошибка, не «плохой стиль». Поймает её validate. - **Не сортирует аргументы по алфавиту.** Порядок аргументов внутри блока сохраняется. - **Не трогает комментарии.** Если в коде есть `# Замечание здесь`, оно останется на месте. - **Не работает с .tf.json.** Только с HCL. ## Подводные камни - **`fmt` пишет на диск по умолчанию.** Если коллега в IDE открыл файл и не сохранил, а вы запустили `fmt`, его изменения могут потеряться. В корпоративном setup лучше через IDE-интеграцию (Terraform extension VS Code/JetBrains сам зовёт fmt). - **`fmt -recursive` обходит `.terraform/` тоже.** Если хочется игнорить, `.terraform/` обычно в `.gitignore`, и проблем нет, но fmt всё равно туда заглянет. - **Версия terraform имеет значение.** Между минорными версиями правила форматирования иногда меняются (например, в 1.9 добавили выравнивание comments). Команда должна быть на одной версии, иначе PR с «fmt-only» правками будут плодиться. Решается через `.terraform-version` (для tfenv) или CI с зафиксированной версией. - **Не запускайте `fmt` на CI без `-check`.** Иначе CI сам исправит файлы и закоммитит, но кто хозяин коммита, непонятно. Локально исправлять, в CI только проверять. ## Команды ```bash terraform fmt ``` Отформатировать все .tf и .tfvars в текущей директории, пишет на диск. ```bash terraform fmt -recursive ``` То же, но рекурсивно по всем подпапкам. Нужно если в проекте есть modules/. ```bash terraform fmt -check -recursive ``` В CI: не писать, упасть с exit 3 если что-то не отформатировано. ```bash terraform fmt -check -diff -recursive ``` В CI + показать что именно не так. Помогает разработчику починить локально. ```bash terraform fmt - ``` Прочитать HCL из stdin, выдать отформатированный в stdout. Полезно в скриптах. ## См. также - [HCL: язык, на котором пишут Terraform](/terraform/kb/hcl-syntax.md) - [terraform validate: проверка HCL без облака](/terraform/kb/tf-validate.md) - [Конфигурация Terraform CLI: terraformrc, env vars, TF_LOG](/terraform/kb/tf-cli-config.md)