refactor(scripts): reorganize scripts/ into seed/ and validate/ subfolders
Move 9 init/seed scripts into scripts/seed/ and 7 validation scripts (+ validators/ subfolder) into scripts/validate/ to reduce clutter in the root scripts/ directory. Update all references across Makefile, CI/CD configs, pre-commit hooks, docs (~40 files), and Python imports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
246
scripts/validate/validate_all.py
Executable file
246
scripts/validate/validate_all.py
Executable file
@@ -0,0 +1,246 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Unified Code Validator
|
||||
======================
|
||||
Runs all validation scripts (architecture, security, performance, audit) in sequence.
|
||||
|
||||
This provides a single entry point for comprehensive code validation,
|
||||
useful for CI/CD pipelines and pre-commit hooks.
|
||||
|
||||
Usage:
|
||||
python scripts/validate/validate_all.py # Run all validators
|
||||
python scripts/validate/validate_all.py --security # Run only security validator
|
||||
python scripts/validate/validate_all.py --performance # Run only performance validator
|
||||
python scripts/validate/validate_all.py --architecture # Run only architecture validator
|
||||
python scripts/validate/validate_all.py --audit # Run only audit validator
|
||||
python scripts/validate/validate_all.py -v # Verbose output
|
||||
python scripts/validate/validate_all.py --fail-fast # Stop on first failure
|
||||
python scripts/validate/validate_all.py --json # JSON output
|
||||
|
||||
Options:
|
||||
--architecture Run architecture validator
|
||||
--security Run security validator
|
||||
--performance Run performance validator
|
||||
--audit Run audit validator
|
||||
--fail-fast Stop on first validator failure
|
||||
-v, --verbose Show detailed output
|
||||
--errors-only Only show errors
|
||||
--json Output results as JSON
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add parent directory to path for imports
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
|
||||
def run_architecture_validator(verbose: bool = False) -> tuple[int, dict]:
|
||||
"""Run the architecture validator"""
|
||||
try:
|
||||
# Import dynamically to avoid circular imports
|
||||
from validate_architecture import ArchitectureValidator
|
||||
|
||||
config_path = Path.cwd() / ".architecture-rules.yaml"
|
||||
validator = ArchitectureValidator(config_path=config_path, verbose=verbose)
|
||||
result = validator.validate_all()
|
||||
|
||||
return (
|
||||
1 if result.has_errors() else 0,
|
||||
{
|
||||
"name": "Architecture",
|
||||
"files_checked": result.files_checked,
|
||||
"errors": sum(1 for v in result.violations if v.severity.value == "error"),
|
||||
"warnings": sum(1 for v in result.violations if v.severity.value == "warning"),
|
||||
"info": sum(1 for v in result.violations if v.severity.value == "info"),
|
||||
}
|
||||
)
|
||||
except ImportError as e:
|
||||
print(f"⚠️ Architecture validator not available: {e}")
|
||||
return 0, {"name": "Architecture", "skipped": True}
|
||||
except Exception as e:
|
||||
print(f"❌ Architecture validator failed: {e}")
|
||||
return 1, {"name": "Architecture", "error": str(e)}
|
||||
|
||||
|
||||
def run_security_validator(verbose: bool = False) -> tuple[int, dict]:
|
||||
"""Run the security validator"""
|
||||
try:
|
||||
from validate_security import SecurityValidator
|
||||
|
||||
validator = SecurityValidator(verbose=verbose)
|
||||
result = validator.validate_all()
|
||||
|
||||
return (
|
||||
1 if result.has_errors() else 0,
|
||||
{
|
||||
"name": "Security",
|
||||
"files_checked": result.files_checked,
|
||||
"errors": result.error_count(),
|
||||
"warnings": result.warning_count(),
|
||||
"info": result.info_count(),
|
||||
}
|
||||
)
|
||||
except ImportError as e:
|
||||
print(f"⚠️ Security validator not available: {e}")
|
||||
return 0, {"name": "Security", "skipped": True}
|
||||
except Exception as e:
|
||||
print(f"❌ Security validator failed: {e}")
|
||||
return 1, {"name": "Security", "error": str(e)}
|
||||
|
||||
|
||||
def run_performance_validator(verbose: bool = False) -> tuple[int, dict]:
|
||||
"""Run the performance validator"""
|
||||
try:
|
||||
from validate_performance import PerformanceValidator
|
||||
|
||||
validator = PerformanceValidator(verbose=verbose)
|
||||
result = validator.validate_all()
|
||||
|
||||
return (
|
||||
1 if result.has_errors() else 0,
|
||||
{
|
||||
"name": "Performance",
|
||||
"files_checked": result.files_checked,
|
||||
"errors": result.error_count(),
|
||||
"warnings": result.warning_count(),
|
||||
"info": result.info_count(),
|
||||
}
|
||||
)
|
||||
except ImportError as e:
|
||||
print(f"⚠️ Performance validator not available: {e}")
|
||||
return 0, {"name": "Performance", "skipped": True}
|
||||
except Exception as e:
|
||||
print(f"❌ Performance validator failed: {e}")
|
||||
return 1, {"name": "Performance", "error": str(e)}
|
||||
|
||||
|
||||
def run_audit_validator(verbose: bool = False) -> tuple[int, dict]:
|
||||
"""Run the audit validator"""
|
||||
try:
|
||||
from validate_audit import AuditValidator
|
||||
|
||||
validator = AuditValidator()
|
||||
has_errors = not validator.validate()
|
||||
|
||||
return (
|
||||
1 if has_errors else 0,
|
||||
{
|
||||
"name": "Audit",
|
||||
"files_checked": len(validator.files_checked) if hasattr(validator, 'files_checked') else 0,
|
||||
"errors": len(validator.errors),
|
||||
"warnings": len(validator.warnings),
|
||||
"info": len(validator.info) if hasattr(validator, 'info') else 0,
|
||||
}
|
||||
)
|
||||
except ImportError as e:
|
||||
print(f"⚠️ Audit validator not available: {e}")
|
||||
return 0, {"name": "Audit", "skipped": True}
|
||||
except Exception as e:
|
||||
print(f"❌ Audit validator failed: {e}")
|
||||
return 1, {"name": "Audit", "error": str(e)}
|
||||
|
||||
|
||||
def print_summary(results: list[dict], json_output: bool = False):
|
||||
"""Print validation summary"""
|
||||
if json_output:
|
||||
print(json.dumps({"validators": results}, indent=2))
|
||||
return
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print("📊 UNIFIED VALIDATION SUMMARY")
|
||||
print("=" * 80)
|
||||
|
||||
total_errors = 0
|
||||
total_warnings = 0
|
||||
total_info = 0
|
||||
|
||||
for result in results:
|
||||
if result.get("skipped"):
|
||||
print(f"\n⏭️ {result['name']}: Skipped")
|
||||
elif result.get("error"):
|
||||
print(f"\n❌ {result['name']}: Error - {result['error']}")
|
||||
else:
|
||||
errors = result.get("errors", 0)
|
||||
warnings = result.get("warnings", 0)
|
||||
info = result.get("info", 0)
|
||||
total_errors += errors
|
||||
total_warnings += warnings
|
||||
total_info += info
|
||||
|
||||
status = "✅" if errors == 0 else "❌"
|
||||
print(f"\n{status} {result['name']}:")
|
||||
print(f" Files: {result.get('files_checked', 0)}")
|
||||
print(f" Errors: {errors}, Warnings: {warnings}, Info: {info}")
|
||||
|
||||
print("\n" + "-" * 80)
|
||||
print(f"TOTAL: {total_errors} errors, {total_warnings} warnings, {total_info} info")
|
||||
print("=" * 80)
|
||||
|
||||
if total_errors > 0:
|
||||
print("❌ VALIDATION FAILED")
|
||||
elif total_warnings > 0:
|
||||
print(f"⚠️ VALIDATION PASSED WITH {total_warnings} WARNING(S)")
|
||||
else:
|
||||
print("✅ VALIDATION PASSED")
|
||||
print("=" * 80)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Unified code validator - runs architecture, security, performance, and audit checks",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument("--architecture", action="store_true", help="Run architecture validator")
|
||||
parser.add_argument("--security", action="store_true", help="Run security validator")
|
||||
parser.add_argument("--performance", action="store_true", help="Run performance validator")
|
||||
parser.add_argument("--audit", action="store_true", help="Run audit validator")
|
||||
parser.add_argument("--fail-fast", action="store_true", help="Stop on first failure")
|
||||
parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
|
||||
parser.add_argument("--errors-only", action="store_true", help="Only show errors")
|
||||
parser.add_argument("--json", action="store_true", help="JSON output")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# If no specific validators selected, run all
|
||||
run_all = not (args.architecture or args.security or args.performance or args.audit)
|
||||
|
||||
print("\n🔍 UNIFIED CODE VALIDATION")
|
||||
print("=" * 80)
|
||||
|
||||
validators = []
|
||||
if run_all or args.architecture:
|
||||
validators.append(("Architecture", run_architecture_validator))
|
||||
if run_all or args.security:
|
||||
validators.append(("Security", run_security_validator))
|
||||
if run_all or args.performance:
|
||||
validators.append(("Performance", run_performance_validator))
|
||||
if run_all or args.audit:
|
||||
validators.append(("Audit", run_audit_validator))
|
||||
|
||||
results = []
|
||||
exit_code = 0
|
||||
|
||||
for name, validator_func in validators:
|
||||
print(f"\n{'=' * 40}")
|
||||
print(f"🔍 Running {name} Validator...")
|
||||
print("=" * 40)
|
||||
|
||||
code, result = validator_func(verbose=args.verbose)
|
||||
|
||||
results.append(result)
|
||||
|
||||
if code != 0:
|
||||
exit_code = 1
|
||||
if args.fail_fast:
|
||||
print(f"\n❌ {name} validator failed. Stopping (--fail-fast)")
|
||||
break
|
||||
|
||||
print_summary(results, json_output=args.json)
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user