Some syntax errors fixed. Syntax checking added. Release checklist created.
This commit is contained in:
231
tools/pre-commit-composite
Executable file
231
tools/pre-commit-composite
Executable file
@ -0,0 +1,231 @@
|
||||
#!/bin/bash
|
||||
# Fenrir Composite Pre-commit Hook
|
||||
#
|
||||
# This hook combines version management and code quality validation.
|
||||
# It first runs the version management logic, then runs validation.
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}Fenrir Pre-commit Validation${NC}"
|
||||
echo "=================================="
|
||||
|
||||
# Get the repository root
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# ============================================================================
|
||||
# PART 1: VERSION MANAGEMENT (existing logic)
|
||||
# ============================================================================
|
||||
|
||||
echo -e "\n${YELLOW}1. Version Management...${NC}"
|
||||
|
||||
# Check if SKIP_VERSION_UPDATE is set
|
||||
if [[ "${SKIP_VERSION_UPDATE}" = "1" ]]; then
|
||||
echo -e "${YELLOW}Notice: Skipping version update due to SKIP_VERSION_UPDATE=1${NC}"
|
||||
else
|
||||
# Verify .git/versionpath exists
|
||||
if [[ ! -f ".git/versionpath" ]]; then
|
||||
echo -e "${RED}Error: .git/versionpath not found. Please create it with contents:${NC}"
|
||||
echo -e "${YELLOW}versionFile=\"path/to/your/version/file\"${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Source the version path file
|
||||
source ".git/versionpath"
|
||||
|
||||
# Validate that versionFile variable was set
|
||||
if [[ -z "$versionFile" ]]; then
|
||||
echo -e "${RED}Error: versionFile variable not set in .git/versionpath${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get current date components
|
||||
year=$(date +%Y)
|
||||
month=$(date +%m)
|
||||
day=$(date +%d)
|
||||
|
||||
# Create new version string
|
||||
newVersion="$year.$month.$day"
|
||||
|
||||
# Get current branch name
|
||||
branchName=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Check if we're in the middle of a merge
|
||||
if [[ -f ".git/MERGE_HEAD" ]]; then
|
||||
echo -e "${YELLOW}Warning: In the middle of a merge. Skipping version update.${NC}"
|
||||
else
|
||||
# Check if file exists relative to git root
|
||||
if [[ ! -f "$versionFile" ]]; then
|
||||
echo -e "${RED}Error: Version file not found at $versionFile${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Store original version file content
|
||||
originalContent=$(cat "$versionFile")
|
||||
|
||||
# Check if version actually needs updating
|
||||
if ! grep -q "version = \"$newVersion\"" "$versionFile"; then
|
||||
# Update the version in the file
|
||||
sed -i "s/version = [\"']\{0,1\}[0-9.]\+[\"']\{0,1\}/version = \"$newVersion\"/" "$versionFile"
|
||||
fi
|
||||
|
||||
# Check if codeName exists and isn't "stable"
|
||||
if grep -q "codeName.*=.*\"stable\"" "$versionFile"; then
|
||||
# Don't modify stable codeName
|
||||
:
|
||||
elif grep -q "codeName.*=.*\"$branchName\"" "$versionFile"; then
|
||||
# CodeName already matches branch name, no need to update
|
||||
:
|
||||
elif grep -q "codeName" "$versionFile"; then
|
||||
# Update existing codeName
|
||||
sed -i "s/codeName = [\"']\{0,1\}[^\"']*[\"']\{0,1\}/codeName = \"$branchName\"/" "$versionFile"
|
||||
else
|
||||
# Add codeName after the version line
|
||||
sed -i "/version = / a\codeName = \"$branchName\"" "$versionFile"
|
||||
fi
|
||||
|
||||
# Check if the file was actually modified
|
||||
if [[ "$(cat "$versionFile")" != "$originalContent" ]]; then
|
||||
echo -e "${GREEN}✓ Version file updated to $newVersion${NC}"
|
||||
if ! git diff --cached --quiet "$versionFile"; then
|
||||
echo -e "${YELLOW}Notice: Version file was already staged, updates made to staged version${NC}"
|
||||
else
|
||||
git add "$versionFile"
|
||||
echo -e "${YELLOW}Notice: Version file has been staged${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}✓ No version updates needed${NC}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# PART 2: CODE QUALITY VALIDATION (our new logic)
|
||||
# ============================================================================
|
||||
|
||||
echo -e "\n${YELLOW}2. Code Quality Validation...${NC}"
|
||||
|
||||
# Track validation results
|
||||
VALIDATION_FAILED=0
|
||||
|
||||
# 2a. Python Syntax Validation
|
||||
echo -e "\n${YELLOW} 2a. Validating Python syntax...${NC}"
|
||||
if python3 tools/validate_syntax.py --check-only >/dev/null 2>&1; then
|
||||
echo -e "${GREEN} ✓ Syntax validation passed${NC}"
|
||||
else
|
||||
echo -e "${RED} ✗ Syntax validation failed${NC}"
|
||||
echo " Run: python3 tools/validate_syntax.py --fix"
|
||||
VALIDATION_FAILED=1
|
||||
fi
|
||||
|
||||
# 2b. Check for common issues in modified files
|
||||
echo -e "\n${YELLOW} 2b. Checking modified files for common issues...${NC}"
|
||||
|
||||
# Get list of staged files (all types)
|
||||
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM || true)
|
||||
STAGED_PYTHON_FILES=$(echo "$STAGED_FILES" | grep '\.py$' || true)
|
||||
|
||||
if [ -n "$STAGED_FILES" ]; then
|
||||
ISSUES_FOUND=0
|
||||
|
||||
# Check for cache files being committed
|
||||
CACHE_FILES=$(echo "$STAGED_FILES" | grep -E '(__pycache__|\.pyc$)' || true)
|
||||
if [ -n "$CACHE_FILES" ]; then
|
||||
echo -e "${RED} ✗ Python cache files staged for commit:${NC}"
|
||||
echo "$CACHE_FILES" | while read cache_file; do
|
||||
echo -e "${RED} $cache_file${NC}"
|
||||
done
|
||||
echo -e "${RED} ✗ Run: python3 tools/cleanup_cache.py --remove${NC}"
|
||||
ISSUES_FOUND=1
|
||||
fi
|
||||
|
||||
# Check Python files for specific issues
|
||||
if [ -n "$STAGED_PYTHON_FILES" ]; then
|
||||
for file in $STAGED_PYTHON_FILES; do
|
||||
if [ -f "$file" ]; then
|
||||
# Check for unterminated strings (the main issue from the email)
|
||||
if grep -n 'f".*{$' "$file" >/dev/null 2>&1; then
|
||||
echo -e "${RED} ✗ $file: Potential unterminated f-string${NC}"
|
||||
ISSUES_FOUND=1
|
||||
fi
|
||||
|
||||
# Check for missing imports that are commonly used
|
||||
if grep -q 'debug\.DebugLevel\.' "$file" && ! grep -q 'from.*debug' "$file" && ! grep -q 'import.*debug' "$file"; then
|
||||
echo -e "${YELLOW} ⚠ $file: Uses debug.DebugLevel but no debug import found${NC}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ $ISSUES_FOUND -eq 0 ]; then
|
||||
echo -e "${GREEN} ✓ No common issues found in staged files${NC}"
|
||||
else
|
||||
echo -e "${RED} ✗ Common issues found in staged files${NC}"
|
||||
VALIDATION_FAILED=1
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN} ✓ No files staged for commit${NC}"
|
||||
fi
|
||||
|
||||
# 2c. Quick import test for core modules (informational only)
|
||||
echo -e "\n${YELLOW} 2c. Testing core module imports...${NC}"
|
||||
IMPORT_WARNINGS=0
|
||||
|
||||
# Test core imports that are critical (but don't fail on import issues - might be dependency related)
|
||||
CORE_MODULES=(
|
||||
"src.fenrirscreenreader.core.fenrirManager"
|
||||
"src.fenrirscreenreader.core.commandManager"
|
||||
"src.fenrirscreenreader.core.eventManager"
|
||||
)
|
||||
|
||||
cd src
|
||||
for module in "${CORE_MODULES[@]}"; do
|
||||
if python3 -c "import $module" 2>/dev/null; then
|
||||
echo -e "${GREEN} ✓ $module${NC}"
|
||||
else
|
||||
echo -e "${YELLOW} ⚠ $module (import failed - might be dependency related)${NC}"
|
||||
IMPORT_WARNINGS=1
|
||||
fi
|
||||
done
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
if [ $IMPORT_WARNINGS -eq 1 ]; then
|
||||
echo -e "${YELLOW} ⚠ Some core module imports failed (non-blocking)${NC}"
|
||||
echo -e "${YELLOW} This may be due to missing runtime dependencies${NC}"
|
||||
else
|
||||
echo -e "${GREEN} ✓ Core module imports successful${NC}"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# FINAL SUMMARY
|
||||
# ============================================================================
|
||||
|
||||
echo -e "\n============================================================"
|
||||
if [ $VALIDATION_FAILED -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ All pre-commit validations passed${NC}"
|
||||
echo -e "${GREEN}✓ Version management completed${NC}"
|
||||
echo -e "${GREEN}✓ Code quality checks passed${NC}"
|
||||
echo -e "${GREEN}Commit allowed to proceed${NC}"
|
||||
|
||||
# Show skip option
|
||||
echo -e "\n${BLUE}Tip: You can skip version updates with SKIP_VERSION_UPDATE=1${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}✗ Pre-commit validation failed${NC}"
|
||||
echo -e "${RED}Commit blocked - please fix issues above${NC}"
|
||||
echo ""
|
||||
echo "Quick fixes:"
|
||||
echo " • Python syntax: python3 tools/validate_syntax.py --fix"
|
||||
echo " • Review flagged files manually"
|
||||
echo " • Re-run commit after fixes"
|
||||
echo ""
|
||||
echo -e "${BLUE}Note: Version management completed successfully${NC}"
|
||||
exit 1
|
||||
fi
|
Reference in New Issue
Block a user