-
Notifications
You must be signed in to change notification settings - Fork 24
122 lines (99 loc) · 4.92 KB
/
commit.yml
File metadata and controls
122 lines (99 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
name: Custom Commit Message Validator
on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
validate_COMMIT_MESSAGEs:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get PR Commits SHAs
id: get_pr_commits
run: |
# Fetch all commit SHAs associated with the current Pull Request
PR_COMMIT_SHAS=$(gh pr view ${{ github.event.pull_request.number }} --json commits --jq '[.commits[].oid] | join(" ")')
echo "PR_COMMITS_LIST=${PR_COMMIT_SHAS}" >> "$GITHUB_OUTPUT"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Validate Each Commit Message
env:
TARGET_DATE: "2025-07-22" # Only check commits after this date
SKIP_KEYWORDS: "Merge,Revert,Release" # Comma-separated keywords to skip validation
run: |
# Read commit SHAs into array
IFS=' ' read -r -a commit_shas <<< "${{ steps.get_pr_commits.outputs.PR_COMMITS_LIST }}"
has_validation_failed=false
# Convert skip keywords to array
IFS=',' read -r -a skip_keywords <<< "$SKIP_KEYWORDS"
for commit_sha in "${commit_shas[@]}"; do
echo "--- Checking commit: ${commit_sha} ---"
# Get commit timestamps for date filtering
COMMIT_DATE_UNIX=$(git log -n 1 --format=%at "${commit_sha}")
TARGET_DATE_UNIX=$(date -d "${TARGET_DATE}" +"%s")
COMMIT_DATE_HUMAN=$(git log -n 1 --format=%ad --date=iso-strict "${commit_sha}")
# Skip older commits
if (( COMMIT_DATE_UNIX < TARGET_DATE_UNIX )); then
echo "Skipping commit ${commit_sha} (Date: ${COMMIT_DATE_HUMAN}) as it is older than ${TARGET_DATE}."
continue
fi
echo "Processing commit ${commit_sha} (Date: ${COMMIT_DATE_HUMAN}) as it is on or after ${TARGET_DATE}."
COMMIT_MESSAGE=$(git log --format=%B -n 1 "${commit_sha}")
echo "Message content:"
echo "${COMMIT_MESSAGE}"
echo ""
# Check for skip keywords
skip_this_commit=false
for keyword in "${skip_keywords[@]}"; do
# Trim whitespace from keyword
trimmed_keyword=$(echo "$keyword" | xargs)
if [[ -n "$trimmed_keyword" ]] &&
[[ "${COMMIT_MESSAGE}" == *"$trimmed_keyword"* ]]; then
echo "Skipping validation for commit ${commit_sha} due to skip keyword: ${trimmed_keyword}"
skip_this_commit=true
break
fi
done
if [ "$skip_this_commit" = true ]; then
continue
fi
# --- Validation Logic Start ---
# 1. Check Conventional Commit format
if [[ ! "${COMMIT_MESSAGE}" =~ ^(feat|fix|docs|chore|style|refactor|perf|test|build|ci|revert)(\([a-zA-Z0-9_-]+\))?(!?): ]]; then
echo "::error file=COMMIT_MESSAGE::Commit ${commit_sha} does not start with a conventional commit type. Message: '${COMMIT_MESSAGE}'"
has_validation_failed=true
continue
fi
# Extract commit subject (first line)
commit_subject=$(echo "${COMMIT_MESSAGE}" | head -n 1)
# 2. NEW: Check minimum subject length (15 characters)
if [[ ${#commit_subject} -lt 15 ]]; then
echo "::error file=COMMIT_MESSAGE::Commit ${commit_sha} subject is too short (min 15 characters). Length: ${#commit_subject}. Subject: '${commit_subject}'"
has_validation_failed=true
continue
fi
# 3. Check maximum subject length (72 characters)
if [[ ${#commit_subject} -gt 72 ]]; then
echo "::warning file=COMMIT_MESSAGE::Commit ${commit_sha} subject line exceeds 72 characters. Length: ${#commit_subject}. Subject: '${commit_subject}'"
fi
# 4. Check empty line between subject and body
if [[ $(echo "${COMMIT_MESSAGE}" | wc -l) -gt 1 ]]; then
second_line=$(echo "${COMMIT_MESSAGE}" | awk 'NR==2 {print}' | xargs)
if [[ -n "${second_line}" ]]; then
echo "::error file=COMMIT_MESSAGE::Commit ${commit_sha} is missing an empty line between subject and body. Message: '${COMMIT_MESSAGE}'"
has_validation_failed=true
continue
fi
fi
done
# Fail job if any validation errors occurred
if [ "$has_validation_failed" = true ]; then
echo "::error::One or more commit messages failed validation. Please review the errors above."
exit 1
fi
echo "All relevant commit messages in the PR passed validation."