CI+Meta: Synchronize commit linting rules

Our CI commit linter now evaluates commit messages line by line, similar
to `Meta/lint-commit.sh`.

The URL rule was updated to allow any freestanding URL, optionally
prefixed by whitespace.
This commit is contained in:
Jelle Raaijmakers
2025-10-24 11:03:31 +02:00
committed by Jelle Raaijmakers
parent e3a56ef913
commit ba78e3d4be
Notes: github-actions[bot] 2025-10-24 11:10:47 +00:00
2 changed files with 26 additions and 15 deletions

View File

@@ -24,31 +24,36 @@ jobs:
error: "Commit message contains CRLF line breaks (only unix-style LF linebreaks are allowed)",
},
{
pattern: /^.+(\n(\n.*)*)?$/,
line: 2,
pattern: /^$/,
error: "Empty line between commit title and body is missing",
},
{
pattern: /^((?!^Merge branch )[\s\S])*$/,
line: 1,
pattern: /^(?!Merge branch )/,
error: "Commit is a git merge commit, use the rebase command instead",
},
{
pattern: /^\S.*?\S: .+/,
line: 1,
pattern: /^(Revert "|\S+: )/,
error: "Missing category in commit title (if this is a fix up of a previous commit, it should be squashed)",
},
{
line: 1,
pattern: /^\S.*?: [A-Z0-9]/,
error: "First word of commit after the subsystem is not capitalized",
},
{
pattern: /^.+[^.\n](\n.*)*$/,
line: 1,
pattern: /[^.]$/,
error: "Commit title ends in a period",
},
{
pattern: /^.{0,72}(?:\n(?:(.{0,72})|(.*?([a-z]+:\/\/)?(([a-zA-Z0-9_]|-)+\.)+[a-z]{2,}(:\d+)?([a-zA-Z_0-9@:%\+.~\?&/=]|-)+).*?))*$/,
error: "Commit message lines are too long (maximum allowed is 72 characters, except for URLs)",
pattern: /^(.{0,72}|\s*[a-z]+:\/\/([a-z0-9\-]+\.)+[a-z]{2,}(:\d+)?(\/[a-zA-Z_0-9@:%+.~?&=\-]+)*)$/,
error: "Commit message lines are too long (maximum allowed is 72 characters, except for URLs on their own line)",
},
{
pattern: /^((?!Signed-off-by: )[\s\S])*$/,
pattern: /^(?!Signed-off-by: )/,
error: "Commit body contains a Signed-off-by tag",
},
];
@@ -69,14 +74,20 @@ jobs:
if (author !== null && excludedBotIds.includes(author.id)) {
continue;
}
const commitErrors = [];
for (const { pattern, error } of rules) {
if (!pattern.test(message)) {
commitErrors.push(error);
let commitErrors = [];
message.split("\n").forEach((line, index) => {
for (const { line: ruleLine, pattern, error } of rules) {
if (ruleLine !== undefined && ruleLine !== index + 1) {
continue;
}
if (!pattern.test(line)) {
commitErrors.push(error);
}
}
}
});
if (commitErrors.length > 0) {
const title = message.split("\n")[0];
commitErrors = [...new Set(commitErrors)]; // remove duplicates
errors.push([`${title} (${sha}):`, ...commitErrors].join("\n "));
}
}

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
# the file containing the commit message is passed as the first argument
commit_file="$1"
@@ -53,14 +54,13 @@ while read -r line; do
error "Commit title ends in a period"
fi
url_pattern="([a-z]+:\/\/)?(([a-zA-Z0-9_]|-)+\.)+[a-z]{2,}(:\d+)?([a-zA-Z_0-9@:%\+.~\?&\/=]|-)+"
url_pattern='^\s*[a-z]+:\/\/([a-z0-9\-]+\.)+[a-z]{2,}(:\d+)?(\/[a-zA-Z_0-9@:%+.~?&=\-]+)*$'
if [[ $line_length -gt 72 ]] && (echo "$line" | grep -E -v -q "$url_pattern"); then
error "Commit message lines are too long (maximum allowed is 72 characters)"
error "Commit message lines are too long (maximum allowed is 72 characters, except for URLs on their own line)"
fi
if [[ "$line" == "Signed-off-by: "* ]]; then
error "Commit body contains a Signed-off-by tag"
fi
done <"$commit_file"
exit 0