From 10ee3c40db65039a32fc682ce0ee79bed203c2ff Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Wed, 7 May 2025 11:16:57 +0000 Subject: [PATCH] Add pre-receive.sh --- pre-receive.sh | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 pre-receive.sh diff --git a/pre-receive.sh b/pre-receive.sh new file mode 100644 index 0000000..1982dec --- /dev/null +++ b/pre-receive.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +# Semantic commit pattern +PATTERN='^(feat|fix|docs|style|refactor|test|perf|build|ci|chore|revert)(\([a-zA-Z0-9\._-]+\))?: .{1,}$' + +# Pattern for merge commits from pull requests +PR_MERGE_PATTERN='^Merge pull request' + +# Pattern for standard Git merge commits +GIT_MERGE_PATTERN='^Merge (branch|remote-tracking branch) .+ into .+$' + +# Set text colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +# Statistics tracking +INVALID_COMMITS=0 +VALID_COMMITS=0 +MERGE_COMMITS=0 +TOTAL_COMMITS=0 + +# Draw box for statistics +draw_box() { + local title="$1" + local width=60 + local padding=$(((width - ${#title}) / 2)) + + echo -e "${BOLD}┌$(printf '─%.0s' $(seq 1 $width))┐${NC}" + echo -e "${BOLD}│$(printf ' %.0s' $(seq 1 $padding))$title$(printf ' %.0s' $(seq 1 $((width - padding - ${#title}))))│${NC}" + echo -e "${BOLD}└$(printf '─%.0s' $(seq 1 $width))┘${NC}" +} + +# Read stdin (format: ) +while read -r OLD_REV NEW_REV REF_NAME; do + # Skip if it's a branch deletion + if [[ "$NEW_REV" = "0000000000000000000000000000000000000000" ]]; then + continue + fi + + # Handle new branch pushes differently + if [[ "$OLD_REV" = "0000000000000000000000000000000000000000" ]]; then + continue + fi + + echo -e "${YELLOW}Checking commits in $REF_NAME${NC}" + + # Get branch stats from git (quietly) + BRANCH_COMMITS=$(git rev-list --count "$REF_NAME" 2>/dev/null || echo "?") + BRANCH_AGE=$(git log -1 --format="%cr" "$REF_NAME" 2>/dev/null || echo "unknown time ago") + + # Get all commit hashes between old and new revision + COMMITS=$(git rev-list "$OLD_REV".."$NEW_REV") + + # Count how many commits we're validating + COMMITS_TO_CHECK=$(echo "$COMMITS" | wc -l) + if [ "$COMMITS_TO_CHECK" -eq 0 ]; then + echo -e "${GREEN}No new commits to validate${NC}" + continue + else + echo -e "${BLUE}Validating $COMMITS_TO_CHECK commit(s)${NC}" + fi + + # Process each commit message silently + for COMMIT in $COMMITS; do + TOTAL_COMMITS=$((TOTAL_COMMITS + 1)) + COMMIT_MSG=$(git log --format=%B -n 1 "$COMMIT") + COMMIT_SUBJECT=$(echo "$COMMIT_MSG" | head -n 1) + PARENT_COUNT=$(git rev-list --parents -n 1 "$COMMIT" | awk '{print NF - 1}') + + # Process merge commits or regular commits + if [[ $PARENT_COUNT -gt 1 ]] && (echo "$COMMIT_SUBJECT" | grep -E "$PR_MERGE_PATTERN" >/dev/null || echo "$COMMIT_SUBJECT" | grep -E "$GIT_MERGE_PATTERN" >/dev/null); then + MERGE_COMMITS=$((MERGE_COMMITS + 1)) + continue + fi + + # Validate commit message silently + if ! [[ "$COMMIT_SUBJECT" =~ $PATTERN ]]; then + INVALID_COMMITS=$((INVALID_COMMITS + 1)) + else + VALID_COMMITS=$((VALID_COMMITS + 1)) + fi + done + + # Display only the commit statistics box + draw_box "COMMIT STATISTICS" + echo -e "${BOLD}Branch information:${NC} $BRANCH_COMMITS total commits (created $BRANCH_AGE)" + echo -e "${BOLD}Commits validated:${NC} $TOTAL_COMMITS" + echo -e "${GREEN}Valid semantic commits: ${NC} $VALID_COMMITS" + echo -e "${BLUE}Merge commits: ${NC} $MERGE_COMMITS" + echo -e "${RED}Invalid commits: ${NC} $INVALID_COMMITS" + echo "" + + if [ $TOTAL_COMMITS -gt 0 ]; then + VALID_PERCENT=$(((VALID_COMMITS + MERGE_COMMITS) * 100 / TOTAL_COMMITS)) + echo -e "${BOLD}Semantic compliance:${NC} $VALID_PERCENT%" + + # Print bar + printf "[" + for ((i = 0; i < VALID_PERCENT / 5; i++)); do + printf "${GREEN}#${NC}" + done + for ((i = VALID_PERCENT / 5; i < 20; i++)); do + printf "${RED}.${NC}" + done + printf "] $VALID_PERCENT%%\n" + echo "" + fi +done + +# If any commits were invalid, reject the push +if [[ $INVALID_COMMITS -gt 0 ]]; then + echo -e "${RED}Push rejected: $INVALID_COMMITS commit(s) have invalid messages.${NC}" + echo -e "${YELLOW}Please rewrite your commit messages to follow the semantic commit format:${NC}" + echo "type(scope): message" + exit 1 +fi + +exit 0 \ No newline at end of file