From 1446a7ce86220dfcf1a9498ad74cf0ed277b425b Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Thu, 16 Oct 2025 10:49:56 -0300 Subject: [PATCH 01/14] added helm hooks(first version) --- .pre-commit-hooks.yaml | 30 +++++++++- README.md | 109 ++++++++++++++++++++++++++++++++++- hooks/helm-lint.sh | 77 +++++++++++++++++++++++++ hooks/helm-template-check.sh | 90 +++++++++++++++++++++++++++++ hooks/yamllint.sh | 45 +++++++++++++++ 5 files changed, 346 insertions(+), 5 deletions(-) create mode 100755 hooks/helm-lint.sh create mode 100755 hooks/helm-template-check.sh create mode 100755 hooks/yamllint.sh diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index e738c33..a80d847 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -4,7 +4,7 @@ name: Terraform fmt description: Rewrites all Terraform configuration files to a canonical format entry: hooks/terraform-fmt.sh - language: script + language: system files: \.tf$ exclude: '(^|.*/)(\.terraform|examples)/' require_serial: true @@ -13,7 +13,7 @@ name: Terraform validate description: Runs 'terraform validate' entry: hooks/terraform-validate.sh - language: script + language: system files: \.tf$ exclude: '(^|.*/)(\.terraform|examples)/' require_serial: true @@ -25,3 +25,29 @@ language: script pass_filenames: false +- id: helm-lint + name: Helm lint + description: Runs 'helm lint' on Helm charts + entry: hooks/helm-lint.sh + language: system + files: (Chart\.yaml|values.*\.yaml|templates/.*\.yaml)$ + exclude: '(^|.*/)(\.terraform|examples)/' + require_serial: true + +- id: yamllint + name: YAML Lint + description: Validates YAML syntax and style + entry: hooks/yamllint.sh + language: system + files: \.(yaml|yml)$ + exclude: '(^|.*/)(\.terraform|examples)/' + require_serial: false + +- id: helm-template-check + name: Helm template check + description: Validates that Helm templates can render without errors + entry: hooks/helm-template-check.sh + language: system + files: (Chart\.yaml|values.*\.yaml|templates/.*\.yaml)$ + exclude: '(^|.*/)(\.terraform|examples)/' + require_serial: true diff --git a/README.md b/README.md index f9e2239..3953da5 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,27 @@ This repo defines Git pre-commit hooks intended for use with [pre-commit](https://pre-commit.com/). The currently supported hooks are: +> 🚀 **Quick Start**: New to pre-commit? Check out our [Quick Start Guide](QUICKSTART.md) for a 5-minute setup! + +## Terraform Hooks + * **terraform-fmt**: Checks that all Terraform files (`*.tf`) are properly formatted (`terraform fmt --check -diff`). * **terraform-validate**: Runs `terraform init -backend=false` and then `terraform validate`. > Notes: directories requiring a private registry and lacking credentials are marked as **skipped** (do not fail the commit). Both hooks ignore `.terraform/` and `examples/`. +## Helm/Kubernetes Hooks + +* **helm-lint**: Executes `helm lint` on all Helm charts (directories with `Chart.yaml`). Validates chart structure, syntax, and best practices. +* **helm-template-check**: Runs `helm template` to ensure templates can render without errors. Uses the default `values.yaml` file. Does not validate the output against Kubernetes schemas. +* **yamllint**: Validates YAML syntax and style for all `.yaml` and `.yml` files. Checks indentation, duplicates, trailing spaces, etc. + > Note: Copy `.yamllint.yaml` to your repo root for custom configuration. + ## General Usage In each of your repos, add a file called `.pre-commit-config.yaml` with the following contents: +### For Terraform projects: + ```yaml repos: - repo: git@github.com:craftech-io/pre-commit.git # or https://github.com/craftech-io/pre-commit.git @@ -21,19 +34,51 @@ repos: verbose: true ``` +### For Helm/Kubernetes projects: + +```yaml +repos: + - repo: git@github.com:craftech-io/pre-commit.git # or https://github.com/craftech-io/pre-commit.git + rev: + hooks: + - id: yamllint + - id: helm-lint + - id: helm-template-check +``` + +### For mixed projects (Terraform + Helm): + +```yaml +repos: + - repo: git@github.com:craftech-io/pre-commit.git + rev: + hooks: + # Terraform + - id: terraform-fmt + - id: terraform-validate + # Helm/Kubernetes + - id: yamllint + - id: helm-lint + - id: helm-template-check +``` + Next, have every developer: 1. Install [pre-commit](https://pre-commit.com/#install). - macOS: `brew install pre-commit` - Linux: `pipx install pre-commit` (or `pip install --user pre-commit`) -2. Run `pre-commit install` in the repo. +2. Install required tools based on your hooks: + - **Terraform hooks**: Install [Terraform](https://www.terraform.io/downloads) + - **Helm hooks**: Install [Helm](https://helm.sh/docs/intro/install/) + - **yamllint hook**: Install yamllint (`brew install yamllint` or `pip install yamllint`) +3. Run `pre-commit install` in the repo. That's it! Now every time you commit a code change (`.tf` file), the hooks in the `hooks:` config will execute. If any hook fails, the commit is aborted; if all pass, the commit succeeds. ## Running Against All Files At Once -### Example: Formatting and validating all files +### Terraform: Formatting and validating all files If you'd like to run the hooks across the whole repo (useful the first time), you can run: @@ -43,12 +88,70 @@ pre-commit run terraform-fmt --all-files # Validate all Terraform directories pre-commit run terraform-validate --all-files +``` + +### Helm/Kubernetes: Linting and validating all files +```bash +# Validate YAML syntax in all files +pre-commit run yamllint --all-files + +# Lint all Helm charts +pre-commit run helm-lint --all-files + +# Check that all Helm templates can render +pre-commit run helm-template-check --all-files +``` + +### Run all configured hooks at once + +```bash # Or run every configured hook across the repo pre-commit run --all-files ``` -> Tip: for detailed output on demand, use `-v`, e.g. `pre-commit run -v terraform-validate --all-files`. +> Tip: for detailed output on demand, use `-v`, e.g. `pre-commit run -v helm-lint --all-files`. + +## Optional Configuration + +### yamllint Configuration + +By default, `yamllint` uses strict rules. You can customize the behavior by copying the example configuration to your repo: + +```bash +# Copy the example configuration +cp .yamllint.yaml /path/to/your/repo/.yamllint.yaml + +# Or download it directly +curl -O https://raw.githubusercontent.com/craftech-io/pre-commit/main/.yamllint.yaml +``` + +Then customize `.yamllint.yaml` in your repo root according to your needs. See [yamllint documentation](https://yamllint.readthedocs.io/) for all available options. + +## Troubleshooting + +### Helm hooks are skipped + +If the Helm hooks show "No Helm charts found", ensure your repository has: +- A `Chart.yaml` file in your chart directory +- A `templates/` directory with your Kubernetes manifests +- A `values.yaml` file (required for template rendering) + +### yamllint is too strict + +If yamllint reports too many warnings for your use case: +1. Copy the `.yamllint.yaml` configuration file to your repo +2. Adjust the rules (e.g., increase `line-length`, disable specific rules) +3. Commit the configuration file + +### Dependencies not installed + +Each hook requires specific tools to be installed: +- **terraform-fmt, terraform-validate**: Requires Terraform CLI +- **helm-lint, helm-template-check**: Requires Helm CLI +- **yamllint**: Requires yamllint Python package + +Install missing tools before running `pre-commit install`. ## License diff --git a/hooks/helm-lint.sh b/hooks/helm-lint.sh new file mode 100755 index 0000000..3dc9818 --- /dev/null +++ b/hooks/helm-lint.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -uo pipefail +IFS=$'\n\t' + +RED='\033[31m'; GRN='\033[32m'; YLW='\033[33m'; BLD='\033[1m'; RST='\033[0m' +if [[ "${PRE_COMMIT_COLOR:-}" == "never" ]]; then RED=''; GRN=''; YLW=''; BLD=''; RST=''; fi + +# Verificar que helm esté instalado +if ! command -v helm &>/dev/null; then + echo -e "${RED}✗ Error: helm no está instalado${RST}" + echo " Instalá helm desde: https://helm.sh/docs/intro/install/" + exit 1 +fi + +# Recolectar directorios únicos que contienen Chart.yaml +if [[ "$#" -gt 0 ]]; then + # Buscar Chart.yaml en los directorios de los archivos modificados + mapfile -t CHART_DIRS < <( + for f in "$@"; do + dir="$(dirname "$f")" + # Buscar hacia arriba hasta encontrar Chart.yaml + while [[ "$dir" != "." && "$dir" != "/" ]]; do + if [[ -f "$dir/Chart.yaml" ]]; then + echo "$dir" + break + fi + dir="$(dirname "$dir")" + done + done | sort -u + ) +else + # Buscar todos los Chart.yaml en el repo + mapfile -t CHART_DIRS < <(find . -name "Chart.yaml" -exec dirname {} \; | sort -u) +fi + +# Si no hay charts, salir exitosamente +if [[ "${#CHART_DIRS[@]}" -eq 0 ]]; then + echo -e "${YLW}! No se encontraron Helm charts (Chart.yaml)${RST}" + exit 0 +fi + +exit_code=0 + +for chart_dir in "${CHART_DIRS[@]}"; do + echo -e "${BLD}>> Validando Helm chart: ${chart_dir}${RST}" + + pushd "$chart_dir" >/dev/null + + set +e + out="$(helm lint . 2>&1)" + status=$? + set -e + + if [[ $status -eq 0 ]]; then + echo -e " ${GRN}✓ Chart válido${RST}" + # Mostrar warnings si existen pero el lint pasó + if grep -q "WARNING" <<<"$out"; then + echo -e " ${YLW}⚠ Warnings encontrados:${RST}" + echo "$out" | grep "WARNING" | sed 's/^/ /' + fi + else + echo -e " ${RED}✗ Lint falló${RST}" + echo "$out" | sed 's/^/ /' + exit_code=1 + fi + + popd >/dev/null + echo +done + +if [[ $exit_code -eq 0 ]]; then + echo -e "${GRN}✓ Todos los charts pasaron helm lint${RST}" +else + echo -e "${RED}✗ Algunos charts tienen errores de lint${RST}" +fi + +exit "$exit_code" diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh new file mode 100755 index 0000000..eadd083 --- /dev/null +++ b/hooks/helm-template-check.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +set -uo pipefail +IFS=$'\n\t' + +RED='\033[31m'; GRN='\033[32m'; YLW='\033[33m'; BLD='\033[1m'; RST='\033[0m' +if [[ "${PRE_COMMIT_COLOR:-}" == "never" ]]; then RED=''; GRN=''; YLW=''; BLD=''; RST=''; fi + +# Verificar que helm esté instalado +if ! command -v helm &>/dev/null; then + echo -e "${RED}✗ Error: helm no está instalado${RST}" + echo " Instalá helm desde: https://helm.sh/docs/intro/install/" + exit 1 +fi + +# Recolectar directorios únicos que contienen Chart.yaml +if [[ "$#" -gt 0 ]]; then + # Buscar Chart.yaml en los directorios de los archivos modificados + mapfile -t CHART_DIRS < <( + for f in "$@"; do + dir="$(dirname "$f")" + # Buscar hacia arriba hasta encontrar Chart.yaml + while [[ "$dir" != "." && "$dir" != "/" ]]; do + if [[ -f "$dir/Chart.yaml" ]]; then + echo "$dir" + break + fi + dir="$(dirname "$dir")" + done + done | sort -u + ) +else + # Buscar todos los Chart.yaml en el repo + mapfile -t CHART_DIRS < <(find . -name "Chart.yaml" -exec dirname {} \; | sort -u) +fi + +# Si no hay charts, salir exitosamente +if [[ "${#CHART_DIRS[@]}" -eq 0 ]]; then + echo -e "${YLW}! No se encontraron Helm charts (Chart.yaml)${RST}" + exit 0 +fi + +exit_code=0 + +for chart_dir in "${CHART_DIRS[@]}"; do + echo -e "${BLD}>> Validando templates de Helm chart: ${chart_dir}${RST}" + + # Verificar que exista el directorio templates + if [[ ! -d "$chart_dir/templates" ]]; then + echo -e " ${YLW}! Skipped (no hay directorio templates/)${RST}" + echo + continue + fi + + pushd "$chart_dir" >/dev/null + + # Verificar si existe values.yaml + values_file="values.yaml" + if [[ ! -f "$values_file" ]]; then + echo -e " ${YLW}! Skipped (no existe values.yaml)${RST}" + popd >/dev/null + echo + continue + fi + + set +e + # Ejecutar helm template solo para verificar que renderice sin errores + # No validamos el output, solo que pueda generar algo + out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" + status=$? + set -e + + if [[ $status -eq 0 ]]; then + echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" + else + echo -e " ${RED}✗ Error al renderizar templates${RST}" + echo "$out" | sed 's/^/ /' + exit_code=1 + fi + + popd >/dev/null + echo +done + +if [[ $exit_code -eq 0 ]]; then + echo -e "${GRN}✓ Todos los templates se renderizaron correctamente${RST}" +else + echo -e "${RED}✗ Algunos templates tienen errores${RST}" +fi + +exit "$exit_code" diff --git a/hooks/yamllint.sh b/hooks/yamllint.sh new file mode 100755 index 0000000..b3b5320 --- /dev/null +++ b/hooks/yamllint.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -uo pipefail +IFS=$'\n\t' + +RED='\033[31m'; GRN='\033[32m'; YLW='\033[33m'; BLD='\033[1m'; RST='\033[0m' +if [[ "${PRE_COMMIT_COLOR:-}" == "never" ]]; then RED=''; GRN=''; YLW=''; BLD=''; RST=''; fi + +# Verificar que yamllint esté instalado +if ! command -v yamllint &>/dev/null; then + echo -e "${RED}✗ Error: yamllint no está instalado${RST}" + echo " Instalá yamllint:" + echo " - macOS: brew install yamllint" + echo " - Linux: pip install yamllint (o pipx install yamllint)" + exit 1 +fi + +exit_code=0 + +# Si no hay archivos, salir +if [[ "$#" -eq 0 ]]; then + echo -e "${YLW}! No hay archivos YAML para validar${RST}" + exit 0 +fi + +for f in "$@"; do + echo -e "${BLD}→ ${f}${RST}" + + set +e + out="$(yamllint -f parsable "$f" 2>&1)" + status=$? + set -e + + if [[ $status -eq 0 ]]; then + echo -e " ${GRN}✓ YAML válido${RST}" + else + echo -e " ${RED}✗ Errores de sintaxis YAML${RST}" + # Formatear output para mejor legibilidad + echo "$out" | sed 's/^/ /' + exit_code=1 + fi + + echo +done + +exit "$exit_code" From 9401f95c399a73aaca1ad10f6a6c673ca2804b1c Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Thu, 16 Oct 2025 10:59:09 -0300 Subject: [PATCH 02/14] changed hook.yaml --- .pre-commit-hooks.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index a80d847..9cad001 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -1,4 +1,6 @@ -# This configuration file allows our pre-commit hooks to be used with pre-commit: http://pre-commit.com/ +--- +# This configuration file allows our pre-commit hooks to be used with +# pre-commit: http://pre-commit.com/ - id: terraform-fmt name: Terraform fmt From 47179159b1603fafa9532726e6605e4413939b60 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Thu, 16 Oct 2025 16:49:25 -0300 Subject: [PATCH 03/14] added change in scripts --- .pre-commit-hooks.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 9cad001..4866d48 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -6,7 +6,7 @@ name: Terraform fmt description: Rewrites all Terraform configuration files to a canonical format entry: hooks/terraform-fmt.sh - language: system + language: script files: \.tf$ exclude: '(^|.*/)(\.terraform|examples)/' require_serial: true @@ -15,7 +15,7 @@ name: Terraform validate description: Runs 'terraform validate' entry: hooks/terraform-validate.sh - language: system + language: script files: \.tf$ exclude: '(^|.*/)(\.terraform|examples)/' require_serial: true @@ -31,7 +31,7 @@ name: Helm lint description: Runs 'helm lint' on Helm charts entry: hooks/helm-lint.sh - language: system + language: script files: (Chart\.yaml|values.*\.yaml|templates/.*\.yaml)$ exclude: '(^|.*/)(\.terraform|examples)/' require_serial: true @@ -40,7 +40,7 @@ name: YAML Lint description: Validates YAML syntax and style entry: hooks/yamllint.sh - language: system + language: script files: \.(yaml|yml)$ exclude: '(^|.*/)(\.terraform|examples)/' require_serial: false @@ -49,7 +49,7 @@ name: Helm template check description: Validates that Helm templates can render without errors entry: hooks/helm-template-check.sh - language: system + language: script files: (Chart\.yaml|values.*\.yaml|templates/.*\.yaml)$ exclude: '(^|.*/)(\.terraform|examples)/' require_serial: true From 1c8f8234ff6dc0b850cdf82fcce22b58d79b64f2 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Thu, 16 Oct 2025 17:15:39 -0300 Subject: [PATCH 04/14] adding identation test --- hooks/helm-template-check.sh | 68 ++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index eadd083..361c5f0 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -53,28 +53,66 @@ for chart_dir in "${CHART_DIRS[@]}"; do pushd "$chart_dir" >/dev/null - # Verificar si existe values.yaml - values_file="values.yaml" - if [[ ! -f "$values_file" ]]; then + # Recolectar archivos de values para probar + # 1. values.yaml (base) + # 2. tests/values-*.yaml (casos de prueba) + mapfile -t VALUES_FILES < <( + [[ -f "values.yaml" ]] && echo "values.yaml" + find tests -name "values-*.yaml" 2>/dev/null | sort + ) + + if [[ "${#VALUES_FILES[@]}" -eq 0 ]]; then echo -e " ${YLW}! Skipped (no existe values.yaml)${RST}" popd >/dev/null echo continue fi - set +e - # Ejecutar helm template solo para verificar que renderice sin errores - # No validamos el output, solo que pueda generar algo - out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" - status=$? - set -e + # Probar con cada archivo de values + chart_failed=0 + for values_file in "${VALUES_FILES[@]}"; do + echo -e " ${BLD}Testing with: ${values_file}${RST}" + + set +e + # Ejecutar helm template y capturar output + out="$(helm template test-release . --values "$values_file" 2>&1)" + status=$? + set -e + + if [[ $status -ne 0 ]]; then + echo -e " ${RED}✗ Error al renderizar templates${RST}" + echo "$out" | sed 's/^/ /' + chart_failed=1 + exit_code=1 + else + # Validar que el YAML renderizado sea parseable + set +e + yaml_validation=$(echo "$out" | python3 -c " +import yaml +import sys +try: + list(yaml.safe_load_all(sys.stdin)) + print('valid') +except yaml.YAMLError as e: + print(f'YAML Error: {e}', file=sys.stderr) + sys.exit(1) +" 2>&1) + yaml_status=$? + set -e + + if [[ $yaml_status -eq 0 ]]; then + echo -e " ${GRN}✓ Renderiza y genera YAML válido${RST}" + else + echo -e " ${RED}✗ Genera YAML inválido${RST}" + echo "$yaml_validation" | sed 's/^/ /' + chart_failed=1 + exit_code=1 + fi + fi + done - if [[ $status -eq 0 ]]; then - echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" - else - echo -e " ${RED}✗ Error al renderizar templates${RST}" - echo "$out" | sed 's/^/ /' - exit_code=1 + if [[ $chart_failed -eq 0 ]]; then + echo -e " ${GRN}✓ Todos los valores renderizan correctamente${RST}" fi popd >/dev/null From 1ae33b8455369b1122f9435b6b6cf2ed353db1f9 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Thu, 16 Oct 2025 17:18:49 -0300 Subject: [PATCH 05/14] adding identation test --- hooks/helm-template-check.sh | 70 +++++++++--------------------------- 1 file changed, 16 insertions(+), 54 deletions(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index 361c5f0..f0cc1e9 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -53,66 +53,28 @@ for chart_dir in "${CHART_DIRS[@]}"; do pushd "$chart_dir" >/dev/null - # Recolectar archivos de values para probar - # 1. values.yaml (base) - # 2. tests/values-*.yaml (casos de prueba) - mapfile -t VALUES_FILES < <( - [[ -f "values.yaml" ]] && echo "values.yaml" - find tests -name "values-*.yaml" 2>/dev/null | sort - ) - - if [[ "${#VALUES_FILES[@]}" -eq 0 ]]; then + # Verificar si existe values.yaml + values_file="values.yaml" + if [[ ! -f "$values_file" ]]; then echo -e " ${YLW}! Skipped (no existe values.yaml)${RST}" popd >/dev/null echo continue fi - # Probar con cada archivo de values - chart_failed=0 - for values_file in "${VALUES_FILES[@]}"; do - echo -e " ${BLD}Testing with: ${values_file}${RST}" - - set +e - # Ejecutar helm template y capturar output - out="$(helm template test-release . --values "$values_file" 2>&1)" - status=$? - set -e - - if [[ $status -ne 0 ]]; then - echo -e " ${RED}✗ Error al renderizar templates${RST}" - echo "$out" | sed 's/^/ /' - chart_failed=1 - exit_code=1 - else - # Validar que el YAML renderizado sea parseable - set +e - yaml_validation=$(echo "$out" | python3 -c " -import yaml -import sys -try: - list(yaml.safe_load_all(sys.stdin)) - print('valid') -except yaml.YAMLError as e: - print(f'YAML Error: {e}', file=sys.stderr) - sys.exit(1) -" 2>&1) - yaml_status=$? - set -e - - if [[ $yaml_status -eq 0 ]]; then - echo -e " ${GRN}✓ Renderiza y genera YAML válido${RST}" - else - echo -e " ${RED}✗ Genera YAML inválido${RST}" - echo "$yaml_validation" | sed 's/^/ /' - chart_failed=1 - exit_code=1 - fi - fi - done + set +e + # Ejecutar helm template solo para verificar que renderice sin errores + # No validamos el output, solo que pueda generar algo + out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" + status=$? + set -e - if [[ $chart_failed -eq 0 ]]; then - echo -e " ${GRN}✓ Todos los valores renderizan correctamente${RST}" + if [[ $status -eq 0 ]]; then + echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" + else + echo -e " ${RED}✗ Error al renderizar templates${RST}" + echo "$out" | sed 's/^/ /' + exit_code=1 fi popd >/dev/null @@ -125,4 +87,4 @@ else echo -e "${RED}✗ Algunos templates tienen errores${RST}" fi -exit "$exit_code" +exit "$exit_code" \ No newline at end of file From ece44ea248163052e28027d255b57430d5e73848 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 14:27:51 -0300 Subject: [PATCH 06/14] changing template rendering hook --- README.md | 6 ++++-- hooks/helm-template-check.sh | 37 +++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3953da5..ee46340 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ supported hooks are: ## Helm/Kubernetes Hooks * **helm-lint**: Executes `helm lint` on all Helm charts (directories with `Chart.yaml`). Validates chart structure, syntax, and best practices. -* **helm-template-check**: Runs `helm template` to ensure templates can render without errors. Uses the default `values.yaml` file. Does not validate the output against Kubernetes schemas. +* **helm-template-check**: Runs `helm template` to ensure templates can render without errors, then validates the YAML syntax of the rendered output using `yamllint`. This catches indentation errors and other YAML syntax issues in your templates. Uses the default `values.yaml` file. + > Note: Requires `yamllint` to be installed for full validation. Without it, only template rendering is checked. * **yamllint**: Validates YAML syntax and style for all `.yaml` and `.yml` files. Checks indentation, duplicates, trailing spaces, etc. > Note: Copy `.yamllint.yaml` to your repo root for custom configuration. @@ -148,7 +149,8 @@ If yamllint reports too many warnings for your use case: Each hook requires specific tools to be installed: - **terraform-fmt, terraform-validate**: Requires Terraform CLI -- **helm-lint, helm-template-check**: Requires Helm CLI +- **helm-lint**: Requires Helm CLI +- **helm-template-check**: Requires Helm CLI and yamllint (yamllint optional but recommended for full validation) - **yamllint**: Requires yamllint Python package Install missing tools before running `pre-commit install`. diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index f0cc1e9..773e6f1 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -63,18 +63,41 @@ for chart_dir in "${CHART_DIRS[@]}"; do fi set +e - # Ejecutar helm template solo para verificar que renderice sin errores - # No validamos el output, solo que pueda generar algo - out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" + # Ejecutar helm template y capturar el output + rendered_output="$(helm template test-release . --values "$values_file" 2>&1)" status=$? set -e - if [[ $status -eq 0 ]]; then - echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" - else + if [[ $status -ne 0 ]]; then echo -e " ${RED}✗ Error al renderizar templates${RST}" - echo "$out" | sed 's/^/ /' + echo "$rendered_output" | sed 's/^/ /' exit_code=1 + else + # Templates renderizaron bien, ahora validar el YAML resultante + echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" + + # Validar YAML solo si yamllint está disponible + if command -v yamllint &>/dev/null; then + echo -e " ${BLD}→ Validando sintaxis YAML del output...${RST}" + + set +e + yaml_errors="$(echo "$rendered_output" | yamllint -f parsable -d '{extends: default, rules: {line-length: disable, document-start: disable}}' - 2>&1)" + yaml_status=$? + set -e + + if [[ $yaml_status -eq 0 ]]; then + echo -e " ${GRN}✓ YAML del output es válido${RST}" + else + echo -e " ${RED}✗ YAML del output tiene errores de sintaxis/indentación${RST}" + echo "$yaml_errors" | sed 's/^/ /' + exit_code=1 + fi + else + echo -e " ${YLW}⚠ yamllint no está instalado, no se validó la sintaxis del YAML renderizado${RST}" + echo -e " Instalá yamllint para validación completa:" + echo -e " - macOS: brew install yamllint" + echo -e " - Linux: pip install yamllint (o pipx install yamllint)" + fi fi popd >/dev/null From d58d19a086c65ba5ce23550212331cd4ad67dfba Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 14:37:38 -0300 Subject: [PATCH 07/14] changing template rendering hook --- hooks/helm-template-check.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index 773e6f1..e34f16b 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -81,7 +81,9 @@ for chart_dir in "${CHART_DIRS[@]}"; do echo -e " ${BLD}→ Validando sintaxis YAML del output...${RST}" set +e - yaml_errors="$(echo "$rendered_output" | yamllint -f parsable -d '{extends: default, rules: {line-length: disable, document-start: disable}}' - 2>&1)" + # Usar configuración relajada de yamllint para evitar falsos positivos + # Solo validar errores críticos de indentación y sintaxis + yaml_errors="$(echo "$rendered_output" | yamllint -f parsable -d '{extends: relaxed, rules: {line-length: disable, document-start: disable, trailing-spaces: enable, indentation: {spaces: consistent, indent-sequences: consistent}}}' - 2>&1)" yaml_status=$? set -e From f40caf26d3585e989ce9dd4c63616e75594603c0 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 14:43:48 -0300 Subject: [PATCH 08/14] rolled back template hook --- hooks/helm-template-check.sh | 39 +++++++----------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index e34f16b..f0cc1e9 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -63,43 +63,18 @@ for chart_dir in "${CHART_DIRS[@]}"; do fi set +e - # Ejecutar helm template y capturar el output - rendered_output="$(helm template test-release . --values "$values_file" 2>&1)" + # Ejecutar helm template solo para verificar que renderice sin errores + # No validamos el output, solo que pueda generar algo + out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" status=$? set -e - if [[ $status -ne 0 ]]; then + if [[ $status -eq 0 ]]; then + echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" + else echo -e " ${RED}✗ Error al renderizar templates${RST}" - echo "$rendered_output" | sed 's/^/ /' + echo "$out" | sed 's/^/ /' exit_code=1 - else - # Templates renderizaron bien, ahora validar el YAML resultante - echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" - - # Validar YAML solo si yamllint está disponible - if command -v yamllint &>/dev/null; then - echo -e " ${BLD}→ Validando sintaxis YAML del output...${RST}" - - set +e - # Usar configuración relajada de yamllint para evitar falsos positivos - # Solo validar errores críticos de indentación y sintaxis - yaml_errors="$(echo "$rendered_output" | yamllint -f parsable -d '{extends: relaxed, rules: {line-length: disable, document-start: disable, trailing-spaces: enable, indentation: {spaces: consistent, indent-sequences: consistent}}}' - 2>&1)" - yaml_status=$? - set -e - - if [[ $yaml_status -eq 0 ]]; then - echo -e " ${GRN}✓ YAML del output es válido${RST}" - else - echo -e " ${RED}✗ YAML del output tiene errores de sintaxis/indentación${RST}" - echo "$yaml_errors" | sed 's/^/ /' - exit_code=1 - fi - else - echo -e " ${YLW}⚠ yamllint no está instalado, no se validó la sintaxis del YAML renderizado${RST}" - echo -e " Instalá yamllint para validación completa:" - echo -e " - macOS: brew install yamllint" - echo -e " - Linux: pip install yamllint (o pipx install yamllint)" - fi fi popd >/dev/null From 6a3f59ec78e33e43ac676a53594dec49aab5c7c8 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 14:48:31 -0300 Subject: [PATCH 09/14] new version of template hook --- hooks/helm-template-check.sh | 49 ++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index f0cc1e9..83b1819 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -5,20 +5,19 @@ IFS=$'\n\t' RED='\033[31m'; GRN='\033[32m'; YLW='\033[33m'; BLD='\033[1m'; RST='\033[0m' if [[ "${PRE_COMMIT_COLOR:-}" == "never" ]]; then RED=''; GRN=''; YLW=''; BLD=''; RST=''; fi -# Verificar que helm esté instalado -if ! command -v helm &>/dev/null; then - echo -e "${RED}✗ Error: helm no está instalado${RST}" - echo " Instalá helm desde: https://helm.sh/docs/intro/install/" - exit 1 -fi +# Verificar que helm y yamllint estén instalados +for cmd in helm yamllint; do + if ! command -v "$cmd" &>/dev/null; then + echo -e "${RED}✗ Error: ${cmd} no está instalado${RST}" + exit 1 + fi +done # Recolectar directorios únicos que contienen Chart.yaml if [[ "$#" -gt 0 ]]; then - # Buscar Chart.yaml en los directorios de los archivos modificados mapfile -t CHART_DIRS < <( for f in "$@"; do dir="$(dirname "$f")" - # Buscar hacia arriba hasta encontrar Chart.yaml while [[ "$dir" != "." && "$dir" != "/" ]]; do if [[ -f "$dir/Chart.yaml" ]]; then echo "$dir" @@ -29,22 +28,20 @@ if [[ "$#" -gt 0 ]]; then done | sort -u ) else - # Buscar todos los Chart.yaml en el repo mapfile -t CHART_DIRS < <(find . -name "Chart.yaml" -exec dirname {} \; | sort -u) fi -# Si no hay charts, salir exitosamente if [[ "${#CHART_DIRS[@]}" -eq 0 ]]; then echo -e "${YLW}! No se encontraron Helm charts (Chart.yaml)${RST}" exit 0 fi exit_code=0 +YAMLLINT_CONFIG_FILE=".yamllint" for chart_dir in "${CHART_DIRS[@]}"; do echo -e "${BLD}>> Validando templates de Helm chart: ${chart_dir}${RST}" - # Verificar que exista el directorio templates if [[ ! -d "$chart_dir/templates" ]]; then echo -e " ${YLW}! Skipped (no hay directorio templates/)${RST}" echo @@ -53,7 +50,6 @@ for chart_dir in "${CHART_DIRS[@]}"; do pushd "$chart_dir" >/dev/null - # Verificar si existe values.yaml values_file="values.yaml" if [[ ! -f "$values_file" ]]; then echo -e " ${YLW}! Skipped (no existe values.yaml)${RST}" @@ -62,29 +58,38 @@ for chart_dir in "${CHART_DIRS[@]}"; do continue fi - set +e - # Ejecutar helm template solo para verificar que renderice sin errores - # No validamos el output, solo que pueda generar algo - out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" + set +e # Desactivamos la salida inmediata en caso de error + + # El comando '-' en yamllint le indica que lea desde la entrada estándar (stdin) + # Usamos una configuración de yamllint si existe para consistencia. + if [[ -f "../../$YAMLLINT_CONFIG_FILE" ]]; then + LINT_CMD="yamllint -c ../../$YAMLLINT_CONFIG_FILE -" + else + LINT_CMD="yamllint -" + fi + + # Generamos el template y lo pasamos al linter + out=$(helm template test-release . --values "$values_file" | $LINT_CMD 2>&1) status=$? - set -e + set -e # Reactivamos la salida en error if [[ $status -eq 0 ]]; then - echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" + echo -e " ${GRN}✓ Templates renderizan correctamente y el YAML es válido${RST}" else - echo -e " ${RED}✗ Error al renderizar templates${RST}" - echo "$out" | sed 's/^/ /' + echo -e " ${RED}✗ Error al renderizar o validar el YAML de los templates${RST}" + echo "$out" | sed 's/^/ /' # Indentamos la salida del error para mayor claridad exit_code=1 fi + # --- FIN DEL CAMBIO --- popd >/dev/null echo done if [[ $exit_code -eq 0 ]]; then - echo -e "${GRN}✓ Todos los templates se renderizaron correctamente${RST}" + echo -e "${GRN}✓ Todos los templates se renderizaron y validaron correctamente${RST}" else - echo -e "${RED}✗ Algunos templates tienen errores${RST}" + echo -e "${RED}✗ Algunos templates tienen errores de renderizado o indentación${RST}" fi exit "$exit_code" \ No newline at end of file From 2d2d999bc21caf41fdd42ecce0a0b80e1410a076 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 14:58:13 -0300 Subject: [PATCH 10/14] new version of template hook --- hooks/helm-template-check.sh | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index 83b1819..ee38954 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -58,29 +58,35 @@ for chart_dir in "${CHART_DIRS[@]}"; do continue fi - set +e # Desactivamos la salida inmediata en caso de error - - # El comando '-' en yamllint le indica que lea desde la entrada estándar (stdin) - # Usamos una configuración de yamllint si existe para consistencia. - if [[ -f "../../$YAMLLINT_CONFIG_FILE" ]]; then - LINT_CMD="yamllint -c ../../$YAMLLINT_CONFIG_FILE -" + set +e + # Determinar la raíz del repo para resolver configuración de yamllint + REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" + + # Construir el comando de yamllint como un array (evita problemas con IFS sin espacios) + yamllint_cmd=(yamllint) + if [[ -f "$REPO_ROOT/.yamllint" ]]; then + yamllint_cmd+=( -c "$REPO_ROOT/.yamllint" ) + elif [[ -f "$REPO_ROOT/.yamllint.yaml" ]]; then + yamllint_cmd+=( -c "$REPO_ROOT/.yamllint.yaml" ) else - LINT_CMD="yamllint -" + # Configuración relajada por defecto para evitar falsos positivos de estilo + yamllint_cmd+=( -d '{extends: relaxed, rules: {line-length: disable, document-start: disable, trailing-spaces: enable, indentation: {spaces: consistent, indent-sequences: consistent}}}' ) fi + # Leer desde stdin + yamllint_cmd+=( - ) - # Generamos el template y lo pasamos al linter - out=$(helm template test-release . --values "$values_file" | $LINT_CMD 2>&1) + # Generar templates y validar YAML + out="$(helm template test-release . --values "$values_file" | "${yamllint_cmd[@]}" 2>&1)" status=$? - set -e # Reactivamos la salida en error + set -e if [[ $status -eq 0 ]]; then echo -e " ${GRN}✓ Templates renderizan correctamente y el YAML es válido${RST}" else echo -e " ${RED}✗ Error al renderizar o validar el YAML de los templates${RST}" - echo "$out" | sed 's/^/ /' # Indentamos la salida del error para mayor claridad + echo "$out" | sed 's/^/ /' exit_code=1 fi - # --- FIN DEL CAMBIO --- popd >/dev/null echo From ca1ecf8682be4391401d15831994ebaeec3a91d3 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 15:45:53 -0300 Subject: [PATCH 11/14] hook update --- hooks/helm-template-check.sh | 49 ++++++++++++++---------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index ee38954..f0cc1e9 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -5,19 +5,20 @@ IFS=$'\n\t' RED='\033[31m'; GRN='\033[32m'; YLW='\033[33m'; BLD='\033[1m'; RST='\033[0m' if [[ "${PRE_COMMIT_COLOR:-}" == "never" ]]; then RED=''; GRN=''; YLW=''; BLD=''; RST=''; fi -# Verificar que helm y yamllint estén instalados -for cmd in helm yamllint; do - if ! command -v "$cmd" &>/dev/null; then - echo -e "${RED}✗ Error: ${cmd} no está instalado${RST}" - exit 1 - fi -done +# Verificar que helm esté instalado +if ! command -v helm &>/dev/null; then + echo -e "${RED}✗ Error: helm no está instalado${RST}" + echo " Instalá helm desde: https://helm.sh/docs/intro/install/" + exit 1 +fi # Recolectar directorios únicos que contienen Chart.yaml if [[ "$#" -gt 0 ]]; then + # Buscar Chart.yaml en los directorios de los archivos modificados mapfile -t CHART_DIRS < <( for f in "$@"; do dir="$(dirname "$f")" + # Buscar hacia arriba hasta encontrar Chart.yaml while [[ "$dir" != "." && "$dir" != "/" ]]; do if [[ -f "$dir/Chart.yaml" ]]; then echo "$dir" @@ -28,20 +29,22 @@ if [[ "$#" -gt 0 ]]; then done | sort -u ) else + # Buscar todos los Chart.yaml en el repo mapfile -t CHART_DIRS < <(find . -name "Chart.yaml" -exec dirname {} \; | sort -u) fi +# Si no hay charts, salir exitosamente if [[ "${#CHART_DIRS[@]}" -eq 0 ]]; then echo -e "${YLW}! No se encontraron Helm charts (Chart.yaml)${RST}" exit 0 fi exit_code=0 -YAMLLINT_CONFIG_FILE=".yamllint" for chart_dir in "${CHART_DIRS[@]}"; do echo -e "${BLD}>> Validando templates de Helm chart: ${chart_dir}${RST}" + # Verificar que exista el directorio templates if [[ ! -d "$chart_dir/templates" ]]; then echo -e " ${YLW}! Skipped (no hay directorio templates/)${RST}" echo @@ -50,6 +53,7 @@ for chart_dir in "${CHART_DIRS[@]}"; do pushd "$chart_dir" >/dev/null + # Verificar si existe values.yaml values_file="values.yaml" if [[ ! -f "$values_file" ]]; then echo -e " ${YLW}! Skipped (no existe values.yaml)${RST}" @@ -59,31 +63,16 @@ for chart_dir in "${CHART_DIRS[@]}"; do fi set +e - # Determinar la raíz del repo para resolver configuración de yamllint - REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" - - # Construir el comando de yamllint como un array (evita problemas con IFS sin espacios) - yamllint_cmd=(yamllint) - if [[ -f "$REPO_ROOT/.yamllint" ]]; then - yamllint_cmd+=( -c "$REPO_ROOT/.yamllint" ) - elif [[ -f "$REPO_ROOT/.yamllint.yaml" ]]; then - yamllint_cmd+=( -c "$REPO_ROOT/.yamllint.yaml" ) - else - # Configuración relajada por defecto para evitar falsos positivos de estilo - yamllint_cmd+=( -d '{extends: relaxed, rules: {line-length: disable, document-start: disable, trailing-spaces: enable, indentation: {spaces: consistent, indent-sequences: consistent}}}' ) - fi - # Leer desde stdin - yamllint_cmd+=( - ) - - # Generar templates y validar YAML - out="$(helm template test-release . --values "$values_file" | "${yamllint_cmd[@]}" 2>&1)" + # Ejecutar helm template solo para verificar que renderice sin errores + # No validamos el output, solo que pueda generar algo + out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" status=$? set -e if [[ $status -eq 0 ]]; then - echo -e " ${GRN}✓ Templates renderizan correctamente y el YAML es válido${RST}" + echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" else - echo -e " ${RED}✗ Error al renderizar o validar el YAML de los templates${RST}" + echo -e " ${RED}✗ Error al renderizar templates${RST}" echo "$out" | sed 's/^/ /' exit_code=1 fi @@ -93,9 +82,9 @@ for chart_dir in "${CHART_DIRS[@]}"; do done if [[ $exit_code -eq 0 ]]; then - echo -e "${GRN}✓ Todos los templates se renderizaron y validaron correctamente${RST}" + echo -e "${GRN}✓ Todos los templates se renderizaron correctamente${RST}" else - echo -e "${RED}✗ Algunos templates tienen errores de renderizado o indentación${RST}" + echo -e "${RED}✗ Algunos templates tienen errores${RST}" fi exit "$exit_code" \ No newline at end of file From 6f37569a3f42ea00b25dbd40be223af23a955ca9 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 15:57:11 -0300 Subject: [PATCH 12/14] updated template pre-commit hook --- hooks/helm-template-check.sh | 52 ++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/hooks/helm-template-check.sh b/hooks/helm-template-check.sh index f0cc1e9..689202d 100755 --- a/hooks/helm-template-check.sh +++ b/hooks/helm-template-check.sh @@ -62,29 +62,53 @@ for chart_dir in "${CHART_DIRS[@]}"; do continue fi - set +e - # Ejecutar helm template solo para verificar que renderice sin errores - # No validamos el output, solo que pueda generar algo - out="$(helm template test-release . --values "$values_file" 2>&1 >/dev/null)" - status=$? - set -e + # Array para almacenar archivos de valores a probar + declare -a values_files=("$values_file") - if [[ $status -eq 0 ]]; then - echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" - else - echo -e " ${RED}✗ Error al renderizar templates${RST}" - echo "$out" | sed 's/^/ /' - exit_code=1 + # Buscar archivos de ejemplo en examples/ + if [[ -d "examples" ]]; then + while IFS= read -r -d '' example_file; do + values_files+=("$example_file") + done < <(find examples -type f \( -name "*.yaml" -o -name "*.yml" \) -print0 2>/dev/null | sort -z) fi + echo -e " ${BLD}Casos de prueba encontrados: ${#values_files[@]}${RST}" + + # Iterar sobre todos los archivos de valores + for values_test_file in "${values_files[@]}"; do + # Obtener nombre descriptivo del archivo + if [[ "$values_test_file" == "values.yaml" ]]; then + test_name="valores por defecto" + else + test_name="$(basename "$values_test_file")" + fi + + echo -e " ${BLD}→ Probando: ${test_name}${RST}" + + set +e + # Ejecutar helm template solo para verificar que renderice sin errores + # No validamos el output, solo que pueda generar algo + out="$(helm template test-release . --values "$values_test_file" 2>&1 >/dev/null)" + status=$? + set -e + + if [[ $status -eq 0 ]]; then + echo -e " ${GRN}✓ Templates renderizan correctamente${RST}" + else + echo -e " ${RED}✗ Error al renderizar templates${RST}" + echo "$out" | sed 's/^/ /' + exit_code=1 + fi + done + popd >/dev/null echo done if [[ $exit_code -eq 0 ]]; then - echo -e "${GRN}✓ Todos los templates se renderizaron correctamente${RST}" + echo -e "${GRN}✓ Todos los templates se renderizaron correctamente con todos los casos de prueba${RST}" else - echo -e "${RED}✗ Algunos templates tienen errores${RST}" + echo -e "${RED}✗ Algunos templates tienen errores en uno o más casos de prueba${RST}" fi exit "$exit_code" \ No newline at end of file From 6f080620f6c25a7c9c5b1ac20fecce11067da7aa Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 16:20:40 -0300 Subject: [PATCH 13/14] updated README --- README.md | 308 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 213 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index ee46340..572eab5 100644 --- a/README.md +++ b/README.md @@ -1,160 +1,278 @@ -# Pre-commit hooks +# Pre-commit Hooks Collection -This repo defines Git pre-commit hooks intended for use with [pre-commit](https://pre-commit.com/). The currently -supported hooks are: +
-> 🚀 **Quick Start**: New to pre-commit? Check out our [Quick Start Guide](QUICKSTART.md) for a 5-minute setup! +**Quality gates for your Infrastructure as Code** -## Terraform Hooks +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) +[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://pre-commit.com/) -* **terraform-fmt**: Checks that all Terraform files (`*.tf`) are properly formatted (`terraform fmt --check -diff`). -* **terraform-validate**: Runs `terraform init -backend=false` and then `terraform validate`. - > Notes: directories requiring a private registry and lacking credentials are marked as **skipped** (do not fail the commit). Both hooks ignore `.terraform/` and `examples/`. +
-## Helm/Kubernetes Hooks +--- -* **helm-lint**: Executes `helm lint` on all Helm charts (directories with `Chart.yaml`). Validates chart structure, syntax, and best practices. -* **helm-template-check**: Runs `helm template` to ensure templates can render without errors, then validates the YAML syntax of the rendered output using `yamllint`. This catches indentation errors and other YAML syntax issues in your templates. Uses the default `values.yaml` file. - > Note: Requires `yamllint` to be installed for full validation. Without it, only template rendering is checked. -* **yamllint**: Validates YAML syntax and style for all `.yaml` and `.yml` files. Checks indentation, duplicates, trailing spaces, etc. - > Note: Copy `.yamllint.yaml` to your repo root for custom configuration. +## Overview -## General Usage +This repository provides a curated collection of **Git pre-commit hooks** designed to enforce best practices and catch issues early in your Infrastructure as Code (IaC) workflows. By integrating these hooks into your development process, you can ensure code quality, consistency, and compliance before changes ever reach your repository. -In each of your repos, add a file called `.pre-commit-config.yaml` with the following contents: +### Why Use Pre-commit Hooks? -### For Terraform projects: +- **Catch issues early** - Identify problems before they reach CI/CD +- **Fast feedback loop** - Get instant validation on your local machine +- **Enforce standards** - Maintain consistent code quality across teams +- **Prevent broken commits** - Block commits that don't meet your criteria +- **Team collaboration** - Share the same quality gates with everyone -```yaml -repos: - - repo: git@github.com:craftech-io/pre-commit.git # or https://github.com/craftech-io/pre-commit.git - rev: - hooks: - - id: terraform-fmt - - id: terraform-validate - verbose: true -``` +--- -### For Helm/Kubernetes projects: +## Available Hooks -```yaml -repos: - - repo: git@github.com:craftech-io/pre-commit.git # or https://github.com/craftech-io/pre-commit.git - rev: - hooks: - - id: yamllint - - id: helm-lint - - id: helm-template-check +### Terraform Hooks + +| Hook | Description | What it does | +|------|-------------|--------------| +| `terraform-fmt` | **Format checker** | Verifies all `.tf` files are properly formatted using `terraform fmt --check -diff` | +| `terraform-validate` | **Syntax validator** | Runs `terraform init -backend=false` followed by `terraform validate` to catch configuration errors | + +> **Note:** Directories requiring private registries without credentials are automatically skipped. Both hooks ignore `.terraform/` and `examples/` directories. + +### Helm Hooks + +| Hook | Description | What it does | +|------|-------------|--------------| +| `helm-lint` | **Chart linter** | Validates Helm charts using `helm lint` to check for common issues and best practices | +| `helm-template-check` | **Template validator** | Renders templates with `helm template` to ensure they generate valid Kubernetes manifests | + +> **Note:** Helm hooks automatically discover charts by locating `Chart.yaml` files in your repository. + +--- + +## Quick Start + +### Prerequisites + +First, ensure you have [pre-commit](https://pre-commit.com/) installed on your system: + +```bash +# macOS +brew install pre-commit + +# Linux (recommended) +pipx install pre-commit + +# Linux (alternative) +pip install --user pre-commit + +# Windows (WSL or Git Bash) +pip install pre-commit ``` -### For mixed projects (Terraform + Helm): +### Installation + +**Step 1: Add the configuration file** + +Create a `.pre-commit-config.yaml` file in the root of your repository: ```yaml repos: - repo: git@github.com:craftech-io/pre-commit.git - rev: + # or use: https://github.com/craftech-io/pre-commit.git + rev: # Use the latest release tag hooks: - # Terraform + # Terraform hooks - id: terraform-fmt - id: terraform-validate - # Helm/Kubernetes - - id: yamllint + verbose: true # Show detailed output + + # Helm hooks - id: helm-lint - id: helm-template-check ``` -Next, have every developer: +> **Tip:** Replace `` with the latest release tag (e.g., `v1.0.0`). Check the [releases page](https://github.com/craftech-io/pre-commit/releases) for available versions. + +**Step 2: Install the hooks** + +Run this command in your repository: + +```bash +pre-commit install +``` + +**Step 3: You're all set!** -1. Install [pre-commit](https://pre-commit.com/#install). - - macOS: `brew install pre-commit` - - Linux: `pipx install pre-commit` (or `pip install --user pre-commit`) -2. Install required tools based on your hooks: - - **Terraform hooks**: Install [Terraform](https://www.terraform.io/downloads) - - **Helm hooks**: Install [Helm](https://helm.sh/docs/intro/install/) - - **yamllint hook**: Install yamllint (`brew install yamllint` or `pip install yamllint`) -3. Run `pre-commit install` in the repo. +Now, every time you run `git commit`, the configured hooks will automatically execute. If any hook fails, the commit will be blocked, allowing you to fix issues before they're committed. -That's it! Now every time you commit a code change (`.tf` file), the hooks in the `hooks:` config will execute. -If any hook fails, the commit is aborted; if all pass, the commit succeeds. +--- -## Running Against All Files At Once +## Usage -### Terraform: Formatting and validating all files +### Automatic Validation (Recommended) -If you'd like to run the hooks across the whole repo (useful the first time), you can run: +Once installed, hooks run automatically on every commit: ```bash -# Check formatting for all Terraform files -pre-commit run terraform-fmt --all-files +git add . +git commit -m "feat: add new infrastructure" +# Hooks will run automatically here! +``` + +### Manual Execution + +Run hooks manually without committing: + +```bash +# Run all configured hooks on staged files +pre-commit run + +# Run a specific hook on staged files +pre-commit run terraform-fmt -# Validate all Terraform directories +# Run hooks on all files in the repository +pre-commit run --all-files + +# Run a specific hook on all files pre-commit run terraform-validate --all-files ``` -### Helm/Kubernetes: Linting and validating all files +### Common Commands ```bash -# Validate YAML syntax in all files -pre-commit run yamllint --all-files +# Run all hooks with verbose output +pre-commit run --all-files -v -# Lint all Helm charts -pre-commit run helm-lint --all-files +# Run only Terraform hooks +pre-commit run terraform-fmt --all-files +pre-commit run terraform-validate --all-files -# Check that all Helm templates can render +# Run only Helm hooks +pre-commit run helm-lint --all-files pre-commit run helm-template-check --all-files + +# Update hooks to the latest version +pre-commit autoupdate + +# Temporarily bypass hooks (not recommended!) +git commit --no-verify ``` -### Run all configured hooks at once +--- -```bash -# Or run every configured hook across the repo -pre-commit run --all-files +## Advanced Configuration + +### Customizing Hook Behavior + +You can customize hooks in your `.pre-commit-config.yaml`: + +```yaml +repos: + - repo: git@github.com:craftech-io/pre-commit.git + rev: + hooks: + - id: terraform-fmt + # Run on specific file patterns only + files: ^modules/ + + - id: terraform-validate + # Exclude specific directories + exclude: ^(examples|tests)/ + + - id: helm-lint + # Always show verbose output + verbose: true + + - id: helm-template-check + # Run even if files haven't changed + always_run: false ``` -> Tip: for detailed output on demand, use `-v`, e.g. `pre-commit run -v helm-lint --all-files`. +### Combining with Other Hooks + +Mix these hooks with other pre-commit hooks for comprehensive validation: -## Optional Configuration +```yaml +repos: + # This repository's hooks + - repo: git@github.com:craftech-io/pre-commit.git + rev: + hooks: + - id: terraform-fmt + - id: helm-lint + + # Additional hooks from other sources + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files +``` -### yamllint Configuration +--- -By default, `yamllint` uses strict rules. You can customize the behavior by copying the example configuration to your repo: +## Contributing + +We welcome contributions! Here's how you can help improve this project: + +### Adding New Hooks + +1. **Create the hook script** in the `hooks/` directory +2. **Make it executable**: `chmod +x hooks/your-hook.sh` +3. **Add entry** to `.pre-commit-hooks.yaml` +4. **Test thoroughly** with various scenarios +5. **Submit a pull request** with a clear description + +### Testing Your Changes + +Before submitting a PR, test your hooks: ```bash -# Copy the example configuration -cp .yamllint.yaml /path/to/your/repo/.yamllint.yaml +# Test on a specific file +bash hooks/your-hook.sh path/to/test/file -# Or download it directly -curl -O https://raw.githubusercontent.com/craftech-io/pre-commit/main/.yamllint.yaml +# Test with pre-commit +pre-commit try-repo /path/to/your/local/repo your-hook-id --verbose --all-files ``` -Then customize `.yamllint.yaml` in your repo root according to your needs. See [yamllint documentation](https://yamllint.readthedocs.io/) for all available options. +### Development Guidelines -## Troubleshooting +- Follow existing code style and structure +- Include error handling and clear error messages +- Add colorized output for better readability +- Write descriptive commit messages +- Update documentation (README, comments) +- Test on multiple scenarios (success, failure, edge cases) -### Helm hooks are skipped +### Reporting Issues -If the Helm hooks show "No Helm charts found", ensure your repository has: -- A `Chart.yaml` file in your chart directory -- A `templates/` directory with your Kubernetes manifests -- A `values.yaml` file (required for template rendering) +Found a bug or have a suggestion? Please [open an issue](https://github.com/craftech-io/pre-commit/issues) with: -### yamllint is too strict +- **Clear description** of the problem or enhancement +- **Steps to reproduce** (for bugs) +- **Expected vs actual behavior** +- **Environment details** (OS, tool versions) -If yamllint reports too many warnings for your use case: -1. Copy the `.yamllint.yaml` configuration file to your repo -2. Adjust the rules (e.g., increase `line-length`, disable specific rules) -3. Commit the configuration file +--- -### Dependencies not installed +## Additional Resources -Each hook requires specific tools to be installed: -- **terraform-fmt, terraform-validate**: Requires Terraform CLI -- **helm-lint**: Requires Helm CLI -- **helm-template-check**: Requires Helm CLI and yamllint (yamllint optional but recommended for full validation) -- **yamllint**: Requires yamllint Python package +- [Pre-commit Documentation](https://pre-commit.com/) +- [Terraform Documentation](https://www.terraform.io/docs) +- [Helm Documentation](https://helm.sh/docs/) +- [Pre-commit Hook Examples](https://github.com/pre-commit/pre-commit-hooks) -Install missing tools before running `pre-commit install`. +--- ## License -This code is released under the Apache 2.0 License. Please see [LICENSE](LICENSE) for more details. \ No newline at end of file +This project is released under the **Apache 2.0 License**. + + +
+ +**[Back to Top](#pre-commit-hooks-collection)** + +Made by Craftech + +
\ No newline at end of file From 2ea6b34911ddca784ca09838bc05371e2939ae26 Mon Sep 17 00:00:00 2001 From: Lautaro Torchia Date: Fri, 17 Oct 2025 16:41:05 -0300 Subject: [PATCH 14/14] Update README.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 572eab5..dd66598 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ pip install pre-commit ### Installation -**Step 1: Add the configuration file** +### Step 1: Add the configuration file Create a `.pre-commit-config.yaml` file in the root of your repository: