xref: /cloud-hypervisor/scripts/gitlint/rules/TitleStartsWithComponent.py (revision 851ab0ad433608fbfa2ac6d6fb34f0bbedb174fd)
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            'Jenkinsfile',
46            'misc',
47            'net_gen',
48            'net_util',
49            'option_parser',
50            'pci',
51            'performance-metrics',
52            'rate_limiter',
53            'README',
54            'resources',
55            'scripts',
56            'serial_buffer',
57            'test_data',
58            'test_infra',
59            'tests',
60            'tpm',
61            'tracer',
62            'vhost_user_block',
63            'vhost_user_net',
64            'virtio-devices',
65            'vm-allocator',
66            'vm-device',
67            'vmm',
68            'vm-migration',
69            'vm-virtio')
70
71        ptrn_title = re.compile(r'^(.+?):\s(.+)$')
72        match = ptrn_title.match(line)
73
74        if not match:
75            self.log.debug("Invalid commit title {}", line)
76            return [RuleViolation(self.id, "Commit title does not comply with "
77                                  "rule: 'component: change summary'")]
78        components = match.group(1)
79        summary = match.group(2)
80        self.log.debug(f"\nComponents: {components}\nSummary: {summary}")
81
82        ptrn_components = re.compile(r',\s')
83        components_list = re.split(ptrn_components, components)
84        self.log.debug("components list: %s" % components_list)
85
86        for component in components_list:
87            if component not in valid_components:
88                return [RuleViolation(self.id,
89                                      f"Invalid component: {component}, "
90                                      "\nValid components are: {}".format(
91                                          " ".join(valid_components)))]
92