Skip to content

Conversation

Wes1eyyy
Copy link
Contributor

@Wes1eyyy Wes1eyyy commented Oct 2, 2025

Commit Message

  • 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.

🤖 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

  • Webhook signature verification using HMAC-SHA256
  • GitHub App JWT authentication with RS256 algorithm
  • Organization membership validation (optional)
  • Secure environment variable management

🎯 Command Processing

  • Smart command parsing with regex-based detection
  • Case-insensitive command matching
  • Flexible argument support for /fix commands
  • Background task processing for non-blocking webhook responses

🔧 Automated Workflow

  1. Webhook validation → Verify signature and event type
  2. Command detection → Parse /fix commands from comments
  3. Permission check → Validate organization membership (if configured)
  4. Repository cloning → Clone target repository to temporary directory
  5. AI-powered fixing → Run EuniFix service (placeholder for AI agent integration)
  6. Branch management → Create new branch with unique naming
  7. Commit & push → Commit changes and push to remote repository
  8. Pull request creation → Open PR with detailed description and file changes
  9. Status updates → Update placeholder comments with progress and results

📝 User Experience

  • Real-time feedback with placeholder comments
  • Detailed progress updates showing processing status
  • Rich PR descriptions with change summaries and file lists
  • Error handling with user-friendly error messages
  • Automatic issue linking with "Closes #issue" syntax

🏗️ Architecture

New Components

Configuration Layer

  • github.py - GitHub App settings management

Security Utilities

  • github_sec.py - Webhook verification, JWT creation, command parsing

Service Layer

  • github_service.py - GitHub API operations (tokens, comments, PRs, branches)
  • euni_fix.py - AI agent placeholder service

API Layer

  • github_webhook.py - Webhook endpoint handler

Testing

  • test_github_webhook.py - Comprehensive unit tests with mocked GitHub payloads

Updated Components

  • API Router - Added webhook route registration
  • Environment Config - Added GitHub App environment variables
  • Docker Compose - Updated with new environment variables
  • Dependencies - Added aiohttp and PyJWT[crypto] for HTTP requests and JWT handling

🚀 Usage

Environment Setup

# GitHub App Configuration
GITHUB_APP_ID=your_github_app_id
GITHUB_WEBHOOK_SECRET=your_webhook_secret
GITHUB_PRIVATE_KEY=your_github_private_key_content
GITHUB_BOT_HANDLE=euni-bot
GITHUB_ORG_NAME=your_org_name  # Optional

User Commands

# Basic fix command
@euni-bot /fix

# Fix with arguments
@euni-bot /fix --strict --format

# Fix with custom instructions
@euni-bot /fix Please focus on performance optimizations

Webhook Endpoint

  • URL: POST /v1.2/github/webhook
  • Events: issue_comment (created)
  • Security: HMAC-SHA256 signature verification

🧪 Testing

The implementation includes comprehensive test coverage:

  • pending test Webhook signature verification (valid/invalid signatures)
  • pending test Command parsing (various formats and edge cases)
  • pending test GitHub API integration (tokens, comments, PRs)
  • pending test Event filtering (correct event types and actions)
  • pending test Error handling (network failures, API errors)
  • pending test EuniFix service (success/failure scenarios)

📋 Requirements

GitHub App Permissions

  • Repository permissions:

    • Contents: Read & Write (for cloning and pushing)
    • Issues: Write (for commenting)
    • Pull requests: Write (for creating PRs)
    • Metadata: Read (for repository info)
  • Organization permissions:

    • Members: Read (for membership validation)

…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.
@Wes1eyyy Wes1eyyy requested review from Copilot and dcloud347 October 2, 2025 09:46
Copy link

@Copilot Copilot AI left a 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.


# Pattern to match @bot-handle /fix [optional args]
# Case insensitive matching
pattern = rf'@{re.escape(bot_handle)}\s+/fix(?:\s+(.+))?'
Copy link

Copilot AI Oct 2, 2025

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.

Suggested change
pattern = rf'@{re.escape(bot_handle)}\s+/fix(?:\s+(.+))?'
pattern = rf'@{re.escape(bot_handle)}\s+/fix(?:\s+(.*))?'

Copilot uses AI. Check for mistakes.

Comment on lines +21 to +22
self._installation_token: Optional[str] = None
self._token_expires_at: Optional[float] = None
Copy link

Copilot AI Oct 2, 2025

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.

Comment on lines +117 to +118
# Use git commands to commit changes
import subprocess
Copy link

Copilot AI Oct 2, 2025

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_")
Copy link

Copilot AI Oct 2, 2025

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.

Suggested change
temp_dir = tempfile.mkdtemp(prefix="euni_fix_")
temp_dir = tempfile.mkdtemp(prefix="euni_fix_", mode=0o700)

Copilot uses AI. Check for mistakes.

Comment on lines +194 to +198
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
Copy link

Copilot AI Oct 2, 2025

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.

Suggested change
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.

Comment on lines 288 to 290
try:
import shutil
shutil.rmtree(temp_repo_dir)
Copy link

Copilot AI Oct 2, 2025

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.

@dcloud347 dcloud347 closed this Oct 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants