From 1f27ab1c8f2e3e90fbdd87f367b3ceca10df5314 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 4 Mar 2026 18:52:07 +0000 Subject: [PATCH] GH: check commit messages for the most common errors This checks commit messages in a pull-request for the most common problems we see. --- .github/scripts/commit-msg-check.pl | 103 ++++++++++++++++++++ .github/workflows/check-commit-message.yaml | 38 ++++++++ 2 files changed, 141 insertions(+) create mode 100755 .github/scripts/commit-msg-check.pl create mode 100644 .github/workflows/check-commit-message.yaml diff --git a/.github/scripts/commit-msg-check.pl b/.github/scripts/commit-msg-check.pl new file mode 100755 index 000000000..80ac97529 --- /dev/null +++ b/.github/scripts/commit-msg-check.pl @@ -0,0 +1,103 @@ +#!/usr/bin/env perl + +# Copyright (C) Nginx, Inc. + +# +# Takes input in the form +# +# git show -s --format=%B +# + +use strict; +use warnings; + +my $E = "❌ "; + +# 72 characters is a natural choice. It provides 4 characters of +# left/right margin on a standard 80 character wide terminal in +# git-log(1) etc standard output. +# +# vim(1) (from 7.2) ships with Tim Pope's vim-git ftplugin which +# amongst other things autowraps lines when editing commit messages +# after 72 characters. +my $LINE_LENGTH_LIMIT = 72; + +my $subject = <>; +my $body; + +while (<>) { + $body .= $_; +} + +sub chk_sub_length { + if (length($subject) > $LINE_LENGTH_LIMIT) { + print $E . "Subject is longer than " . $LINE_LENGTH_LIMIT . + " characters\n"; + } +} + +sub chk_sub_prefix_cap { + my $excemptions = qr/gRPC: /; + + if ($subject =~ /^[a-z][a-zA-Z_-]*: /) { + if ($subject =~ /^((?!$excemptions).)*$/) { + print $E . "Subject prefix should be capitalised\n"; + } + } + + if ($subject =~ /^[a-zA-Z_-]*: [A-Z]/) { + print $E . "First word after the prefix should be lower case\n"; + } +} + +sub chk_body_blank_line { + if (($body =~ /^(.*)/)[0]) { + print $E . "Commit message body should be separated from the subject by a blank line\n"; + } +} + +sub chk_body_trailers { + my $prev_line = ""; + + foreach (split(/\n/, $body)) { + if (/^[a-zA-Z-]*: /) { + if ($prev_line ne "") { + print $E . "Commit tags/trailers should be separated from the commit message body by a blank line\n"; + } + + last; + } + + $prev_line = $_; + } +} + +sub chk_body_line_length { + foreach (split(/\n/, $body)) { + # Ignore indented lines for command/log output etc and URLs. + if (/^[ \t]/ || /https?:\/\// || /ftp:\/\//) { + next; + } + + # Stop after hitting commit tags/trailers + if (/^[a-zA-Z-]*: /) { + last; + } + + if (length($_) <= $LINE_LENGTH_LIMIT) { + next; + } + + print $E . "One or more body lines exceed " . $LINE_LENGTH_LIMIT . " characters. (Indent command/log output etc lines to quell this error)\n"; + + last; + } +} + +chomp($subject); +chk_sub_length(); +chk_sub_prefix_cap(); + +chk_body_blank_line(); +chk_body_trailers(); +chk_body_line_length(); diff --git a/.github/workflows/check-commit-message.yaml b/.github/workflows/check-commit-message.yaml new file mode 100644 index 000000000..3f0cc8041 --- /dev/null +++ b/.github/workflows/check-commit-message.yaml @@ -0,0 +1,38 @@ +name: Check Commit Message(s) + +# Get the repository with all commits to ensure that we can +# analyze all of the commits contributed via the Pull Request. + +on: + pull_request: + types: [ opened, synchronize ] + +jobs: + check-commit-messages: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 + + - name: check-commits.sh + run: | + echo "## Commit Message Linter Results" >${GITHUB_STEP_SUMMARY} + err=0 + while read hash subj + do + echo "Checking: ${hash} (\"${subj}\")" | tee -a ${GITHUB_STEP_SUMMARY} + out=$(git show -s --format=%B ${hash} | .github/scripts/commit-msg-check.pl) + if test -n "${out}" + then + echo "${out}" | tee -a ${GITHUB_STEP_SUMMARY} + err=1 + else + echo "✅ ok" | tee -a ${GITHUB_STEP_SUMMARY} + fi + done <<< $(git rev-list --oneline ${{github.event.pull_request.base.sha}}..${{github.event.pull_request.head.sha}}) + + if test ${err} -ne 0 + then + exit 2 + fi -- 2.47.3