fetch_ml/scripts/ci-checks.sh
Jeremie Fraeys 3187ff26ea
refactor: complete maintainability phases 1-9 and fix all tests
Test fixes (all 41 test packages now pass):
- Fix ComputeTaskProvenance - add dataset_specs JSON output
- Fix EnforceTaskProvenance - populate all metadata fields in best-effort mode
- Fix PrewarmNextOnce - preserve prewarm state when queue empty
- Fix RunManifest directory creation in SetupJobDirectories
- Add ManifestWriter to test worker (simpleManifestWriter)
- Fix worker ID mismatch (use cfg.WorkerID)
- Fix WebSocket binary protocol responses
- Implement all WebSocket handlers: QueueJob, QueueJobWithSnapshot, StatusRequest,
  CancelJob, Prune, ValidateRequest (with run manifest validation), LogMetric,
  GetExperiment, DatasetList/Register/Info/Search

Maintainability phases completed:
- Phases 1-6: Domain types, error system, config boundaries, worker/API/queue splits
- Phase 7: TUI cleanup - reorganize model package (jobs.go, messages.go, styles.go, keys.go)
- Phase 8: MLServer unification - consolidate worker + TUI into internal/network/mlserver.go
- Phase 9: CI enforcement - add scripts/ci-checks.sh with 5 checks:
  * No internal/ -> cmd/ imports
  * domain/ has zero internal imports
  * File size limit (500 lines, rigid)
  * No circular imports
  * Package naming conventions

Documentation:
- Add docs/src/file-naming-conventions.md
- Add make ci-checks target

Lines changed: +756/-36 (WebSocket fixes), +518/-320 (TUI), +263/-20 (Phase 8-9)
2026-02-17 20:32:14 -05:00

109 lines
3.5 KiB
Bash
Executable file

#!/bin/bash
# ci-checks.sh - CI enforcement for maintainability rules
# Usage: ./scripts/ci-checks.sh
set -e
echo "=== FetchML Maintainability CI Checks ==="
echo ""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
FAILED=0
# Check 1: No internal/ -> cmd/ imports
echo "1. Checking for illegal internal/ -> cmd/ imports..."
if go list -f '{{.ImportPath}}: {{.Imports}}' ./internal/... 2>/dev/null | grep -q 'github.com/jfraeys/fetch_ml/cmd'; then
echo -e "${RED}FAIL: Found internal/ package importing from cmd/${NC}"
go list -f '{{.ImportPath}}: {{.Imports}}' ./internal/... | grep 'github.com/jfraeys/fetch_ml/cmd'
FAILED=1
else
echo -e "${GREEN}PASS: No internal/ -> cmd/ imports found${NC}"
fi
echo ""
# Check 2: domain package has zero internal imports (only stdlib)
echo "2. Checking domain package has no internal imports..."
DOMAIN_IMPORTS=$(go list -f '{{join .Imports "\n"}}' ./internal/domain/... 2>/dev/null | grep 'github.com/jfraeys/fetch_ml' || true)
if [ -n "$DOMAIN_IMPORTS" ]; then
echo -e "${RED}FAIL: domain/ package imports internal packages:${NC}"
echo "$DOMAIN_IMPORTS"
FAILED=1
else
echo -e "${GREEN}PASS: domain/ package has no internal imports${NC}"
fi
echo ""
# Check 3: Check file size limits (no file >500 lines)
echo "3. Checking file size limits (max 500 lines)..."
OVERSIZED=$(find ./internal ./cmd -name '*.go' -type f -exec wc -l {} + 2>/dev/null | awk '$1 > 500 {print $2}' | head -10)
if [ -n "$OVERSIZED" ]; then
echo -e "${RED}FAIL: Files exceeding 500 lines:${NC}"
find ./internal ./cmd -name '*.go' -type f -exec wc -l {} + 2>/dev/null | awk '$1 > 500 {print " " $1 " lines: " $2}'
FAILED=1
else
echo -e "${GREEN}PASS: All files under 500 lines${NC}"
fi
echo ""
# Check 4: Verify no circular imports
echo "4. Checking for circular imports..."
CIRCULAR=$(go list -deps ./internal/... 2>&1 | grep -i 'circular' || true)
if [ -n "$CIRCULAR" ]; then
echo -e "${RED}FAIL: Circular imports detected:${NC}"
echo "$CIRCULAR"
FAILED=1
else
echo -e "${GREEN}PASS: No circular imports detected${NC}"
fi
echo ""
# Check 5: Verify package naming conventions
echo "5. Checking package naming conventions..."
NAMING_ISSUES=$(find ./internal ./cmd -name '*.go' -type f | while read f; do
# Skip vendor and generated files
if echo "$f" | grep -qE '(vendor|_test\.go|\.pb\.go|generated)'; then
continue
fi
# Check file name matches content (basic check)
pkg=$(grep '^package ' "$f" 2>/dev/null | head -1 | awk '{print $2}')
if [ -z "$pkg" ]; then
continue
fi
# Skip main packages
if [ "$pkg" = "main" ]; then
continue
fi
# Check that file is in correct directory for its package
dir=$(dirname "$f")
expected_pkg=$(basename "$dir")
if [ "$pkg" != "$expected_pkg" ] && [ "$pkg" != "${expected_pkg}_test" ]; then
# Allow common exceptions
if echo "$f" | grep -qE '(factory|config|helper|util)'; then
continue
fi
echo " $f: package '$pkg' doesn't match directory '$expected_pkg'"
fi
done)
if [ -n "$NAMING_ISSUES" ]; then
echo -e "${YELLOW}WARNING: Potential naming convention issues:${NC}"
echo "$NAMING_ISSUES"
else
echo -e "${GREEN}PASS: Package naming conventions look good${NC}"
fi
echo ""
# Summary
echo "=== Summary ==="
if [ $FAILED -eq 0 ]; then
echo -e "${GREEN}All critical checks passed!${NC}"
exit 0
else
echo -e "${RED}Some checks failed. Please fix the issues above.${NC}"
exit 1
fi