From 77e042237dcfbbfde2da2b3d2b6b7347c8516e9e Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Fri, 21 Mar 2025 11:00:40 +0100 Subject: [PATCH] ci: improve gitlint (max line length in body with exceptions) Follow-up of 5aa1540c5dc33d61020a08dd2818c0f5fd08575f but way more mature. We now use custom gitlint rules written in Python to better handle the max line length, with respect to a few valid exceptions. Recognizing code blocks or compiler output, as discussed, is not trivial and hard to get right for all corner-cases. Therefore, this commit is a pragmatic way forward. The CI job should be kept optional. Allowed exceptions for the 72 line length limit are now: 1. links in the following three common patterns: https://example.com/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links [0] https://example.com/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links [0]: https://example.com/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links 2. code blocks (anything between the three backticks) ``` let x = "very_long_very_long_very_long_very_long_very_long_very_long_very_long_very_long_very_long_very_long_" ``` Signed-off-by: Philipp Schuster On-behalf-of: SAP philipp.schuster@sap.com --- .gitlint | 11 +---- scripts/gitlint/rules/BodyMaxLineLengthEx.py | 49 +++++++++++++++++++ .../TitleStartsWithComponent.py} | 2 + 3 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 scripts/gitlint/rules/BodyMaxLineLengthEx.py rename scripts/gitlint/{rules.py => rules/TitleStartsWithComponent.py} (98%) diff --git a/.gitlint b/.gitlint index f94b9ec2b..455dd0281 100644 --- a/.gitlint +++ b/.gitlint @@ -1,6 +1,7 @@ [general] -extra-path=scripts/gitlint/rules.py +extra-path=scripts/gitlint/rules regex-style-search=true +ignore=body-max-line-length [ignore-by-author-name] regex=dependabot @@ -10,11 +11,3 @@ ignore=all [title-max-length] line-length=72 -# default 80 -[body-max-line-length] -line-length=72 - -# Allow developers to add long links to useful resources -[ignore-by-body] -regex=^https?:\/\/ -ignore=body-max-line-length diff --git a/scripts/gitlint/rules/BodyMaxLineLengthEx.py b/scripts/gitlint/rules/BodyMaxLineLengthEx.py new file mode 100644 index 000000000..88314fc52 --- /dev/null +++ b/scripts/gitlint/rules/BodyMaxLineLengthEx.py @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: Apache-2.0 + +from gitlint.rules import LineRule, RuleViolation, CommitMessageBody +import re + + +class BodyMaxLineLengthEx(LineRule): + """A rule to enforce a line limit of 72 characters, except for valid cases.""" + + # A rule MUST have a human friendly name + name = "body-max-line-length-ex" + + # A rule MUST have a *unique* id. + # We recommend starting with UL (for User-defined Line-rule) + id = "UL-ll" + + # A line-rule MUST have a target (not required for CommitRules). + target = CommitMessageBody + + max_len = 72 + + # Updated property as the commit messages is validated line by line. + inside_open_codeblock = False + + def validate(self, line, commit): + # Pattern allowing: + # - [0]: https://foobar + # - [0] https://foobar + # - https://foobar + link_regex = re.compile(r"^((\[[0-9]+\]:?\s?)?https?:\/\/).*$") + + is_codeblock_marker = line.startswith("```") + + inside_open_codeblock_ = self.inside_open_codeblock + if is_codeblock_marker: + self.inside_open_codeblock = not self.inside_open_codeblock + + if len(line) > self.max_len: + is_link = link_regex.match(line) + + if inside_open_codeblock_: + return + + if is_link: + return + + return [ + RuleViolation(self.id, f"Line '{line}' exceeds limit of {self.max_len}") + ] diff --git a/scripts/gitlint/rules.py b/scripts/gitlint/rules/TitleStartsWithComponent.py similarity index 98% rename from scripts/gitlint/rules.py rename to scripts/gitlint/rules/TitleStartsWithComponent.py index 1a84113dd..cbac9946d 100644 --- a/scripts/gitlint/rules.py +++ b/scripts/gitlint/rules/TitleStartsWithComponent.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + from gitlint.rules import LineRule, RuleViolation, CommitMessageTitle import re