From ea7999e0644bb8a7ca75d464d967fde1d5f127fc Mon Sep 17 00:00:00 2001 From: Ruslan Mstoi Date: Thu, 9 Nov 2023 18:31:17 +0200 Subject: [PATCH] build: add gitlint commit message linter Implement commit message check workflow using gitlint Fixes: #5840 Signed-off-by: Ruslan Mstoi --- .github/workflows/gitlint.yaml | 26 ++++++++++++ .gitlint | 15 +++++++ scripts/gitlint/rules.py | 75 ++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 .github/workflows/gitlint.yaml create mode 100644 .gitlint create mode 100644 scripts/gitlint/rules.py diff --git a/.github/workflows/gitlint.yaml b/.github/workflows/gitlint.yaml new file mode 100644 index 000000000..f7ee7c909 --- /dev/null +++ b/.github/workflows/gitlint.yaml @@ -0,0 +1,26 @@ +name: Commit messages check + +on: + pull_request: + +jobs: + gitlint: + name: Check commit messages + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install --upgrade gitlint + - name: Lint git commit messages + run: | + gitlint --commits origin/$GITHUB_BASE_REF.. diff --git a/.gitlint b/.gitlint new file mode 100644 index 000000000..5acb7610b --- /dev/null +++ b/.gitlint @@ -0,0 +1,15 @@ +[general] +extra-path=scripts/gitlint/rules.py +regex-style-search=true + +[ignore-by-author-name] +regex=dependabot +ignore=all + +# default 72 +[title-max-length] +line-length=50 + +# default 80 +[body-max-line-length] +line-length=72 diff --git a/scripts/gitlint/rules.py b/scripts/gitlint/rules.py new file mode 100644 index 000000000..1c9286c6b --- /dev/null +++ b/scripts/gitlint/rules.py @@ -0,0 +1,75 @@ +from gitlint.rules import LineRule, RuleViolation, CommitMessageTitle +import re + + +class TitleStartsWithComponent(LineRule): + """This rule will enforce that the commit message title starts with valid + component name + """ + + # A rule MUST have a human friendly name + name = "title-has-valid-component" + + # A rule MUST have a *unique* id. + # We recommend starting with UL (for User-defined Line-rule) + id = "UL1" + + # A line-rule MUST have a target (not required for CommitRules). + target = CommitMessageTitle + + def validate(self, line, _commit): + valid_components = [ + 'api_client', + 'arch', + 'block', + 'build', + 'ch-remote', + 'ci', + 'devices', + 'docs', + 'event_monitor', + 'fuzz', + 'github', + 'gitignore', + 'hypervisor', + 'Jenkinsfile', + 'misc', + 'net_gen', + 'net_util', + 'option_parser', + 'pci', + 'performance-metrics', + 'rate_limiter', + 'README', + 'resources', + 'scripts', + 'serial_buffer', + 'test_data', + 'test_infra', + 'tests', + 'tpm', + 'tracer', + 'vhost_user_block', + 'vhost_user_net', + 'virtio-devices', + 'vm-allocator', + 'vm-device', + 'vmm', + 'vm-migration', + 'vm-virtio'] + + pattern = re.compile(r'^(.+):\s(.+)$') + match = pattern.match(line) + + if not match: + self.log.debug("Invalid commit title {}", line) + return [RuleViolation(self.id, "Commit title does not comply with " + "rule: 'component: change summary'")] + component = match.group(1) + summary = match.group(2) + self.log.debug(f"\nComponent: {component}\nSummary: {summary}") + + if component not in valid_components: + return [RuleViolation(self.id, + f"Invalid component: {component}, " + f"valid components are: {valid_components}")]