Skip to content

Commit d929a5e

Browse files
authored
Merge pull request #33 from telexintegrations/staging
Staging
2 parents a562409 + 3abe8b5 commit d929a5e

File tree

8 files changed

+545
-372
lines changed

8 files changed

+545
-372
lines changed

src/config/data.py

Lines changed: 150 additions & 82 deletions
Large diffs are not rendered by default.

src/core/analyzer.py

Lines changed: 0 additions & 276 deletions
This file was deleted.

src/core/analyzer/__init__.py

Whitespace-only changes.

src/core/analyzer/analyzer.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
from ...config.data import (
2+
commit_types,
3+
example_commits,
4+
commit_training_data
5+
)
6+
from fastapi import HTTPException, status
7+
from ..models import CommitIssue
8+
from .format_analyzer import FormatAnalyzer
9+
from .quality_analyzer import QualityAnalyzer
10+
from datetime import datetime
11+
import ast
12+
13+
14+
class CommitAnalyzer:
15+
"""
16+
Analyzes Git commit messages using a combination of pattern matching,
17+
machine learning, and semantic analysis to ensure commit quality and
18+
provide improvement suggestions.
19+
"""
20+
def __init__(self, settings: list) -> None:
21+
"""Initializes the analyzer with custom settings and prepares the ML classifier."""
22+
self.settings = settings
23+
self.slack_url = None # Retrieved from settings
24+
self.commit_types = commit_types
25+
self.example_commits = example_commits.copy()
26+
self.commit_training_data = commit_training_data.copy()
27+
28+
try:
29+
self._apply_data_settings()
30+
except Exception as e:
31+
raise HTTPException(
32+
status_code=status.HTTP_400_BAD_REQUEST,
33+
detail=f"Invalid settings data: {str(e)}",
34+
)
35+
36+
def _apply_data_settings(self) -> None:
37+
"""
38+
Updates analyzer configuration with custom settings provided through Telex.
39+
Custom settings can override default commit types, examples, and training data.
40+
Provides slack webhook url.
41+
"""
42+
for setting in self.settings:
43+
if setting["label"] == "commit_types":
44+
self.commit_types.update(ast.literal_eval(setting["default"].replace("\n", "\\n"))) if setting["default"] else self.commit_types
45+
if setting["label"] == "example_commits":
46+
self.example_commits.update(ast.literal_eval(setting["default"].replace("\n", "\\n"))) if setting["default"] else self.example_commits
47+
if setting["label"] == "training_data":
48+
self.commit_training_data.update(ast.literal_eval(setting["default"].replace("\n", "\\n"))) if setting["default"] else self.commit_training_data
49+
if setting["label"] == "slack_url":
50+
self.slack_url = setting["default"]
51+
52+
def _check_content_format(self, message: str) -> list[CommitIssue]:
53+
format_analyzer = FormatAnalyzer(message, self.commit_types, self.example_commits)
54+
return format_analyzer.check_all()
55+
56+
def _check_content_quality(self, message: str) -> list[CommitIssue]:
57+
quality_analyzer = QualityAnalyzer(message)
58+
return quality_analyzer.check_all()
59+
60+
def analyze_commit(self, message: str) -> list[CommitIssue]:
61+
"""Analyzes a commit message and returns any quality issues found."""
62+
issues = []
63+
issues.extend([*self._check_content_format(message)])
64+
issues.extend([*self._check_content_quality(message)])
65+
return [issue for issue in issues if issue]
66+
67+
def format_analysis(self, commit: dict, issues: list[CommitIssue]) -> str:
68+
"""Formats analysis results into a human-readable message for Slack."""
69+
icons = {"high": "🔴", "medium": "🟡", "low": "🔵"}
70+
71+
timestamp = datetime.fromisoformat(commit["timestamp"].replace("Z", "+00:00"))
72+
formatted_time = timestamp.strftime("%-I:%M%p. %A, %B %-d, %Y.")
73+
74+
author = commit["author"]
75+
author_info = f"{author['name']} ({author.get('email')})"
76+
77+
commit_details = (
78+
"📝 *Commit Details*\n"
79+
f"└─ Hash: `{commit['id'][:8]}`\n"
80+
f"└─ Author: {author_info}\n"
81+
f"└─ URL: <{commit['url']}|commit url>\n"
82+
f"└─ Time: {formatted_time}\n"
83+
f"└─ Message:\n"
84+
f"• ```{commit['message']}```\n"
85+
)
86+
87+
if issues:
88+
issues_text = "\n".join(
89+
f"{icons[issue.severity]} {issue.message}\n"
90+
f" └─ {issue.suggestion.replace(chr(10), chr(10) + ' ')}"
91+
for issue in sorted(issues, key=lambda x: x.severity)
92+
)
93+
analysis_section = "\n🔍 *Analysis Results*\n" f"{issues_text}\n"
94+
95+
suggestions = (
96+
"\n💡 Resources\n"
97+
"└─ Conventional Commits: <https://www.conventionalcommits.org|Conventional Commits>\n"
98+
"└─ Commit Best Practices: <https://dev.to/sheraz4194/good-commit-vs-bad-commit-best-practices-for-git-1plc|Best Practices>\n"
99+
"└─ Git Best Practices: <https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project|Git Contributing>"
100+
)
101+
102+
return f"{commit_details}{analysis_section}{suggestions}"

0 commit comments

Comments
 (0)