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