git-pre-commit-hook.shā¢6.71 kB
#!/bin/bash
# EuConquisto Composer MCP Server PoC - Pre-commit Hook
# Version: 0.1.0 | Foundation Release | Last Updated: 2025-06-08
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
print_status() {
echo -e "${BLUE}[HOOK]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Function to check TypeScript files have version headers
check_ts_headers() {
print_status "Checking TypeScript version headers..."
MISSING_HEADERS=()
for file in $(git diff --cached --name-only --diff-filter=AM | grep '\.ts$'); do
if [ -f "$file" ] && ! grep -q "@version" "$file"; then
MISSING_HEADERS+=("$file")
fi
done
if [ ${#MISSING_HEADERS[@]} -gt 0 ]; then
print_error "The following TypeScript files are missing version headers:"
for file in "${MISSING_HEADERS[@]}"; do
echo " - $file"
done
echo ""
echo "Please add version headers using the template:"
echo "/**"
echo " * EuConquisto Composer MCP Server - [Component Name]"
echo " * "
echo " * @version 0.1.0"
echo " * @created $(date +%Y-%m-%d)"
echo " * @updated $(date +%Y-%m-%d)"
echo " * @author [Author Name]"
echo " * ..."
echo " */"
return 1
else
print_success "All TypeScript files have version headers"
fi
}
# Function to check documentation files have version info
check_doc_versions() {
print_status "Checking documentation version info..."
MISSING_DOC_VERSIONS=()
for file in $(git diff --cached --name-only --diff-filter=AM | grep '\.md$'); do
if [ -f "$file" ] && ! grep -q "Document Version\|Version.*:" "$file"; then
MISSING_DOC_VERSIONS+=("$file")
fi
done
if [ ${#MISSING_DOC_VERSIONS[@]} -gt 0 ]; then
print_warning "The following documentation files may need version information:"
for file in "${MISSING_DOC_VERSIONS[@]}"; do
echo " - $file"
done
echo ""
echo "Consider adding version information like:"
echo "**Document Version**: 1.0"
echo "**Project Version**: 0.1.0"
echo "**Last Updated**: $(date +%Y-%m-%d)"
else
print_success "Documentation version info looks good"
fi
}
# Function to check if CHANGELOG.md needs updating
check_changelog() {
print_status "Checking if CHANGELOG.md needs updating..."
# Check if there are significant changes that should be in changelog
CHANGED_FILES=$(git diff --cached --name-only | wc -l)
CHANGELOG_MODIFIED=$(git diff --cached --name-only | grep -c "CHANGELOG.md" || echo "0")
if [ "$CHANGED_FILES" -gt 3 ] && [ "$CHANGELOG_MODIFIED" -eq 0 ]; then
print_warning "You're committing many changes but CHANGELOG.md wasn't updated"
echo "Consider updating CHANGELOG.md if this represents significant changes"
fi
}
# Function to validate version consistency
check_version_consistency() {
print_status "Checking version consistency..."
# Only check if version-critical files are being modified
VERSION_FILES=$(git diff --cached --name-only | grep -E "(package.json|VERSION|README.md|project.json)" | wc -l)
if [ "$VERSION_FILES" -gt 0 ]; then
# Get current versions (from working directory, not staged)
if [ -f "package.json" ]; then
PKG_VERSION=$(grep '"version"' package.json | cut -d'"' -f4)
fi
if [ -f "VERSION" ]; then
VER_VERSION=$(grep "Version.*:" VERSION | head -1 | sed 's/.*: *//' | sed 's/ .*//')
fi
if [ -f "README.md" ]; then
README_VERSION=$(grep "Version.*:" README.md | head -1 | sed 's/.*: *//' | sed 's/ .*//')
fi
# Basic consistency check
if [ -n "$PKG_VERSION" ] && [ -n "$VER_VERSION" ] && [ "$PKG_VERSION" != "$VER_VERSION" ]; then
print_warning "Version mismatch detected between package.json and VERSION file"
echo " package.json: $PKG_VERSION"
echo " VERSION file: $VER_VERSION"
fi
fi
}
# Function to run linting on staged files
run_lint_on_staged() {
print_status "Running linting on staged TypeScript files..."
STAGED_TS_FILES=$(git diff --cached --name-only --diff-filter=AM | grep '\.ts$' | tr '\n' ' ')
if [ -n "$STAGED_TS_FILES" ]; then
if command -v eslint >/dev/null 2>&1; then
if eslint $STAGED_TS_FILES; then
print_success "Linting passed for staged files"
else
print_error "Linting failed for staged files"
echo "Fix linting errors before committing"
return 1
fi
else
print_warning "ESLint not found, skipping lint check"
fi
fi
}
# Function to check for TODO/FIXME comments in staged files
check_todos() {
print_status "Checking for TODO/FIXME comments..."
TODO_COUNT=0
for file in $(git diff --cached --name-only --diff-filter=AM | grep -E '\.(ts|js|md)$'); do
if [ -f "$file" ]; then
TODOS=$(git diff --cached "$file" | grep -E "^\+" | grep -i "todo\|fixme" | wc -l)
TODO_COUNT=$((TODO_COUNT + TODOS))
fi
done
if [ "$TODO_COUNT" -gt 0 ]; then
print_warning "Found $TODO_COUNT new TODO/FIXME comments in staged changes"
echo "Make sure these are intentional and tracked"
fi
}
# Main execution
main() {
echo "=============================================="
echo "š EuConquisto Composer MCP Server - Pre-commit Validation"
echo "=============================================="
echo ""
# Initialize error tracking
ERROR_COUNT=0
# Run all checks
if ! check_ts_headers; then
ERROR_COUNT=$((ERROR_COUNT + 1))
fi
check_doc_versions # Warning only
check_changelog # Warning only
check_version_consistency # Warning only
if ! run_lint_on_staged; then
ERROR_COUNT=$((ERROR_COUNT + 1))
fi
check_todos # Warning only
echo ""
# Final decision
if [ "$ERROR_COUNT" -gt 0 ]; then
print_error "Pre-commit validation failed with $ERROR_COUNT error(s)"
echo "Please fix the errors above before committing"
exit 1
else
print_success "Pre-commit validation passed! ā
"
exit 0
fi
}
# Execute main function
main "$@"