-
Notifications
You must be signed in to change notification settings - Fork 4
Add GitHub App Webhook Integration for Automated Issue Fixing #139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…mand - Introduced GitHub App settings in the environment configuration. - Implemented GitHub webhook route to handle issue_comment events. - Added logic to parse and process /fix commands from comments. - Created background task to clone repositories, apply fixes, and create pull requests. - Developed EuniFix service to simulate code fixes on Python files. - Implemented GitHub service for API interactions, including token management and comment posting. - Added utility functions for verifying webhook signatures and creating JWT tokens. - Enhanced testing suite with comprehensive tests for GitHub webhook handling and EuniFix functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a comprehensive GitHub App webhook integration that enables EuniBot to automatically respond to /fix
commands in GitHub issues and pull requests. When users comment @euni-bot /fix
on an issue, the bot analyzes the code, applies fixes, and creates a pull request with the changes.
- Adds GitHub App authentication with JWT tokens and webhook signature verification
- Implements automated workflow from command detection to pull request creation
- Provides real-time user feedback with status updates and detailed progress tracking
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
File | Description |
---|---|
tests/app/test_github_webhook.py | Comprehensive test suite for webhook handling, command parsing, and GitHub API interactions |
pyproject.toml | Updated dependencies to support GitHub App integration |
prometheus/utils/github_sec.py | Security utilities for webhook verification, JWT creation, and command parsing |
prometheus/git/github_service.py | GitHub API service for token management, comments, PRs, and repository operations |
prometheus/configuration/github.py | GitHub App configuration settings management |
prometheus/app/services/euni_fix.py | EuniFix service placeholder with repository cloning and file modification logic |
prometheus/app/api/routes/github_webhook.py | Main webhook endpoint handler with background task processing |
prometheus/app/api/main.py | Router registration for the new webhook endpoint |
example.env | Added GitHub App environment variables template |
docker-compose.yml | Updated environment configuration for GitHub App settings |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
prometheus/utils/github_sec.py
Outdated
|
||
# Pattern to match @bot-handle /fix [optional args] | ||
# Case insensitive matching | ||
pattern = rf'@{re.escape(bot_handle)}\s+/fix(?:\s+(.+))?' |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The regex pattern uses a non-capturing group (?:\s+(.+))?
which could be simplified. Consider using rf'@{re.escape(bot_handle)}\s+/fix(?:\s+(.*))?'
to capture empty strings consistently, or handle the None case more explicitly.
pattern = rf'@{re.escape(bot_handle)}\s+/fix(?:\s+(.+))?' | |
pattern = rf'@{re.escape(bot_handle)}\s+/fix(?:\s+(.*))?' |
Copilot uses AI. Check for mistakes.
self._installation_token: Optional[str] = None | ||
self._token_expires_at: Optional[float] = None |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class defines token caching fields but never uses them. The get_installation_token
method always creates a new JWT and requests a new token. Either implement proper token caching with expiration checking or remove these unused fields.
Copilot uses AI. Check for mistakes.
# Use git commands to commit changes | ||
import subprocess |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The subprocess
import should be moved to the top of the file rather than inside the function. This follows Python best practices and makes dependencies clearer.
Copilot uses AI. Check for mistakes.
import subprocess | ||
|
||
# Create temporary directory | ||
temp_dir = tempfile.mkdtemp(prefix="euni_fix_") |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The temporary directory is created without explicit permission restrictions. Consider using tempfile.mkdtemp(prefix=\"euni_fix_\", mode=0o700)
to ensure only the owner can access the cloned repository contents.
temp_dir = tempfile.mkdtemp(prefix="euni_fix_") | |
temp_dir = tempfile.mkdtemp(prefix="euni_fix_", mode=0o700) |
Copilot uses AI. Check for mistakes.
authenticated_clone_url = repo_clone_url.replace( | ||
"https://", f"https://x-access-token:{token}@" | ||
) | ||
push_success = await push_to_branch( | ||
temp_repo_dir, branch_name, authenticated_clone_url |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GitHub token is embedded directly in the clone URL string. Consider using environment variables or git credential helpers to avoid exposing the token in command line arguments or process lists.
authenticated_clone_url = repo_clone_url.replace( | |
"https://", f"https://x-access-token:{token}@" | |
) | |
push_success = await push_to_branch( | |
temp_repo_dir, branch_name, authenticated_clone_url | |
# Use the regular clone URL and pass the token separately for secure authentication | |
push_success = await push_to_branch( | |
temp_repo_dir, branch_name, repo_clone_url, token |
Copilot uses AI. Check for mistakes.
try: | ||
import shutil | ||
shutil.rmtree(temp_repo_dir) |
Copilot
AI
Oct 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The shutil
import should be moved to the top of the file rather than inside the cleanup block. This follows Python best practices and makes dependencies clearer.
Copilot uses AI. Check for mistakes.
…eld for environment variable specification
# Conflicts: # prometheus/configuration/config.py
Commit Message
🤖 Add GitHub App Webhook Integration for Automated Issue Fixing
Overview
This PR implements a comprehensive GitHub App webhook system that enables EuniBot to automatically respond to
/fix
commands on GitHub issues and pull requests. When users comment@euni-bot /fix
on an issue, the bot will analyze the code, apply fixes, and create a pull request with the changes.✨ Features
🔐 Security & Authentication
🎯 Command Processing
/fix
commands🔧 Automated Workflow
/fix
commands from comments📝 User Experience
🏗️ Architecture
New Components
Configuration Layer
Security Utilities
Service Layer
API Layer
Testing
Updated Components
aiohttp
andPyJWT[crypto]
for HTTP requests and JWT handling🚀 Usage
Environment Setup
User Commands
Webhook Endpoint
POST /v1.2/github/webhook
issue_comment
(created)🧪 Testing
The implementation includes comprehensive test coverage:
📋 Requirements
GitHub App Permissions
Repository permissions:
Organization permissions: