Implémenter des hooks Git
Ce guide vous montre comment créer, déployer et gérer des hooks Git pour les équipes de développement. Découvrez les techniques multiplateformes modernes, les implémentations axées sur la sécurité et les stratégies pour la mise à l’échelle des hooks entre les grandes équipes de développement.
Configuration moderne des hooks Git
L’implémentation de hooks Git nécessite une réflexion minutieuse sur la compatibilité multiplateforme, la facilité de maintenance et les stratégies de déploiement d’équipe. Les approches modernes se concentrent sur la gestion des hooks avec contrôle de version et sur la distribution automatique, plutôt que sur la configuration manuelle.
Développement de hook multiplateformes
Les environnements de développement modernes ont besoin de crochets Git qui fonctionnent de la même façon sur les environnements de développement Windows, macOS et Linux.
Implémentation universelle
#!/usr/bin/env bash
# Cross-platform compatible shebang that automatically finds bash interpreter
# Works consistently across Windows Git Bash, macOS, and Linux environments
Cette approche supprime les problèmes de chemin spécifiques à la plateforme qui provoquent des problèmes liés aux implémentations traditionnelles et garantit un comportement cohérent dans différents environnements de développement.
Stratégie de détection d’environnement
#!/usr/bin/env bash
# Smart environment detection for platform-specific optimizations
detect_environment() {
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
PLATFORM="windows"
PYTHON_CMD="python"
elif [[ "$OSTYPE" == "darwin"* ]]; then
PLATFORM="macos"
PYTHON_CMD="python3"
else
PLATFORM="linux"
PYTHON_CMD="python3"
fi
}
Implémentation du hook de pré-commit d’entreprise
Détection des informations d’identification axées sur la sécurité
Implémentez une détection d’informations d’identification sophistiquée qui va au-delà de la correspondance simple des mots clés :
#!/usr/bin/env bash
# Advanced credential detection with pattern recognition
check_credentials() {
local staged_files=$(git diff --cached --name-only)
local violations=""
# Define comprehensive credential patterns
local patterns=(
"password\s*[=:]\s*['\"][^'\"]{8,}"
"api[_-]?key\s*[=:]\s*['\"][^'\"]{20,}"
"secret\s*[=:]\s*['\"][^'\"]{16,}"
"token\s*[=:]\s*['\"][^'\"]{24,}"
"-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----"
"mysql://.*:.*@"
"postgresql://.*:.*@"
)
for file in $staged_files; do
if [ -f "$file" ]; then
for pattern in "${patterns[@]}"; do
if git show ":$file" | grep -qiE "$pattern"; then
violations+="Potential credential detected in $file\n"
fi
done
fi
done
if [ ! -z "$violations" ]; then
echo -e "Security Alert: Credential Detection\n"
echo -e "$violations"
echo -e "Please remove sensitive information before committing\n"
return 1
fi
return 0
}
# Execute security validation
check_credentials || exit 1
Validation complète de la qualité du code
Implémentez la garantie de la qualité du code multilingue qui s’adapte à votre pile technologique.
#!/usr/bin/env bash
# Enterprise code quality validation framework
validate_code_quality() {
local staged_files=$(git diff --cached --name-only --diff-filter=ACM)
local quality_violations=0
echo "Performing code quality validation..."
for file in $staged_files; do
case "$file" in
*.js|*.jsx|*.ts|*.tsx)
if command -v npx >/dev/null 2>&1; then
echo "Linting JavaScript/TypeScript: $file"
npx eslint "$file" || ((quality_violations++))
if [[ "$file" =~ \.(ts|tsx)$ ]]; then
echo "Type checking: $file"
npx tsc --noEmit --skipLibCheck "$file" || ((quality_violations++))
fi
fi
;;
*.py)
if command -v python3 >/dev/null 2>&1; then
echo "Linting Python: $file"
python3 -m flake8 "$file" || ((quality_violations++))
if command -v mypy >/dev/null 2>&1; then
echo "Type checking Python: $file"
python3 -m mypy "$file" || ((quality_violations++))
fi
fi
;;
*.cs)
if command -v dotnet >/dev/null 2>&1; then
echo "Formatting C#: $file"
dotnet format --verify-no-changes --include "$file" || ((quality_violations++))
fi
;;
*.go)
if command -v go >/dev/null 2>&1; then
echo "Formatting Go: $file"
if ! gofmt -l "$file" | grep -q .; then
gofmt -w "$file"
git add "$file"
fi
echo "Linting Go: $file"
golint "$file" || ((quality_violations++))
fi
;;
esac
done
if [ $quality_violations -gt 0 ]; then
echo "Code quality validation failed with $quality_violations violations"
echo "Please fix the issues above before committing"
return 1
fi
echo "Code quality validation passed"
return 0
}
# Execute quality validation
validate_code_quality || exit 1
Stratégie d’exécution de test intelligente
Implémentez l’exécution de tests intelligents qui exécute uniquement des tests pertinents en fonction du code modifié :
#!/usr/bin/env bash
# Intelligent test execution based on change impact
execute_relevant_tests() {
local changed_files=$(git diff --cached --name-only)
local test_failures=0
echo "Analyzing test requirements for changed files..."
# Check if source code changes require testing
if echo "$changed_files" | grep -qE "\.(js|jsx|ts|tsx|py|cs|go)$"; then
echo "Source code changes detected, running relevant tests..."
# JavaScript/TypeScript projects
if [ -f "package.json" ] && command -v npm >/dev/null 2>&1; then
if echo "$changed_files" | grep -qE "\.(js|jsx|ts|tsx)$"; then
echo "Running JavaScript/TypeScript tests..."
npm test -- --findRelatedTests $changed_files --passWithNoTests || ((test_failures++))
fi
fi
# Python projects
if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
if echo "$changed_files" | grep -qE "\.py$"; then
echo "Running Python tests..."
if command -v pytest >/dev/null 2>&1; then
pytest --tb=short || ((test_failures++))
elif command -v python3 >/dev/null 2>&1; then
python3 -m unittest discover || ((test_failures++))
fi
fi
fi
# .NET projects
if find . -name "*.csproj" -o -name "*.sln" | grep -q .; then
if echo "$changed_files" | grep -qE "\.cs$"; then
echo "Running .NET tests..."
dotnet test --no-build --verbosity minimal || ((test_failures++))
fi
fi
# Go projects
if [ -f "go.mod" ]; then
if echo "$changed_files" | grep -qE "\.go$"; then
echo "Running Go tests..."
go test ./... || ((test_failures++))
fi
fi
fi
if [ $test_failures -gt 0 ]; then
echo "Test execution failed"
echo "Please fix failing tests before committing"
return 1
fi
echo "All relevant tests passed"
return 0
}
# Execute intelligent testing
execute_relevant_tests || exit 1
Automatisation avancée des messages de commit
Implémentation du hook Prepare-commit-msg
Automatisez la génération de messages de validation pour garantir la cohérence et inclure les métadonnées nécessaires :
#!/usr/bin/env bash
# Automated commit message enhancement with Azure DevOps integration
enhance_commit_message() {
local commit_msg_file="$1"
local commit_source="$2"
local sha="$3"
# Skip automation for merge commits, amend commits, etc.
if [ -n "$commit_source" ]; then
return 0
fi
# Get current branch information
local current_branch=$(git branch --show-current)
local branch_prefix=""
# Extract work item ID from branch name if present
if [[ "$current_branch" =~ ^(feature|bugfix|hotfix)/([0-9]+) ]]; then
local work_item_id="${BASH_REMATCH[2]}"
branch_prefix="AB#$work_item_id: "
elif [[ "$current_branch" =~ ^(feature|bugfix|hotfix)/(.+)$ ]]; then
local feature_name="${BASH_REMATCH[2]}"
branch_prefix="[$feature_name] "
fi
# Read existing commit message
local existing_message=$(cat "$commit_msg_file")
# Only add prefix if not already present
if [ ! -z "$branch_prefix" ] && ! echo "$existing_message" | grep -q "^$branch_prefix"; then
# Create enhanced commit message
echo "${branch_prefix}${existing_message}" > "$commit_msg_file"
fi
# Add commit template if message is empty
if [ -z "$existing_message" ] || [ "$existing_message" = "" ]; then
cat >> "$commit_msg_file" << EOF
${branch_prefix}Brief description of changes
# Detailed explanation of what and why changes were made
#
# Include:
# - What problem this solves
# - Why this approach was chosen
# - Any breaking changes or migration notes
#
# Link to work items: AB#1234
EOF
fi
}
enhance_commit_message "$@"
Commiter le hook de validation de message
Vérifiez que les messages de validation répondent aux normes organisationnelles :
#!/usr/bin/env bash
# Comprehensive commit message validation
validate_commit_message() {
local commit_msg_file="$1"
local commit_message=$(cat "$commit_msg_file")
# Remove comment lines for validation
local clean_message=$(echo "$commit_message" | grep -v '^#' | sed '/^$/d')
# Check minimum length
if [ ${#clean_message} -lt 10 ]; then
echo "Commit message too short (minimum 10 characters)"
return 1
fi
# Check maximum length for first line
local first_line=$(echo "$clean_message" | head -n1)
if [ ${#first_line} -gt 72 ]; then
echo "Commit message first line too long (maximum 72 characters)"
echo "Current length: ${#first_line}"
return 1
fi
# Check for work item reference in enterprise environments
if ! echo "$clean_message" | grep -qE "(AB#[0-9]+|#[0-9]+|closes #[0-9]+|fixes #[0-9]+)"; then
echo "Commit message should reference a work item (e.g., AB#1234 or #1234)"
echo "Continue anyway? (y/N)"
read -r response
if [[ ! "$response" =~ ^[Yy]$ ]]; then
return 1
fi
fi
# Check for conventional commit format (optional)
if echo "$first_line" | grep -qE "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: "; then
echo "Conventional commit format detected"
fi
echo "Commit message validation passed"
return 0
}
validate_commit_message "$@" || exit 1
Intégration d’Azure DevOps
Intégration du hook côté serveur
Utilisez des hooks de service Azure DevOps pour l’automatisation côté serveur :
#!/usr/bin/env bash
# Azure DevOps webhook integration for advanced workflows
trigger_azure_validation() {
local branch_name=$(git branch --show-current)
local commit_sha=$(git rev-parse HEAD)
# Trigger Azure Pipelines validation build
if command -v az >/dev/null 2>&1; then
echo "Triggering Azure DevOps validation pipeline..."
az pipelines build queue \
--definition-name "PR-Validation" \
--branch "$branch_name" \
--commit-id "$commit_sha" \
--output table
fi
}
# Integration with Azure Boards
update_work_item() {
local commit_message="$1"
# Extract work item ID from commit message
if [[ "$commit_message" =~ AB#([0-9]+) ]]; then
local work_item_id="${BASH_REMATCH[1]}"
echo "Updating Azure Boards work item #$work_item_id..."
# Add commit information to work item
az boards work-item update \
--id "$work_item_id" \
--discussion "Commit $(git rev-parse --short HEAD): $(echo "$commit_message" | head -n1)"
fi
}
Optimisation des performances et meilleures pratiques
Recommandations en matière de performances de hook
Implémentez des optimisations des performances pour maintenir la productivité des développeurs :
#!/usr/bin/env bash
# Performance-optimized hook implementation
optimize_hook_performance() {
# Cache expensive operations
local cache_dir=".git/hooks-cache"
mkdir -p "$cache_dir"
# Only run expensive checks on changed files
local changed_files=$(git diff --cached --name-only)
# Implement timeout protection
timeout 30s expensive_operation || {
echo "Hook operation timed out, skipping..."
return 0
}
# Provide progress feedback for long operations
echo "Running validation (this may take a moment)..."
}
# Implement graceful degradation
fallback_validation() {
echo "Primary validation failed, running minimal checks..."
# Implement basic validation as fallback
}
Ce guide d’implémentation complet fournit la base des hooks Git d’entreprise sophistiqués qui améliorent la sécurité, la qualité et la conformité tout en conservant la productivité des développeurs et l’efficacité des flux de travail.