Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 48 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
# Git Commit Quality Monitor
# Git Commit Quality Monitor v2

A smart Telex integration that helps teams maintain high-quality git commit messages using ML-powered analysis and real-time feedback.

## Overview

Git Commit Quality Monitor analyzes commit messages in real-time, providing instant feedback on commit quality and suggestions for improvement. It uses machine learning to understand commit patterns and provides customized suggestions based on conventional commit standards and the development team's preferences.

## Version Notes

- **v2 (current)**: Simplified architecture with pre-configured analysis rules
- **v1-legacy**: Available in v1-legacy branch, supports configurable commit rules and dynamic analyzer settings

### Key Features

- ⚡️ Real-time feedback through Slack
- 🎯 Customizable commit rules/conventions
- 🎯 Pre-configured commit standards based on conventional commits
- 🔄 GitHub webhook integration
- 🎨 Telex integration support
- 🤖 Smart ML-powered commit message analysis and suggestions
Expand Down Expand Up @@ -46,38 +51,41 @@ Git Commit Quality Monitor analyzes commit messages in real-time, providing inst
```
project_root/
├── src/
│ ├── core/ # Core Analysis Engine
│ │ ├── analyzer.py # ML-based commit analysis logic
│ │ └── models.py # Data models and structure
│ ├── core/ # Core Analysis Engine
│ │ ├── analyzer/ # ML-based commit analysis logic
| | | ├── analyzer.py
| | | ├── format_analyzer.py
| | | └── quality_analyzer.py
│ │ └── models.py # Data models and structure
│ │
│ ├── config/ # Configuration Management
│ │ ├── data.py # Training data, patterns, and examples
│ │ ├── config.py # Environment settings management
│ │ ├── integration_config.py # Telex integration configuration
│ │ └── middleware.py # CORS and trusted host middleware
│ ├── config/ # Configuration Management
│ │ ├── data.py # Training data, patterns, and examples
│ │ ├── config.py # Environment settings management
│ │ ├── integration_config.py # Telex integration configuration
│ │ └── middleware.py # CORS and trusted host middleware
│ │
│ ├── routers/ # API Routing Layer
│ │ ├── github.py # GitHub webhook endpoint handling
│ │ ├── telex.py # Telex webhook and integration
│ │ └── router.py # Main router configuration
│ ├── routers/ # API Routing Layer
│ │ ├── github.py # GitHub webhook endpoint handling
│ │ ├── telex.py # Telex webhook and integration
│ │ └── router.py # Main router configuration
│ │
│ └── utils/ # Utility Functions
│ └── telex_utils.py # Telex communication helpers
│ └── utils/ # Utility Functions
│ └── telex_utils.py # Telex communication helpers
├── tests/ # Test Suite
│ ├── __init__.py # Test configuration
│ ├── test_github.py # GitHub integration tests
│ └── test_telex.py # Telex integration tests
├── tests/ # Test Suite
│ ├── __init__.py # Test configuration
│ ├── test_github.py # GitHub integration tests
│ └── test_telex.py # Telex integration tests
├── .env.example # Environment variable template
├── main.py # Application entry point
├── requirements.txt # Project dependencies
└── README.md # Project documentation
├── .env.example # Environment variable template
├── main.py # Application entry point
├── requirements.txt # Project dependencies
└── README.md # Project documentation
```

### Core Analysis Engine

The system implements a multi-step process to evaluate the quality of commit messages:
The v2 system implements a multi-step process to evaluate the quality of commit messages:

#### Direct Pattern Matching
- Matches against predefined commit types
Expand Down Expand Up @@ -143,7 +151,7 @@ semantic_patterns = {

### GitHub Webhook Endpoint
```http
POST /api/v1/webhook/github/{telex_channel_id}
POST /api/v2/webhook/github/{telex_channel_id}/
Content-Type: application/json

{
Expand All @@ -157,11 +165,11 @@ Content-Type: application/json
]
}
```
Receives GitHub push events and forwards to Telex.
Receives GitHub push events, analyzes commits, and forwards to Telex.

### Telex Integration Endpoint
```http
POST /api/v1/webhook/telex
POST /api/v2/webhook/telex/
Content-Type: application/json

{
Expand All @@ -175,47 +183,17 @@ Content-Type: application/json
]
}
```
Receives commit messages from Telex and sends analysis results to slack.
Receives commit messages from Telex and forwards to slack.

### Integration Config
```
GET /integration.json
```
Returns integration configuration for Telex.

### Customizing Commit Analysis

You can customize the analyzer through Telex integration settings:

#### Commit Types
```json
{
"feat": ["add", "implement", "new"],
"fix": ["fix", "resolve", "patch"]
}
```

#### Example Commits
```json
{
"feat": "feat(auth): implement OAuth2 with role-based access\n\nImplemented OAuth2 protocol with role-based control to enhance security and scalability.",
"fix": "fix(api): resolve data race in concurrent requests\n\nFixed a race condition by adding synchronization mechanisms to prevent concurrent data modifications."
}
```

#### Training Data
```json
{
"feat": [
"feat(auth): implement JWT authentication flow\n\nImplemented JWT-based authentication with token expiration handling to secure user sessions.",
"feat(ui): add dark mode toggle with system preference detection\n\nAdded dark mode toggle that automatically adjusts based on system settings for improved user experience.",
],
}
```

## Development Guide

### Basic Setup
### Setting Up v2

1. Clone the repository:
```bash
Expand Down Expand Up @@ -270,7 +248,7 @@ uvicorn main:app --reload

#### Step 3: Configure Webhook
1. Fill in the following fields:
- Payload URL: `https://your-domain/api/v1/webhook/github/{telex_channel_id}`
- Payload URL: `https://your-domain/api/v2/webhook/github/{telex_channel_id}/`
- Replace `your-domain` with your actual domain
- Replace `{telex_channel_id}` with your Telex channel ID
2. Set Content Type:
Expand Down Expand Up @@ -322,12 +300,20 @@ uvicorn main:app --reload
- Click on "Manage App" beside the added integration
- Click on "Settings"
- Add the slack webhook in the `slack_url` field
- Clear defaults in `commit_types`, `example_commits`, and `training_data` fields; replace with custom values if necessary.

#### Step 3: Save and Activate
1. Click "Save Settings"
2. Enable the integration on the Apps dashboard

### Using v1 (Legacy Version)

For teams requiring customizable features:
1. Switch to v1-legacy branch:
```bash
git checkout v1-legacy
```
2. Follow setup instructions in v1-legacy README

### Testing Your Integration

#### Step 1: Make a Test Commit
Expand Down
24 changes: 1 addition & 23 deletions src/config/integration_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ def generate_json_config():
"integration_type": "output",
"key_features": [
"Smart commit message analysis with ML-powered suggestions",
"Customizable commit rules that fit any team's style",
"Instant notifications when commits need attention",
"Easy setup with pre-configured commit patterns"
],
"website": settings.app_logo_url,
"website": settings.app_url,
"author": "iamprecieee",
"settings": [
{
Expand All @@ -34,27 +33,6 @@ def generate_json_config():
"required": True,
"description": "Slack Webhook URL",
"default": "https://slack.com"
},
{
"label": "commit_types",
"type": "text",
"required": False,
"description": "Provide custom commit types mapped to keywords that indicate type of change. Format: {'type': ['keyword1', 'keyword2']}. Example: {'docs': ['document', 'readme']} means commits with 'document' or 'readme' suggest documentation changes.",
"default": "{'feat': ['add', 'implement', 'new', 'introduce'], 'fix': ['fix', 'resolve', 'patch', 'address']}"
},
{
"label": "example_commits",
"type": "text",
"required": False,
"description": "Set example commits for each custom commit type to guide new devs. These appear in suggestions when similar commits need fixing. Format: {'type1': 'example message1', 'type2': 'example message 2'}.",
"default": "{'feat': 'feat(auth): implement OAuth2 with role-based access\n\nImplemented OAuth2 protocol with role-based control to enhance security and scalability.', 'fix': 'fix(api): resolve data race in concurrent requests\n\nFixed a race condition by adding synchronization mechanisms to prevent concurrent data modifications.'}"
},
{
"label": "training_data",
"type": "text",
"required": False,
"description": "Add custom data to train the analyzer with commits that match preferred style. More examples = better suggestions. Format: {'type1': ['example1', 'example2'], 'type2': ['example3', 'example4']}. The analyzer learns from these to better match preferred conventions.",
"default": "{'feat': ['feat(auth): implement OAuth2 with role-based access\n\nImplemented OAuth2 protocol with role-based control to enhance security and scalability.','feat(search): implement elasticsearch integration\n\nIntegrated Elasticsearch to boost search performance and enhance result accuracy.']}"
}
],
"target_url": settings.target_url
Expand Down
32 changes: 2 additions & 30 deletions src/core/analyzer/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
example_commits,
commit_training_data
)
from fastapi import HTTPException, status
from ..models import CommitIssue
from .format_analyzer import FormatAnalyzer
from .quality_analyzer import QualityAnalyzer
from datetime import datetime
import ast


class CommitAnalyzer:
Expand All @@ -17,38 +15,12 @@ class CommitAnalyzer:
machine learning, and semantic analysis to ensure commit quality and
provide improvement suggestions.
"""
def __init__(self, settings: list) -> None:
"""Initializes the analyzer with custom settings and prepares the ML classifier."""
self.settings = settings
self.slack_url = None # Retrieved from settings
def __init__(self) -> None:
"""Initializes the analyzer with commit types, examples, and training data."""
self.commit_types = commit_types
self.example_commits = example_commits.copy()
self.commit_training_data = commit_training_data.copy()

try:
self._apply_data_settings()
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid settings data: {str(e)}",
)

def _apply_data_settings(self) -> None:
"""
Updates analyzer configuration with custom settings provided through Telex.
Custom settings can override default commit types, examples, and training data.
Provides slack webhook url.
"""
for setting in self.settings:
if setting["label"] == "commit_types":
self.commit_types.update(ast.literal_eval(setting["default"].replace("\n", "\\n"))) if setting["default"] else self.commit_types
if setting["label"] == "example_commits":
self.example_commits.update(ast.literal_eval(setting["default"].replace("\n", "\\n"))) if setting["default"] else self.example_commits
if setting["label"] == "training_data":
self.commit_training_data.update(ast.literal_eval(setting["default"].replace("\n", "\\n"))) if setting["default"] else self.commit_training_data
if setting["label"] == "slack_url":
self.slack_url = setting["default"]

def _check_content_format(self, message: str) -> list[CommitIssue]:
format_analyzer = FormatAnalyzer(message, self.commit_types, self.example_commits)
return format_analyzer.check_all()
Expand Down
67 changes: 44 additions & 23 deletions src/routers/github.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,55 @@
from fastapi.routing import APIRouter
from ..core.models import GitHubPayload, TelexWebhookPayload
from typing import Annotated
from ..core.analyzer.analyzer import CommitAnalyzer
from ..config.config import settings
from ..utils.telex_utils import send_payload
from fastapi.responses import JSONResponse
from fastapi import status, HTTPException
from fastapi import status, HTTPException, Query
import json


router = APIRouter(prefix="/github")


@router.post("/{telex_channel_id}", status_code=status.HTTP_200_OK)
async def github_webhook(telex_channel_id: str, payload: GitHubPayload):
"""Endpoint to receive GitHub webhook events and forward the commits to Telex."""
telex_payload = TelexWebhookPayload(
event_name="pushed_commits",
message=str(payload.commits),
status="success",
username=payload.pusher["name"],
).model_dump_json()

telex_url = f"{settings.telex_webhook_url}/{telex_channel_id}"

try:
response = await send_payload(telex_payload, telex_url)
response_data = json.loads(response.decode().strip())
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Telex payload sending failed: {str(e)}",
)

return JSONResponse(content={"data": response_data})
@router.post("/{telex_channel_id}/", status_code=status.HTTP_200_OK)
async def github_webhook(
telex_channel_id: str,
payload: GitHubPayload,
is_test: Annotated[str | None, Query()] = None,
):
"""
Endpoint to receive GitHub webhook events, analyze commit messages and
send results to Telex if issues are found.
"""
analyzer = CommitAnalyzer()
commits = payload.commits
all_messages = [] # Accumulate messages for test mode

for commit in commits:
violations = analyzer.analyze_commit(commit["message"])
if violations:
output_message = analyzer.format_analysis(commit, violations)
if is_test == "true":
all_messages.append(output_message)
else:
telex_payload = TelexWebhookPayload(
event_name="pushed_commits",
message=output_message,
status="success",
username=payload.pusher["name"],
).model_dump_json()

telex_url = f"{settings.telex_webhook_url}/{telex_channel_id}"

try:
await send_payload(telex_payload, telex_url)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Telex payload sending failed: {str(e)}",
)
if is_test == "true":
return JSONResponse(content=all_messages, status_code=status.HTTP_200_OK)

return JSONResponse(content={"status": "success"})
2 changes: 1 addition & 1 deletion src/routers/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
from .telex import router as telex_router


webhook_router = APIRouter(prefix="/api/v1/webhook")
webhook_router = APIRouter(prefix="/api/v2/webhook")
webhook_router.include_router(github_router)
webhook_router.include_router(telex_router)
Loading