Skip to content

Commit 9e7ef63

Browse files
committed
ci: add gitlint to pre-commit hook
JIRA: PSDK-216 risk: low
1 parent 73c8706 commit 9e7ef63

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

.gitlint

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# (C) 2025 GoodData Corporation
2+
[general]
3+
# do not enforce maximum line length rules
4+
ignore=T1, B1, B2, B5, T5
5+
6+
# prevent a warning about regexes in the ignore-by-title section
7+
regex-style-search=true
8+
9+
# enable our extended conventional commits rule
10+
extra-path=packages/repo-tools/src/quiver_monorepo/conventional_commit_gitlint_rule.py
11+
12+
# ignore all release commits (merge and revert commits are ignored by default)
13+
[ignore-by-title]
14+
regex=^Release(.*)
15+
ignore=all
16+
17+
# add the most likely scopes for each package
18+
[gdc-title-conventional-commits]
19+
scopes=gooddata-api-client,gooddata-dbt,gooddata-fdw,gooddata-flexconnect,gooddata-flight-server,gooddata-pandas,gooddata-sdk

.pre-commit-config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,7 @@ repos:
3030
args: [ "--update", "FILES" ]
3131
language: script
3232
types: [ text ]
33+
- repo: https://github.com/jorisroovers/gitlint
34+
rev: v0.19.1
35+
hooks:
36+
- id: gitlint

dev-requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
-r ./tox-requirements.txt
22
-r ./release-requirements.txt
3+
34
pre-commit~=4.0.1
5+
gitlint~=0.19.1
46

57
-r ./fmt-requirements.txt
68

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# (C) 2025 GoodData Corporation
2+
"""
3+
An extension of the CT1 rule from gitlint to enforce the conventional commit format.
4+
This version also allows specifying allowed scope values.
5+
"""
6+
7+
import re
8+
9+
from gitlint.options import ListOption
10+
from gitlint.rules import CommitMessageTitle, LineRule, RuleViolation
11+
12+
RULE_REGEX = re.compile(r"([^(]+?)(?:\(([^)]+?)\))?!?: .+")
13+
14+
DEFAULT_TYPES = [
15+
"fix",
16+
"feat",
17+
"chore",
18+
"docs",
19+
"style",
20+
"refactor",
21+
"perf",
22+
"test",
23+
"revert",
24+
"ci",
25+
"build",
26+
]
27+
DEFAULT_SCOPES = []
28+
29+
30+
class ConventionalCommit(LineRule):
31+
"""This rule enforces the spec at https://www.conventionalcommits.org/."""
32+
33+
name = "gdc-title-conventional-commits"
34+
id = "GD1"
35+
target = CommitMessageTitle
36+
37+
options_spec = [
38+
ListOption(
39+
"types",
40+
DEFAULT_TYPES,
41+
"Comma separated list of allowed commit types.",
42+
),
43+
ListOption(
44+
"scopes",
45+
DEFAULT_SCOPES,
46+
"Comma separated list of allowed commit scopes.",
47+
),
48+
]
49+
50+
def validate(self, line, _commit):
51+
violations = []
52+
match = RULE_REGEX.match(line)
53+
54+
if not match:
55+
msg = "Title does not follow ConventionalCommits.org format 'type(optional-scope): description'"
56+
violations.append(RuleViolation(self.id, msg, line))
57+
else:
58+
line_commit_type = match.group(1)
59+
line_commit_scope = match.group(2)
60+
if line_commit_type not in self.options["types"].value:
61+
opt_str = ", ".join(self.options["types"].value)
62+
violations.append(RuleViolation(self.id, f"Title does not start with one of {opt_str}", line))
63+
if line_commit_scope and line_commit_scope not in self.options["scopes"].value:
64+
opt_str = ", ".join(self.options["scopes"].value)
65+
violations.append(RuleViolation(self.id, f"Scope is defined and is not one of {opt_str}", line))
66+
67+
return violations

0 commit comments

Comments
 (0)