diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b6ebdc565a..6c57445a71d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -957,6 +957,38 @@ jobs: if-no-files-found: ignore retention-days: 14 + check-validator-sizes: + name: Check validator file sizes + runs-on: ubuntu-latest + # Non-blocking: report violations but don't fail the build until existing files are cleaned up + continue-on-error: true + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Check validator file sizes + id: check + run: | + set +e + OUTPUT=$(NO_COLOR=1 bash scripts/check-validator-sizes.sh 2>&1) + EXIT_CODE=$? + echo "$OUTPUT" + echo "exit_code=$EXIT_CODE" >> "$GITHUB_OUTPUT" + echo "## Validator File Size Check" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Checking \`*_validation.go\` files against the 768-line hard limit (AGENTS.md)." >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "\`\`\`" >> "$GITHUB_STEP_SUMMARY" + echo "$OUTPUT" >> "$GITHUB_STEP_SUMMARY" + echo "\`\`\`" >> "$GITHUB_STEP_SUMMARY" + if [ "$EXIT_CODE" -ne 0 ]; then + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "⚠️ This check is currently non-blocking. Fix violations to keep the codebase healthy." >> "$GITHUB_STEP_SUMMARY" + fi + exit "$EXIT_CODE" + lint-go: runs-on: ubuntu-latest permissions: diff --git a/Makefile b/Makefile index e43c3205f1c..ecba6ab3bde 100644 --- a/Makefile +++ b/Makefile @@ -611,6 +611,12 @@ lint-errors: check-file-sizes: @bash scripts/check-file-sizes.sh +# Check that *_validation.go files stay within the 768-line hard limit +# Set WARN_ONLY=1 to report violations without failing (non-blocking mode) +.PHONY: check-validator-sizes +check-validator-sizes: + @bash scripts/check-validator-sizes.sh + # Validate all project files .PHONY: lint lint: fmt-check fmt-check-json lint-cjs golint @@ -802,6 +808,8 @@ help: @echo " lint-cjs - Lint JavaScript (.cjs) and JSON files in actions/setup/js" @echo " lint-json - Lint JSON files in pkg directory (excluding actions/setup/js)" @echo " lint-errors - Lint error messages for quality compliance" + @echo " check-file-sizes - Check Go file sizes and function counts (informational)" + @echo " check-validator-sizes - Check *_validation.go files against the 768-line hard limit" @echo " security-scan - Run all security scans (gosec, govulncheck, trivy)" @echo " security-gosec - Run gosec Go security scanner" @echo " security-govulncheck - Run govulncheck for known vulnerabilities" diff --git a/scripts/check-validator-sizes.sh b/scripts/check-validator-sizes.sh new file mode 100755 index 00000000000..017ba94a8ed --- /dev/null +++ b/scripts/check-validator-sizes.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# check-validator-sizes.sh - Enforce the 512-line hard limit on validator files +# +# This script finds any *_validation.go file that exceeds the limit and reports it. +# +# Exit codes: +# 0 - All validator files are within the limit (or WARN_ONLY=1) +# 1 - One or more validator files exceed the limit + +set -euo pipefail + +# Disable colors when not connected to a TTY, when NO_COLOR is set, or when +# TERM=dumb — this keeps output readable when captured into CI step summaries. +if [ -t 1 ] && [ -z "${NO_COLOR:-}" ] && [ "${TERM:-}" != "dumb" ]; then + RED='\033[0;31m' + YELLOW='\033[1;33m' + GREEN='\033[0;32m' + NC='\033[0m' +else + RED='' + YELLOW='' + GREEN='' + NC='' +fi + +# Hard limit (lines per validator file) +HARD_LIMIT=768 + +# Set WARN_ONLY=1 to make the check non-blocking (report but always exit 0) +WARN_ONLY="${WARN_ONLY:-0}" + +over_limit=0 + +echo "Checking validator file sizes in pkg/ directory (limit: ${HARD_LIMIT} lines)..." +echo "" + +# Find all *_validation.go files, excluding test files +while IFS= read -r file; do + # wc -l counts newline characters; a file without a trailing newline is + # undercounted by 1. Go source files always end with a newline (enforced by + # gofmt), so in practice the count is exact. + line_count=$(wc -l < "$file") + + if [ "$line_count" -gt "$HARD_LIMIT" ]; then + echo -e "${RED}OVER LIMIT${NC}: $file" + echo -e " Lines: ${RED}$line_count${NC} / ${HARD_LIMIT} (exceeded by $((line_count - HARD_LIMIT)))" + echo "" + over_limit=$((over_limit + 1)) + fi +done < <(find pkg -name "*_validation.go" ! -name "*_test.go" -type f | sort) + +echo "------------------------------------------------------------" + +if [ "$over_limit" -eq 0 ]; then + echo -e "${GREEN}All validator files are within the ${HARD_LIMIT}-line limit${NC}" + exit 0 +fi + +echo -e "${YELLOW}$over_limit validator file(s) exceed the ${HARD_LIMIT}-line hard limit${NC}" +echo "" +echo "See AGENTS.md 'Validation Complexity Guidelines' for guidance:" +echo " - Target size: 100-200 lines per validator" +echo " - Hard limit: ${HARD_LIMIT} lines (refactor if exceeded)" +echo "" +echo "When to split a validator:" +echo " - File exceeds ${HARD_LIMIT} lines" +echo " - File contains 2+ unrelated validation domains" +echo " - Complex cross-dependencies require separate testing" + +if [ "$WARN_ONLY" = "1" ]; then + echo "" + echo "Note: Running in warn-only mode (WARN_ONLY=1). Fix these files to pass a future blocking check." + exit 0 +fi + +exit 1