Files
Aperant/apps/backend/runners/github/bot_detection_example.py
T
Andy 348de6dfe7 Feat/Auto Fix Github issues and do extensive AI PR reviews (#250)
* feat(github): add GitHub automation system for issues and PRs

Implements comprehensive GitHub automation with three major components:

1. Issue Auto-Fix: Automatically creates specs from labeled issues
   - AutoFixButton component with progress tracking
   - useAutoFix hook for config and queue management
   - Backend handlers for spec creation from issues

2. GitHub PRs Tool: AI-powered PR review sidebar
   - New sidebar tab (Cmd+Shift+P) alongside GitHub Issues
   - PRList/PRDetail components for viewing PRs
   - Review system with findings by severity
   - Post review comments to GitHub

3. Issue Triage: Duplicate/spam/feature-creep detection
   - Triage handlers with label application
   - Configurable detection thresholds

Also adds:
- Debug logging (DEBUG=true) for all GitHub handlers
- Backend runners/github module with orchestrator
- AI prompts for PR review, triage, duplicate/spam detection
- dev:debug npm script for development with logging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(github-runner): resolve import errors for direct script execution

Changes runner.py and orchestrator.py to handle both:
- Package import: `from runners.github import ...`
- Direct script: `python runners/github/runner.py`

Uses try/except pattern for relative vs direct imports.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(github): correct argparse argument order for runner.py

Move --project global argument before subcommand so argparse can
correctly parse it. Fixes "unrecognized arguments: --project" error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* logs when debug mode is on

* refactor(github): extract service layer and fix linting errors

Major refactoring to improve maintainability and code quality:

Backend (Python):
- Extracted orchestrator.py (2,600 → 835 lines, 68% reduction) into 7 service modules:
  - prompt_manager.py: Prompt template management
  - response_parsers.py: AI response parsing
  - pr_review_engine.py: PR review orchestration
  - triage_engine.py: Issue triage logic
  - autofix_processor.py: Auto-fix workflow
  - batch_processor.py: Batch issue handling
- Fixed 18 ruff linting errors (F401, C405, C414, E741):
  - Removed unused imports (BatchValidationResult, AuditAction, locked_json_write)
  - Optimized collection literals (set([n]) → {n})
  - Removed unnecessary list() calls
  - Renamed ambiguous variable 'l' to 'label' throughout

Frontend (TypeScript):
- Refactored IPC handlers (19% overall reduction) with shared utilities:
  - autofix-handlers.ts: 1,042 → 818 lines
  - pr-handlers.ts: 648 → 543 lines
  - triage-handlers.ts: 437 lines (no duplication)
- Created utils layer: logger, ipc-communicator, project-middleware, subprocess-runner
- Split github-store.ts into focused stores: issues, pr-review, investigation, sync-status
- Split ReviewFindings.tsx into focused components

All imports verified, type checks passing, linting clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 16:43:20 +01:00

155 lines
4.7 KiB
Python

"""
Bot Detection Integration Example
==================================
Demonstrates how to use the bot detection system to prevent infinite loops.
"""
from pathlib import Path
from models import GitHubRunnerConfig
from orchestrator import GitHubOrchestrator
async def example_with_bot_detection():
"""Example: Reviewing PRs with bot detection enabled."""
# Create config with bot detection
config = GitHubRunnerConfig(
token="ghp_user_token",
repo="owner/repo",
bot_token="ghp_bot_token", # Bot's token for self-identification
pr_review_enabled=True,
auto_post_reviews=False, # Manual review posting for this example
review_own_prs=False, # CRITICAL: Prevent reviewing own PRs
)
# Initialize orchestrator (bot detector is auto-initialized)
orchestrator = GitHubOrchestrator(
project_dir=Path("/path/to/project"),
config=config,
)
print(f"Bot username: {orchestrator.bot_detector.bot_username}")
print(f"Review own PRs: {orchestrator.bot_detector.review_own_prs}")
print(
f"Cooling off period: {orchestrator.bot_detector.COOLING_OFF_MINUTES} minutes"
)
print()
# Scenario 1: Review a human-authored PR
print("=== Scenario 1: Human PR ===")
result = await orchestrator.review_pr(pr_number=123)
print(f"Result: {result.summary}")
print(f"Findings: {len(result.findings)}")
print()
# Scenario 2: Try to review immediately again (cooling off)
print("=== Scenario 2: Immediate re-review (should skip) ===")
result = await orchestrator.review_pr(pr_number=123)
print(f"Result: {result.summary}")
print()
# Scenario 3: Review bot-authored PR (should skip)
print("=== Scenario 3: Bot-authored PR (should skip) ===")
result = await orchestrator.review_pr(pr_number=456) # Assume this is bot's PR
print(f"Result: {result.summary}")
print()
# Check statistics
stats = orchestrator.bot_detector.get_stats()
print("=== Bot Detection Statistics ===")
print(f"Bot username: {stats['bot_username']}")
print(f"Total PRs tracked: {stats['total_prs_tracked']}")
print(f"Total reviews: {stats['total_reviews_performed']}")
async def example_manual_state_management():
"""Example: Manually managing bot detection state."""
config = GitHubRunnerConfig(
token="ghp_user_token",
repo="owner/repo",
bot_token="ghp_bot_token",
review_own_prs=False,
)
orchestrator = GitHubOrchestrator(
project_dir=Path("/path/to/project"),
config=config,
)
detector = orchestrator.bot_detector
# Manually check if PR should be skipped
pr_data = {"author": {"login": "alice"}}
commits = [
{"author": {"login": "alice"}, "oid": "abc123"},
{"author": {"login": "alice"}, "oid": "def456"},
]
should_skip, reason = detector.should_skip_pr_review(
pr_number=789,
pr_data=pr_data,
commits=commits,
)
if should_skip:
print(f"Skipping PR #789: {reason}")
else:
print("PR #789 is safe to review")
# Proceed with review...
# After review:
detector.mark_reviewed(789, "abc123")
# Clear state when PR is closed/merged
detector.clear_pr_state(789)
def example_configuration_options():
"""Example: Different configuration scenarios."""
# Option 1: Strict bot detection (recommended)
strict_config = GitHubRunnerConfig(
token="ghp_user_token",
repo="owner/repo",
bot_token="ghp_bot_token",
review_own_prs=False, # Bot cannot review own PRs
)
# Option 2: Allow bot self-review (testing only)
permissive_config = GitHubRunnerConfig(
token="ghp_user_token",
repo="owner/repo",
bot_token="ghp_bot_token",
review_own_prs=True, # Bot CAN review own PRs
)
# Option 3: No bot detection (no bot token)
no_detection_config = GitHubRunnerConfig(
token="ghp_user_token",
repo="owner/repo",
bot_token=None, # No bot identification
review_own_prs=False,
)
print("Strict config:", strict_config.review_own_prs)
print("Permissive config:", permissive_config.review_own_prs)
print("No detection config:", no_detection_config.bot_token)
if __name__ == "__main__":
print("Bot Detection Integration Examples\n")
print("\n1. Configuration Options")
print("=" * 50)
example_configuration_options()
print("\n2. With Bot Detection (requires GitHub setup)")
print("=" * 50)
print("Run: asyncio.run(example_with_bot_detection())")
print("\n3. Manual State Management")
print("=" * 50)
print("Run: asyncio.run(example_manual_state_management())")