xref: /cloud-hypervisor/scripts/gitlint/rules/TitleStartsWithComponent.py (revision 38380198e1660348e54cc69a6355bcd1f92e8cae)
1# SPDX-License-Identifier: Apache-2.0
2
3from gitlint.rules import LineRule, RuleViolation, CommitMessageTitle
4import re
5
6
7class TitleStartsWithComponent(LineRule):
8    """A rule to enforce valid commit message title
9
10    Valid title format:
11    component1[, component2, componentN]: submodule: summary
12
13    Title should have at least one component
14    Components are separated by comma+space: ", "
15    Components are validated to be in valid_components
16    Components list is ended by a colon
17    Submodules are not validated
18
19    """
20
21    # A rule MUST have a human friendly name
22    name = "title-has-valid-component"
23
24    # A rule MUST have a *unique* id.
25    # We recommend starting with UL (for User-defined Line-rule)
26    id = "UL1"
27
28    # A line-rule MUST have a target (not required for CommitRules).
29    target = CommitMessageTitle
30
31    def validate(self, line, _commit):
32        valid_components = (
33            'api_client',
34            'arch',
35            'block',
36            'build',
37            'ch-remote',
38            'ci',
39            'devices',
40            'docs',
41            'event_monitor',
42            'fuzz',
43            'github',
44            'gitignore',
45            'gitlint',
46            'hypervisor',
47            'main',
48            'misc',
49            'net_gen',
50            'net_util',
51            'openapi',
52            'option_parser',
53            'pci',
54            'performance-metrics',
55            'rate_limiter',
56            'README',
57            'resources',
58            'scripts',
59            'serial_buffer',
60            'test_data',
61            'test_infra',
62            'tests',
63            'tpm',
64            'tracer',
65            'vhost_user_block',
66            'vhost_user_net',
67            'virtio-devices',
68            'vm-allocator',
69            'vm-device',
70            'vmm',
71            'vm-migration',
72            'vm-virtio')
73
74        ptrn_title = re.compile(r'^(.+?):\s(.+)$')
75        match = ptrn_title.match(line)
76
77        if not match:
78            self.log.debug("Invalid commit title {}", line)
79            return [RuleViolation(self.id, "Commit title does not comply with "
80                                  "rule: 'component: change summary'")]
81        components = match.group(1)
82        summary = match.group(2)
83        self.log.debug(f"\nComponents: {components}\nSummary: {summary}")
84
85        ptrn_components = re.compile(r',\s')
86        components_list = re.split(ptrn_components, components)
87        self.log.debug("components list: %s" % components_list)
88
89        for component in components_list:
90            if component not in valid_components:
91                return [RuleViolation(self.id,
92                                      f"Invalid component: {component}, "
93                                      "\nValid components are: {}".format(
94                                          " ".join(valid_components)))]
95