Skip to content

Commit 80b3c99

Browse files
committed
[MarkAPI-112] feature: Adiciona um hook para padronizar os commits e o nomes dos branchs.
1 parent ee1f205 commit 80b3c99

2 files changed

Lines changed: 130 additions & 0 deletions

File tree

.git-hook-commit-msg

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env python3
2+
"""Git commit-msg hook.
3+
4+
Reads the activity (MarkAPI-NNNN) from the branch name -- anywhere in the
5+
name -- and:
6+
7+
1. validates the message format: <type>(<optional scope>): <message>
8+
allowed types: feature, fix, chore, unittest
9+
2. injects the activity prefix into the first line: [MarkAPI-NNNN] ...
10+
11+
Automatic Git commits (merge/revert/squash) are skipped.
12+
Uses the standard library only for portability across Linux and macOS.
13+
"""
14+
15+
import re
16+
import subprocess
17+
import sys
18+
19+
ALLOWED_TYPES = ("feature", "fix", "chore", "unittest")
20+
21+
BRANCH_ACTIVITY_RE = re.compile(r"MarkupAPI-(\d+)", re.IGNORECASE)
22+
EXISTING_PREFIX_RE = re.compile(r"^\s*\[MarkupAPI-\d+\]\s*", re.IGNORECASE)
23+
MESSAGE_FORMAT_RE = re.compile(
24+
r"^(?:%s)(?:\([a-z0-9-]+\))?: .+" % "|".join(ALLOWED_TYPES)
25+
)
26+
27+
# Automatic commits generated by Git that should pass without validation.
28+
MarkAPI_COMMIT_PREFIXES = (
29+
"Merge branch ",
30+
"Merge pull request ",
31+
"Merge remote-tracking ",
32+
'Revert "',
33+
)
34+
SQUASH_MERGE_RE = re.compile(r"^Merge .+ into ")
35+
36+
37+
def fail(message):
38+
print(message, file=sys.stderr)
39+
sys.exit(1)
40+
41+
42+
def is_auto_commit(first_line):
43+
if first_line.startswith(MarkAPI_COMMIT_PREFIXES):
44+
return True
45+
return bool(SQUASH_MERGE_RE.match(first_line))
46+
47+
48+
def current_branch():
49+
# symbolic-ref works even on the first commit (branch with no commits),
50+
# where rev-parse --abbrev-ref HEAD fails. On a detached HEAD,
51+
# symbolic-ref returns a non-zero code and we fall back to rev-parse
52+
# (which returns "HEAD").
53+
for cmd in (
54+
["git", "symbolic-ref", "--short", "HEAD"],
55+
["git", "rev-parse", "--abbrev-ref", "HEAD"],
56+
):
57+
try:
58+
result = subprocess.run(cmd, capture_output=True, text=True)
59+
except OSError:
60+
return None
61+
if result.returncode == 0:
62+
branch = result.stdout.strip()
63+
if branch:
64+
return branch
65+
return None
66+
67+
68+
def main():
69+
if len(sys.argv) < 2:
70+
fail("❌ commit-msg hook: message file path not provided.")
71+
72+
msg_path = sys.argv[1]
73+
with open(msg_path, "r", encoding="utf-8") as handle:
74+
lines = handle.read().splitlines()
75+
76+
if not lines:
77+
fail("❌ Empty commit message.")
78+
79+
first_line = lines[0].rstrip("\r")
80+
81+
# Let automatic Git commits pass through.
82+
if is_auto_commit(first_line):
83+
sys.exit(0)
84+
85+
branch = current_branch()
86+
if not branch or branch == "HEAD":
87+
fail(
88+
"❌ Could not determine the current branch (detached HEAD?).\n"
89+
"The branch must contain the activity MarkAPI-NNNN."
90+
)
91+
92+
match = BRANCH_ACTIVITY_RE.search(branch)
93+
if not match:
94+
fail(
95+
"❌ Branch without an activity.\n"
96+
"The branch name must contain MarkAPI-NNNN "
97+
"(e.g. feature/MarkAPI-1234/my-feature).\n"
98+
"Current branch: %s" % branch
99+
)
100+
101+
activity = "MarkAPI-%s" % match.group(1)
102+
103+
# Strip an existing prefix to avoid duplication (amend/rebase/reword).
104+
body = EXISTING_PREFIX_RE.sub("", first_line).strip()
105+
106+
if not MESSAGE_FORMAT_RE.match(body):
107+
fail(
108+
"❌ Invalid commit message.\n"
109+
"Expected format: <type>(<optional scope>): <message>\n"
110+
"Allowed types: %s\n"
111+
"Examples:\n"
112+
" chore: format readme\n"
113+
" fix(auth): fix authentication when token is invalid"
114+
% ", ".join(ALLOWED_TYPES)
115+
)
116+
117+
lines[0] = "[%s] %s" % (activity, body)
118+
119+
with open(msg_path, "w", encoding="utf-8") as handle:
120+
handle.write("\n".join(lines) + "\n")
121+
122+
sys.exit(0)
123+
124+
125+
if __name__ == "__main__":
126+
main()

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ latest_commit: ## Show last commit ref
3131
build_date: ## Show build date
3232
@echo "Build date: " $(SCMS_BUILD_DATE)
3333

34+
configure_git_hooks: ## Configure git hooks
35+
cp -fa .git-hook-commit-msg .git/hooks/commit-msg
36+
ln -sf ../../.git-hook-commit-msg .git/hooks/commit-msg
37+
3438
############################################
3539
## atalhos docker compose desenvolvimento ##
3640
############################################

0 commit comments

Comments
 (0)