diff --git a/.githooks/check-branch-name.sh b/.githooks/check-branch-name.sh index 752e199..0e71c9b 100755 --- a/.githooks/check-branch-name.sh +++ b/.githooks/check-branch-name.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script checks if the current branch name follows the specified format. # It's designed to be used as a 'pre-commit' git hook. diff --git a/.githooks/check-commit-msg.sh b/.githooks/check-commit-msg.sh index 82bd441..eacf2a8 100755 --- a/.githooks/check-commit-msg.sh +++ b/.githooks/check-commit-msg.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script checks if a commit message follows the specified format. # It's designed to be used as a 'commit-msg' git hook. @@ -23,6 +23,44 @@ NC='\033[0m' # No Color # The first argument to the hook is the path to the file containing the commit message COMMIT_MSG_FILE=$1 +# --- Automated Commit Detection --- + +# Read the first line (header) for initial checks +HEADER=$(head -n 1 "$COMMIT_MSG_FILE") + +# Check for Merge commits (covers 'git merge' and PR merges from GitHub/GitLab) +# Examples: "Merge branch 'main' into ...", "Merge pull request #123 from ..." +MERGE_PATTERN="^Merge (branch|pull request|tag) .*" +if [[ "$HEADER" =~ $MERGE_PATTERN ]]; then + echo -e "${GREEN}Merge commit detected by message content. Skipping validation.${NC}" + exit 0 +fi + +# Check for Revert commits +# Example: "Revert "feat: add new feature"" +REVERT_PATTERN="^Revert \".*\"" +if [[ "$HEADER" =~ $REVERT_PATTERN ]]; then + echo -e "${GREEN}Revert commit detected by message content. Skipping validation.${NC}" + exit 0 +fi + +# Check for Cherry-pick commits (this pattern appears at the end of the message) +# Example: "(cherry picked from commit deadbeef...)" +# We use grep -q to search the whole file quietly. +CHERRY_PICK_PATTERN="\(cherry picked from commit [a-f0-9]{7,40}\)" +if grep -qE "$CHERRY_PICK_PATTERN" "$COMMIT_MSG_FILE"; then + echo -e "${GREEN}Cherry-pick detected by message content. Skipping validation.${NC}" + exit 0 +fi + +# Check for Squash +# Example: "Squash commits ..." +SQUASH_PATTERN="^Squash .+" +if [[ "$HEADER" =~ $SQUASH_PATTERN ]]; then + echo -e "${GREEN}Squash commit detected by message content. Skipping validation.${NC}" + exit 0 +fi + # --- Validation Functions --- # Function to print an error message and exit @@ -56,20 +94,24 @@ if ! [[ "$HEADER" =~ $HEADER_REGEX ]]; then error_exit "Invalid header format.\n\nHeader must be in the format: : \nAllowed types: ${ALLOWED_TYPES[*]}\nExample: feat: add new user authentication feature" fi -# 3. Validate the footer (last line) of the commit message -FOOTER=$(tail -n 1 "$COMMIT_MSG_FILE") +# Only validate footer if commit type is not chore +TYPE=$(echo "$HEADER" | cut -d':' -f1) +if [ "$TYPE" != "chore" ]; then + # 3. Validate the footer (last line) of the commit message + FOOTER=$(tail -n 1 "$COMMIT_MSG_FILE") -# Regex breakdown: -# ^(ref|close) - Starts with 'ref' or 'close' -# : - Followed by a literal colon -# \s - Followed by a single space -# N25B- - Followed by the literal string 'N25B-' -# [0-9]+ - Followed by one or more digits -# $ - End of the line -FOOTER_REGEX="^(ref|close): N25B-[0-9]+$" + # Regex breakdown: + # ^(ref|close) - Starts with 'ref' or 'close' + # : - Followed by a literal colon + # \s - Followed by a single space + # N25B- - Followed by the literal string 'N25B-' + # [0-9]+ - Followed by one or more digits + # $ - End of the line + FOOTER_REGEX="^(ref|close): N25B-[0-9]+$" -if ! [[ "$FOOTER" =~ $FOOTER_REGEX ]]; then - error_exit "Invalid footer format.\n\nFooter must be in the format: [ref/close]: \nExample: ref: N25B-123" + if ! [[ "$FOOTER" =~ $FOOTER_REGEX ]]; then + error_exit "Invalid footer format.\n\nFooter must be in the format: [ref/close]: \nExample: ref: N25B-123" + fi fi # 4. If the message has more than 2 lines, validate the separator