From ff09c415e8aeb856ce6423e4b97a894770337c08 Mon Sep 17 00:00:00 2001 From: DevCats Date: Thu, 16 Oct 2025 14:21:03 -0500 Subject: [PATCH] feat: change tf test and validation to use paths-filter (#483) ## Description ## Type of Change - [ ] New module - [ ] New template - [ ] Bug fix - [ ] Feature/enhancement - [ ] Documentation - [ ] Other ## Module Information **Path:** `registry/[namespace]/modules/[module-name]` **New version:** `v1.0.0` **Breaking change:** [ ] Yes [ ] No ## Template Information **Path:** `registry/[namespace]/templates/[template-name]` ## Testing & Validation - [ ] Tests pass (`bun test`) - [ ] Code formatted (`bun fmt`) - [ ] Changes tested locally ## Related Issues --- .github/workflows/ci.yaml | 14 ++++++- package.json | 3 +- scripts/terraform_test_all.sh | 72 ++++++++++++++++++++++++++++++-- scripts/terraform_validate.sh | 78 +++++++++++++++++++++++++++++------ 4 files changed, 149 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1079f8ea..502511c9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,6 +27,8 @@ jobs: - 'tsconfig.json' - '.github/workflows/ci.yaml' - 'scripts/ts_test_auto.sh' + - 'scripts/terraform_test_all.sh' + - 'scripts/terraform_validate.sh' modules: - 'registry/**/modules/**' all: @@ -49,10 +51,18 @@ jobs: ALL_CHANGED_FILES: ${{ steps.filter.outputs.all_files }} SHARED_CHANGED: ${{ steps.filter.outputs.shared }} MODULE_CHANGED_FILES: ${{ steps.filter.outputs.modules_files }} - run: ./scripts/ts_test_auto.sh + run: bun tstest - name: Run Terraform tests - run: ./scripts/terraform_test_all.sh + env: + ALL_CHANGED_FILES: ${{ steps.filter.outputs.all_files }} + SHARED_CHANGED: ${{ steps.filter.outputs.shared }} + MODULE_CHANGED_FILES: ${{ steps.filter.outputs.modules_files }} + run: bun tftest - name: Run Terraform Validate + env: + ALL_CHANGED_FILES: ${{ steps.filter.outputs.all_files }} + SHARED_CHANGED: ${{ steps.filter.outputs.shared }} + MODULE_CHANGED_FILES: ${{ steps.filter.outputs.modules_files }} run: bun terraform-validate validate-style: name: Check for typos and unformatted code diff --git a/package.json b/package.json index d441e6ac..c1f73dd2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "fmt": "bun x prettier --write . && terraform fmt -recursive -diff", "fmt:ci": "bun x prettier --check . && terraform fmt -check -recursive -diff", "terraform-validate": "./scripts/terraform_validate.sh", - "test": "./scripts/terraform_test_all.sh", + "tftest": "./scripts/terraform_test_all.sh", + "tstest": "./scripts/ts_test_auto.sh", "update-version": "./update-version.sh" }, "devDependencies": { diff --git a/scripts/terraform_test_all.sh b/scripts/terraform_test_all.sh index 01258904..2da60d63 100755 --- a/scripts/terraform_test_all.sh +++ b/scripts/terraform_test_all.sh @@ -1,7 +1,14 @@ #!/usr/bin/env bash set -euo pipefail -# Find all directories that contain any .tftest.hcl files and run terraform test in each +# Auto-detect which Terraform tests to run based on changed files from paths-filter +# Uses paths-filter outputs from GitHub Actions: +# ALL_CHANGED_FILES - all files changed in the PR (for logging) +# SHARED_CHANGED - boolean indicating if shared infrastructure changed +# MODULE_CHANGED_FILES - only files in registry/**/modules/** (for processing) +# Runs all tests if shared infrastructure changes, or skips if no changes detected +# +# This script only runs tests for changed modules. Documentation and template changes are ignored. run_dir() { local dir="$1" @@ -9,13 +16,72 @@ run_dir() { (cd "$dir" && terraform init -upgrade -input=false -no-color > /dev/null && terraform test -no-color -verbose) } -mapfile -t test_dirs < <(find . -type f -name "*.tftest.hcl" -print0 | xargs -0 -I{} dirname {} | sort -u) +echo "==> Detecting changed files..." + +if [[ -n "${ALL_CHANGED_FILES:-}" ]]; then + echo "Changed files in PR:" + echo "$ALL_CHANGED_FILES" | tr ' ' '\n' | sed 's/^/ - /' + echo "" +fi + +if [[ "${SHARED_CHANGED:-false}" == "true" ]]; then + echo "==> Shared infrastructure changed" + echo "==> Running all tests for safety" + mapfile -t test_dirs < <(find . -type f -name "*.tftest.hcl" -print0 | xargs -0 -I{} dirname {} | sort -u) +elif [[ -z "${MODULE_CHANGED_FILES:-}" ]]; then + echo "✓ No module files changed, skipping tests" + exit 0 +else + CHANGED_FILES=$(echo "$MODULE_CHANGED_FILES" | tr ' ' '\n') + + MODULE_DIRS=() + while IFS= read -r file; do + if [[ "$file" =~ \.(md|png|jpg|jpeg|svg)$ ]]; then + continue + fi + + if [[ "$file" =~ ^registry/([^/]+)/modules/([^/]+)/ ]]; then + namespace="${BASH_REMATCH[1]}" + module="${BASH_REMATCH[2]}" + module_dir="registry/${namespace}/modules/${module}" + + if [[ -d "$module_dir" ]] && [[ ! " ${MODULE_DIRS[*]} " =~ " ${module_dir} " ]]; then + MODULE_DIRS+=("$module_dir") + fi + fi + done <<< "$CHANGED_FILES" + + if [[ ${#MODULE_DIRS[@]} -eq 0 ]]; then + echo "✓ No Terraform tests to run" + echo " (documentation, templates, namespace files, or modules without changes)" + exit 0 + fi + + echo "==> Finding .tftest.hcl files in ${#MODULE_DIRS[@]} changed module(s):" + for dir in "${MODULE_DIRS[@]}"; do + echo " - $dir" + done + echo "" + + test_dirs=() + for module_dir in "${MODULE_DIRS[@]}"; do + while IFS= read -r test_file; do + test_dir=$(dirname "$test_file") + if [[ ! " ${test_dirs[*]} " =~ " ${test_dir} " ]]; then + test_dirs+=("$test_dir") + fi + done < <(find "$module_dir" -type f -name "*.tftest.hcl") + done +fi if [[ ${#test_dirs[@]} -eq 0 ]]; then - echo "No .tftest.hcl tests found." + echo "✓ No .tftest.hcl tests found in changed modules" exit 0 fi +echo "==> Running terraform test in ${#test_dirs[@]} directory(ies)" +echo "" + status=0 for d in "${test_dirs[@]}"; do if ! run_dir "$d"; then diff --git a/scripts/terraform_validate.sh b/scripts/terraform_validate.sh index 5991eb4b..5eb75f63 100755 --- a/scripts/terraform_validate.sh +++ b/scripts/terraform_validate.sh @@ -2,36 +2,90 @@ set -euo pipefail +# Auto-detect which Terraform modules to validate based on changed files from paths-filter +# Uses paths-filter outputs from GitHub Actions: +# ALL_CHANGED_FILES - all files changed in the PR (for logging) +# SHARED_CHANGED - boolean indicating if shared infrastructure changed +# MODULE_CHANGED_FILES - only files in registry/**/modules/** (for processing) +# Validates all modules if shared infrastructure changes, or skips if no changes detected +# +# This script only validates changed modules. Documentation and template changes are ignored. + validate_terraform_directory() { local dir="$1" echo "Running \`terraform validate\` in $dir" - pushd "$dir" + pushd "$dir" > /dev/null terraform init -upgrade terraform validate - popd + popd > /dev/null } main() { - # Get the directory of the script + echo "==> Detecting changed files..." + + if [[ -n "${ALL_CHANGED_FILES:-}" ]]; then + echo "Changed files in PR:" + echo "$ALL_CHANGED_FILES" | tr ' ' '\n' | sed 's/^/ - /' + echo "" + fi + local script_dir=$(dirname "$(readlink -f "$0")") + local registry_dir=$(readlink -f "$script_dir/../registry") - # Code assumes that registry directory will always be in same position - # relative to the main script directory - local registry_dir="$script_dir/../registry" + if [[ "${SHARED_CHANGED:-false}" == "true" ]]; then + echo "==> Shared infrastructure changed" + echo "==> Validating all modules for safety" + local subdirs=$(find "$registry_dir" -mindepth 3 -maxdepth 3 -path "*/modules/*" -type d | sort) + elif [[ -z "${MODULE_CHANGED_FILES:-}" ]]; then + echo "✓ No module files changed, skipping validation" + exit 0 + else + CHANGED_FILES=$(echo "$MODULE_CHANGED_FILES" | tr ' ' '\n') - # Get all module subdirectories in the registry directory. Code assumes that - # Terraform module directories won't begin to appear until three levels deep into - # the registry (e.g., registry/coder/modules/coder-login, which will then - # have a main.tf file inside it) - local subdirs=$(find "$registry_dir" -mindepth 3 -path "*/modules/*" -type d | sort) + MODULE_DIRS=() + while IFS= read -r file; do + if [[ "$file" =~ \.(md|png|jpg|jpeg|svg)$ ]]; then + continue + fi + if [[ "$file" =~ ^registry/([^/]+)/modules/([^/]+)/ ]]; then + namespace="${BASH_REMATCH[1]}" + module="${BASH_REMATCH[2]}" + module_dir="registry/${namespace}/modules/${module}" + + if [[ -d "$module_dir" ]] && [[ ! " ${MODULE_DIRS[*]} " =~ " ${module_dir} " ]]; then + MODULE_DIRS+=("$module_dir") + fi + fi + done <<< "$CHANGED_FILES" + + if [[ ${#MODULE_DIRS[@]} -eq 0 ]]; then + echo "✓ No modules to validate" + echo " (documentation, templates, namespace files, or modules without changes)" + exit 0 + fi + + echo "==> Validating ${#MODULE_DIRS[@]} changed module(s):" + for dir in "${MODULE_DIRS[@]}"; do + echo " - $dir" + done + echo "" + + local subdirs="${MODULE_DIRS[*]}" + fi + + status=0 for dir in $subdirs; do # Skip over any directories that obviously don't have the necessary # files if test -f "$dir/main.tf"; then - validate_terraform_directory "$dir" + if ! validate_terraform_directory "$dir"; then + status=1 + fi fi done + + exit $status } main