177e04223SPhilipp Schuster# SPDX-License-Identifier: Apache-2.0 277e04223SPhilipp Schuster 3ea7999e0SRuslan Mstoifrom gitlint.rules import LineRule, RuleViolation, CommitMessageTitle 4ea7999e0SRuslan Mstoiimport re 5ea7999e0SRuslan Mstoi 6ea7999e0SRuslan Mstoi 7ea7999e0SRuslan Mstoiclass TitleStartsWithComponent(LineRule): 8851ab0adSRuslan Mstoi """A rule to enforce valid commit message title 9851ab0adSRuslan Mstoi 10851ab0adSRuslan Mstoi Valid title format: 11851ab0adSRuslan Mstoi component1[, component2, componentN]: submodule: summary 12851ab0adSRuslan Mstoi 13851ab0adSRuslan Mstoi Title should have at least one component 14851ab0adSRuslan Mstoi Components are separated by comma+space: ", " 15851ab0adSRuslan Mstoi Components are validated to be in valid_components 16851ab0adSRuslan Mstoi Components list is ended by a colon 17851ab0adSRuslan Mstoi Submodules are not validated 18851ab0adSRuslan Mstoi 19ea7999e0SRuslan Mstoi """ 20ea7999e0SRuslan Mstoi 21ea7999e0SRuslan Mstoi # A rule MUST have a human friendly name 22ea7999e0SRuslan Mstoi name = "title-has-valid-component" 23ea7999e0SRuslan Mstoi 24ea7999e0SRuslan Mstoi # A rule MUST have a *unique* id. 25ea7999e0SRuslan Mstoi # We recommend starting with UL (for User-defined Line-rule) 26ea7999e0SRuslan Mstoi id = "UL1" 27ea7999e0SRuslan Mstoi 28ea7999e0SRuslan Mstoi # A line-rule MUST have a target (not required for CommitRules). 29ea7999e0SRuslan Mstoi target = CommitMessageTitle 30ea7999e0SRuslan Mstoi 31ea7999e0SRuslan Mstoi def validate(self, line, _commit): 32851ab0adSRuslan Mstoi valid_components = ( 33ea7999e0SRuslan Mstoi 'api_client', 34ea7999e0SRuslan Mstoi 'arch', 35ea7999e0SRuslan Mstoi 'block', 36ea7999e0SRuslan Mstoi 'build', 37ea7999e0SRuslan Mstoi 'ch-remote', 38ea7999e0SRuslan Mstoi 'ci', 39ea7999e0SRuslan Mstoi 'devices', 40ea7999e0SRuslan Mstoi 'docs', 41ea7999e0SRuslan Mstoi 'event_monitor', 42ea7999e0SRuslan Mstoi 'fuzz', 43ea7999e0SRuslan Mstoi 'github', 44ea7999e0SRuslan Mstoi 'gitignore', 4507475d2bSBo Chen 'gitlint', 46ea7999e0SRuslan Mstoi 'hypervisor', 4766f8841bSMuminul Islam 'main', 48ea7999e0SRuslan Mstoi 'misc', 49ea7999e0SRuslan Mstoi 'net_gen', 50ea7999e0SRuslan Mstoi 'net_util', 518a80bea4SRuslan Mstoi 'openapi', 52ea7999e0SRuslan Mstoi 'option_parser', 53ea7999e0SRuslan Mstoi 'pci', 54ea7999e0SRuslan Mstoi 'performance-metrics', 55ea7999e0SRuslan Mstoi 'rate_limiter', 56ea7999e0SRuslan Mstoi 'README', 57ea7999e0SRuslan Mstoi 'resources', 58ea7999e0SRuslan Mstoi 'scripts', 59*d580ed55SPhilipp Schuster 'seccomp', 60ea7999e0SRuslan Mstoi 'serial_buffer', 61ea7999e0SRuslan Mstoi 'test_data', 62ea7999e0SRuslan Mstoi 'test_infra', 63ea7999e0SRuslan Mstoi 'tests', 64ea7999e0SRuslan Mstoi 'tpm', 65ea7999e0SRuslan Mstoi 'tracer', 66ea7999e0SRuslan Mstoi 'vhost_user_block', 67ea7999e0SRuslan Mstoi 'vhost_user_net', 68ea7999e0SRuslan Mstoi 'virtio-devices', 69ea7999e0SRuslan Mstoi 'vm-allocator', 70ea7999e0SRuslan Mstoi 'vm-device', 71ea7999e0SRuslan Mstoi 'vmm', 72ea7999e0SRuslan Mstoi 'vm-migration', 73851ab0adSRuslan Mstoi 'vm-virtio') 74ea7999e0SRuslan Mstoi 75851ab0adSRuslan Mstoi ptrn_title = re.compile(r'^(.+?):\s(.+)$') 76851ab0adSRuslan Mstoi match = ptrn_title.match(line) 77ea7999e0SRuslan Mstoi 78ea7999e0SRuslan Mstoi if not match: 79ea7999e0SRuslan Mstoi self.log.debug("Invalid commit title {}", line) 80ea7999e0SRuslan Mstoi return [RuleViolation(self.id, "Commit title does not comply with " 81ea7999e0SRuslan Mstoi "rule: 'component: change summary'")] 82851ab0adSRuslan Mstoi components = match.group(1) 83ea7999e0SRuslan Mstoi summary = match.group(2) 84851ab0adSRuslan Mstoi self.log.debug(f"\nComponents: {components}\nSummary: {summary}") 85ea7999e0SRuslan Mstoi 86851ab0adSRuslan Mstoi ptrn_components = re.compile(r',\s') 87851ab0adSRuslan Mstoi components_list = re.split(ptrn_components, components) 88851ab0adSRuslan Mstoi self.log.debug("components list: %s" % components_list) 89851ab0adSRuslan Mstoi 90851ab0adSRuslan Mstoi for component in components_list: 91ea7999e0SRuslan Mstoi if component not in valid_components: 92ea7999e0SRuslan Mstoi return [RuleViolation(self.id, 93ea7999e0SRuslan Mstoi f"Invalid component: {component}, " 94851ab0adSRuslan Mstoi "\nValid components are: {}".format( 95851ab0adSRuslan Mstoi " ".join(valid_components)))] 96