GitHub App Integration Architecture
Overview
This document outlines the technical design for a centralized GitHub App that enables users to connect their repositories (including private ones) to our AI workflow system. The GitHub App will handle webhook events, provide secure access to repository data, and enable workflow triggers based on GitHub activities.
Architecture Components
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ GitHub App │────▶│ API Gateway │────▶│ Workflow │────▶│ Workflow Engine │
│ (Webhooks) │ │ (Event Reception)│ │ Scheduler │ │ (Execution) │
└─────────────────┘ └──────────────────┘ └──────────────────┘ └──────────────────┘
│ │ │ │
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ GitHub API │ │ Supabase │ │ Trigger Match │ │ User Workflows │
│ (Code Access) │ │ (Auth & State) │ │ & Filtering │ │ (Triggered) │
└─────────────────┘ └──────────────────┘ └──────────────────┘ └──────────────────┘
Flow Description:
- GitHub App receives webhook events from repositories
- API Gateway handles webhook reception, authentication, and signature verification
- Workflow Scheduler checks if any workflows have matching GitHub triggers
- Workflow Engine executes triggered workflows with repository context
1. GitHub App Registration & Setup
Step 1: Register GitHub App
Navigate to GitHub Settings:
- Go to
https://github.com/settings/apps
- Click "New GitHub App"
App Configuration:
App Name: "AI Workflow Teams"
Description: "Connect your repositories to AI-powered workflow automation"
Homepage URL: "https://aiworkflowteams.com"
Callback URL: "https://api.aiworkflowteams.com/api/v1/public/webhooks/github/auth"
Webhook URL: "https://api.aiworkflowteams.com/webhooks/github"
Webhook Secret: "generate_secure_random_string_here"
Public/Private Settings:
- ✅ Public - Allow anyone to install (required for public distribution)
- ✅ Allow installation on any account - Users and Organizations
Step 2: Configure Permissions & Events
App Permissions Required
Repository Permissions:
contents: read
- Access repository files and diffsmetadata: read
- Basic repository informationpull_requests: read
- PR data and commentsissues: read
- Issue data and commentsactions: read
- Workflow run informationdeployments: read
- Deployment status
Organization Permissions:
members: read
- Organization member information (optional)
Webhook Events:
push
,pull_request
,pull_request_review
issues
,issue_comment
,release
deployment
,deployment_status
workflow_run
,check_run
,check_suite
Step 3: Generate Private Key & Credentials
After App Creation:
- Generate Private Key: Click "Generate a private key" - download and store securely
- Note App ID: Found at top of app settings page
- Save Webhook Secret: Used for signature verification
- Client ID & Secret: For OAuth flow (if needed)
Security Best Practices:
- Store private key in secure environment variables or secret manager
- Use different webhook secrets for staging/production
- Enable webhook signature verification
- Regularly rotate credentials
Step 4: Development & Testing (Before Public Release)
Private App Testing Setup:
# Development App Configuration (Private)
App Name: "AI Workflow Teams (Dev)"
Description: "Development version for testing GitHub integration"
Homepage URL: "https://dev-api.aiworkflowteams.com"
Callback URL: "https://dev-api.aiworkflowteams.com/api/v1/public/webhooks/github/auth"
Webhook URL: "https://dev-api.aiworkflowteams.com/webhooks/github"
Webhook Secret: "dev_webhook_secret_here"
# Privacy Settings for Development
- ❌ **Private** - Only you can install (for testing)
- ✅ **Allow installation on personal account only** (initially)
Testing Workflow:
-
Create Development App:
# Create separate dev app at https://github.com/settings/apps
# Use different webhook URLs and secrets for dev environment -
Install on Personal Repositories:
# Install your dev app on test repositories
# Direct installation URL: https://github.com/apps/ai-workflow-teams-dev/installations/new -
Test Webhook Reception:
# Test webhook endpoint with ngrok for local development
pip install pyngrok
ngrok http 8000
# Update GitHub App webhook URL to ngrok URL
# Example: https://abc123.ngrok.io/webhooks/github -
Verify Event Processing:
# Monitor logs for webhook events
tail -f logs/github-webhooks.log
# Test different GitHub events:
# - Create a PR in test repo
# - Push commits
# - Add comments
# - Close/reopen issues -
Test Repository Access:
# Test GitHub API access with installation token
async def test_github_access():
client = GitHubSDK(app_id, private_key)
# Test getting installation token
token = await client.get_installation_token(installation_id)
# Test repository operations
repos = await client.list_repositories(installation_id)
pr_data = await client.get_pull_request(installation_id, "owner/repo", 1)
print(f"Successfully accessed {len(repos)} repositories") -
Test Workflow Triggers:
# Create test workflows with GitHub triggers
# Verify they execute when GitHub events occur
# Check workflow execution logs
Testing Checklist:
- Webhook signature verification works
- Installation tokens are correctly generated
- Repository data can be accessed (private repos)
- Workflow triggers activate on GitHub events
- Filtering (branches, paths, actions) works correctly
- Rate limiting doesn't cause issues
- Error handling works for invalid events
Step 5: App Distribution & Discovery
GitHub Marketplace (After Testing):
- Prepare for Marketplace: Complete app description, screenshots, pricing
- Submit for Review: GitHub reviews public apps for quality/security
- App Store Listing: Users can discover and install from GitHub Marketplace
Direct Installation URL:
https://github.com/apps/ai-workflow-teams/installations/new
- Can be embedded in your application for direct installation
Installation Flow
- User initiates connection via our frontend
- OAuth redirect to GitHub App installation page:
https://github.com/apps/{APP_NAME}/installations/new?state=<user_id>
- User selects repositories to grant access
- GitHub redirects back with installation data:
/api/v1/public/webhooks/github/auth?installation_id=12345&setup_action=install&state=<user_id>
- We store installation mapping in existing Supabase OAuth infrastructure
Database Schema (Implementation)
We leverage the existing OAuth infrastructure instead of creating separate GitHub tables:
-- Existing integrations table (stores GitHub app configuration)
-- Already exists - we create a GitHub integration entry
INSERT INTO integrations (
integration_id, integration_type, name, description, version,
configuration, supported_operations, required_scopes
) VALUES (
'github_app', 'github', 'GitHub App Integration',
'GitHub App for repository access and automation', '1.0',
'{"app_name": "agent-team-monorepo", "callback_url": "/api/v1/public/webhooks/github/auth"}',
ARRAY['repositories:read', 'repositories:write', 'issues:read', 'actions:read'],
ARRAY['repo', 'issues', 'actions']
);
-- Existing oauth_tokens table (stores user installation mappings)
-- We store GitHub installations as OAuth tokens with:
-- - integration_id: 'github_app'
-- - provider: 'github'
-- - access_token: placeholder (will be replaced with actual installation token)
-- - credential_data: JSON containing installation_id and setup_action
-- - user_id: links installation to specific user
Installation Data Storage
Credential Data Structure:
{
"installation_id": "12345",
"setup_action": "install",
"callback_timestamp": "2025-01-13T10:30:00Z"
}
Benefits of Existing Schema:
- ✅ Unified OAuth Management: All integrations (GitHub, Slack, etc.) in one system
- ✅ User Association: Direct link between users and their integrations
- ✅ Generic API:
/api/v1/app/integrations
works for all providers - ✅ Authentication: Proper JWT-based access control
- ✅ Audit Trail: Track when integrations are created/revoked
API Endpoints (Implementation)
Public API (No Authentication Required):
# GitHub App installation callback (handles redirect from GitHub)
GET /api/v1/public/webhooks/github/auth?installation_id=12345&setup_action=install&state=<user_id>
# - Stores installation data in database
# - Forwards to workflow_scheduler for additional processing
# - Returns success response with installation details
App API (Requires JWT Authentication):
# Get all user integrations (GitHub, Slack, etc.)
GET /api/v1/app/integrations
Authorization: Bearer <jwt_token>
# Returns: { "integrations": [...], "total_count": 2 }
# Get GitHub integrations only
GET /api/v1/app/integrations/github
Authorization: Bearer <jwt_token>
# Returns: GitHub installations for authenticated user
# Revoke specific integration
DELETE /api/v1/app/integrations/{integration_token_id}
Authorization: Bearer <jwt_token>
# Marks integration as inactive (soft delete)
Example Response:
{
"success": true,
"user_id": "user-123",
"integrations": [
{
"id": "token-abc-123",
"integration_id": "github_app",
"provider": "github",
"integration_type": "github",
"name": "GitHub App Integration",
"is_active": true,
"created_at": "2025-01-13T10:30:00Z",
"credential_data": {
"installation_id": "12345",
"setup_action": "install"
}
}
],
"total_count": 1
}
2. Webhook Event Processing
Step 1: API Gateway Event Reception
# API Gateway webhook endpoint (Implementation)
@router.post("/webhooks/github")
async def github_webhook(
request: Request,
x_github_event: str = Header(..., alias="X-GitHub-Event"),
x_github_delivery: str = Header(..., alias="X-GitHub-Delivery"),
x_hub_signature_256: Optional[str] = Header(None, alias="X-Hub-Signature-256"),
):
"""
GitHub webhook endpoint - handles GitHub App webhooks and routes them to workflow_scheduler
"""
# 1. Verify webhook signature if secret is configured
payload = await request.body()
if hasattr(settings, "GITHUB_WEBHOOK_SECRET") and settings.GITHUB_WEBHOOK_SECRET:
if not x_hub_signature_256 or not _verify_github_signature(
payload, x_hub_signature_256, settings.GITHUB_WEBHOOK_SECRET
):
raise HTTPException(status_code=401, detail="Invalid signature")
# 2. Parse JSON payload
event_data = json.loads(payload.decode())
# 3. Extract repository and installation info
installation_id = event_data.get("installation", {}).get("id")
repository = event_data.get("repository", {})
repo_name = repository.get("full_name", "unknown")
# 4. Forward to workflow_scheduler GitHub webhook handler
scheduler_url = f"{settings.workflow_scheduler_http_url}/api/v1/triggers/github/events"
github_webhook_data = {
"event_type": x_github_event,
"delivery_id": x_github_delivery,
"payload": event_data,
"installation_id": installation_id,
"repository_name": repo_name,
"timestamp": event_data.get("timestamp")
}
async with httpx.AsyncClient() as client:
scheduler_response = await client.post(scheduler_url, json=github_webhook_data, timeout=30.0)
if scheduler_response.status_code == 200:
result = scheduler_response.json()
return {
"status": "received",
"message": "GitHub webhook processed successfully",
"event_type": x_github_event,
"delivery_id": x_github_delivery,
"repository": repo_name,
"installation_id": installation_id,
"processed_workflows": result.get("processed_workflows", 0),
"results": result.get("results", []),
}
# GitHub App installation callback (Implementation)
@router.get("/webhooks/github/auth")
async def github_oauth_callback(
code: Optional[str] = None,
state: Optional[str] = None,
installation_id: Optional[str] = None,
setup_action: Optional[str] = None,
error: Optional[str] = None,
):
"""
GitHub OAuth callback endpoint - handles GitHub App installation OAuth flow
"""
# Handle app installation flow
if setup_action in ["install", "update"]:
# Store installation data in database if user_id is provided in state
if state and installation_id:
db_store_success = await _store_github_installation(state, installation_id, setup_action)
# Forward to workflow_scheduler to handle the installation
scheduler_url = f"{settings.workflow_scheduler_http_url}/api/v1/auth/github/callback"
installation_data = {
"installation_id": int(installation_id),
"setup_action": setup_action,
"state": state,
"code": code,
}
# Process with workflow_scheduler and return response
# Returns installation details including account info and repositories
Step 2: Forward to Workflow Scheduler
async def forward_to_workflow_scheduler(event_type: str, delivery_id: str, payload: dict):
"""Forward GitHub webhook to Workflow Scheduler service"""
scheduler_payload = {
"trigger_type": "github",
"event_type": event_type,
"delivery_id": delivery_id,
"github_payload": payload,
"timestamp": datetime.utcnow().isoformat()
}
# Call Workflow Scheduler API
async with httpx.AsyncClient() as client:
response = await client.post(
f"{WORKFLOW_SCHEDULER_URL}/triggers/github",
json=scheduler_payload,
headers={"Authorization": f"Bearer {INTERNAL_SERVICE_TOKEN}"}
)
if response.status_code != 200:
logger.error(f"Failed to forward to scheduler: {response.text}")
raise HTTPException(500, "Failed to process webhook")
Step 3: Workflow Scheduler Processing
# In Workflow Scheduler service
@app.post("/triggers/github")
async def handle_github_trigger(trigger_request: GitHubTriggerRequest):
"""Process GitHub webhook and check for matching workflow triggers"""
# 1. Extract installation and repository info
payload = trigger_request.github_payload
installation_id = payload.get("installation", {}).get("id")
repository = payload.get("repository", {})
# 2. Find workflows with matching GitHub triggers
matching_workflows = await find_workflows_with_github_triggers(
installation_id=installation_id,
repository_name=repository["full_name"],
event_type=trigger_request.event_type,
payload=payload
)
# 3. For each matching workflow, invoke Workflow Engine
for workflow in matching_workflows:
await invoke_workflow_engine(workflow, trigger_request)
async def find_workflows_with_github_triggers(
installation_id: int,
repository_name: str,
event_type: str,
payload: dict
) -> List[WorkflowDefinition]:
"""Find workflows that have GitHub triggers matching this event"""
# Query database for workflows with GitHub triggers
workflows = await db.execute("""
SELECT w.*, t.trigger_config
FROM workflows w
JOIN workflow_triggers t ON w.id = t.workflow_id
WHERE t.trigger_type = 'TRIGGER_GITHUB'
AND JSON_EXTRACT(t.trigger_config, '$.repository') = ?
AND JSON_EXTRACT(t.trigger_config, '$.events') LIKE ?
""", [repository_name, f'%{event_type}%'])
matching_workflows = []
for workflow_row in workflows:
trigger_config = json.loads(workflow_row.trigger_config)
# Apply filters (branches, paths, actions, authors, labels)
if await matches_github_filters(trigger_config, payload):
matching_workflows.append(WorkflowDefinition.from_row(workflow_row))
return matching_workflows
async def matches_github_filters(trigger_config: dict, payload: dict) -> bool:
"""Check if GitHub event matches all configured filters"""
# Branch filter
if trigger_config.get("branches"):
if not matches_branch_filter(trigger_config["branches"], payload):
return False
# Path filter
if trigger_config.get("paths"):
if not matches_path_filter(trigger_config["paths"], payload):
return False
# Action filter (for PR/issue events)
if trigger_config.get("action_filter"):
action = payload.get("action")
if action not in trigger_config["action_filter"]:
return False
# Author filter
if trigger_config.get("author_filter"):
if not matches_author_filter(trigger_config["author_filter"], payload):
return False
# Label filter (for PR/issue events)
if trigger_config.get("label_filter"):
if not matches_label_filter(trigger_config["label_filter"], payload):
return False
# Bot filter
if trigger_config.get("ignore_bots", True):
sender = payload.get("sender", {})
if sender.get("type") == "Bot":
return False
return True
Step 4: Invoke Workflow Engine
async def invoke_workflow_engine(workflow: WorkflowDefinition, trigger_request: GitHubTriggerRequest):
"""Invoke Workflow Engine to execute the workflow"""
# Prepare workflow execution context with GitHub data
execution_context = {
"workflow_id": workflow.id,
"trigger_type": "github",
"trigger_data": {
"event": trigger_request.event_type,
"action": trigger_request.github_payload.get("action"),
"repository": trigger_request.github_payload.get("repository"),
"sender": trigger_request.github_payload.get("sender"),
"payload": trigger_request.github_payload,
"timestamp": trigger_request.timestamp,
"delivery_id": trigger_request.delivery_id
}
}
# Call Workflow Engine
async with httpx.AsyncClient() as client:
response = await client.post(
f"{WORKFLOW_ENGINE_URL}/workflows/execute",
json={
"workflow_definition": workflow.to_dict(),
"execution_context": execution_context,
"priority": "normal"
},
headers={"Authorization": f"Bearer {INTERNAL_SERVICE_TOKEN}"}
)
if response.status_code == 200:
execution_result = response.json()
logger.info(f"Workflow {workflow.id} triggered successfully: {execution_result['execution_id']}")
else:
logger.error(f"Failed to execute workflow {workflow.id}: {response.text}")
3. Repository Data Access
GitHub API Client
class GitHubAppClient:
def __init__(self, app_id: str, private_key: str):
self.app_id = app_id
self.private_key = private_key
async def get_installation_token(self, installation_id: int) -> str:
"""Get short-lived access token for installation"""
jwt_token = self.generate_jwt()
async with httpx.AsyncClient() as client:
response = await client.post(
f"https://api.github.com/app/installations/{installation_id}/access_tokens",
headers={
"Authorization": f"Bearer {jwt_token}",
"Accept": "application/vnd.github.v3+json"
}
)
return response.json()["token"]
async def get_pull_request_diff(self, installation_id: int, repo: str, pr_number: int) -> str:
"""Get PR diff content"""
token = await self.get_installation_token(installation_id)
async with httpx.AsyncClient() as client:
response = await client.get(
f"https://api.github.com/repos/{repo}/pulls/{pr_number}",
headers={
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3.diff"
}
)
return response.text
async def get_file_content(self, installation_id: int, repo: str, path: str, ref: str = "main") -> str:
"""Get specific file content"""
token = await self.get_installation_token(installation_id)
async with httpx.AsyncClient() as client:
response = await client.get(
f"https://api.github.com/repos/{repo}/contents/{path}",
headers={
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json"
},
params={"ref": ref}
)
content_data = response.json()
if content_data["encoding"] == "base64":
return base64.b64decode(content_data["content"]).decode("utf-8")
return content_data["content"]
Repository Context Service
class GitHubRepositoryService:
"""Service for accessing repository data through GitHub App"""
async def get_pr_context(self, installation_id: int, repo: str, pr_number: int) -> dict:
"""Get comprehensive PR context for workflow"""
client = GitHubAppClient(app_id, private_key)
# Get PR details
pr_data = await client.get_pull_request(installation_id, repo, pr_number)
# Get diff
diff_content = await client.get_pull_request_diff(installation_id, repo, pr_number)
# Get changed files
changed_files = await client.get_pull_request_files(installation_id, repo, pr_number)
# Get comments if needed
comments = await client.get_pull_request_comments(installation_id, repo, pr_number)
return {
"pr": pr_data,
"diff": diff_content,
"files": changed_files,
"comments": comments,
"repository": await client.get_repository(installation_id, repo)
}
async def get_commit_context(self, installation_id: int, repo: str, commit_sha: str) -> dict:
"""Get commit context for push events"""
client = GitHubAppClient(app_id, private_key)
commit_data = await client.get_commit(installation_id, repo, commit_sha)
return {
"commit": commit_data,
"diff": commit_data["files"], # GitHub API includes diff in commit
"repository": await client.get_repository(installation_id, repo)
}
GitHub SDK Implementation
Location: apps/backend/shared/sdks/github_sdk/
The GitHub SDK provides a comprehensive interface for all GitHub App operations, including repository management, PR/issue operations, and code manipulation.
SDK Structure:
github_sdk/
├── __init__.py
├── client.py # Main GitHub SDK client
├── auth.py # JWT and token management
├── repositories.py # Repository operations
├── pulls.py # Pull request operations
├── issues.py # Issue operations
├── branches.py # Branch and code operations
├── webhooks.py # Webhook utilities
├── exceptions.py # Custom exceptions
├── models.py # Data models
├── requirements.txt # Dependencies
└── README.md # Usage documentation
4. Workflow Integration
Enhanced GitHub Trigger Node
class GitHubTriggerNode:
"""Enhanced trigger node with repository access capabilities"""
async def execute(self, context: WorkflowContext) -> dict:
# Standard trigger execution
trigger_data = await super().execute(context)
# Enhanced with repository access
installation_id = self.parameters["github_app_installation_id"]
if trigger_data["event"] == "pull_request":
pr_context = await self.github_service.get_pr_context(
installation_id,
trigger_data["repository"]["full_name"],
trigger_data["payload"]["number"]
)
trigger_data["pr_context"] = pr_context
elif trigger_data["event"] == "push":
# Get commit contexts for all commits in push
commit_contexts = []
for commit in trigger_data["payload"]["commits"]:
commit_context = await self.github_service.get_commit_context(
installation_id,
trigger_data["repository"]["full_name"],
commit["id"]
)
commit_contexts.append(commit_context)
trigger_data["commit_contexts"] = commit_contexts
return trigger_data
GitHub Action Nodes
Create specialized nodes for GitHub operations:
# Get PR Code Node
class GitHubGetPRCodeNode:
async def execute(self, input_data: dict) -> dict:
installation_id = self.parameters["installation_id"]
repo = self.parameters["repository"]
pr_number = input_data.get("pr_number") or self.parameters["pr_number"]
pr_context = await self.github_service.get_pr_context(
installation_id, repo, pr_number
)
return {
"pr_data": pr_context["pr"],
"diff": pr_context["diff"],
"files": pr_context["files"],
"comments": pr_context["comments"]
}
# Create PR Comment Node
class GitHubCreateCommentNode:
async def execute(self, input_data: dict) -> dict:
installation_id = self.parameters["installation_id"]
repo = self.parameters["repository"]
pr_number = input_data["pr_number"]
comment_body = input_data["comment"]
await self.github_service.create_pr_comment(
installation_id, repo, pr_number, comment_body
)
return {"success": True, "comment_created": True}
5. Security Considerations
Webhook Security
- Signature Verification: Always verify GitHub webhook signatures
- Rate Limiting: Implement rate limiting on webhook endpoints
- IP Allowlisting: Restrict to GitHub's webhook IP ranges
Access Token Management
- Short-lived Tokens: Use installation tokens (1 hour expiry)
- Minimal Permissions: Request only necessary permissions
- Token Rotation: Automatic rotation of installation tokens
Data Privacy
- Selective Access: Users control which repositories to connect
- Data Retention: Clear policies on webhook payload storage
- Encryption: Encrypt sensitive data at rest
6. Implementation Status & Plan
✅ Phase 1: Core Infrastructure (COMPLETED)
- ✅ GitHub App Registration: App configuration and credentials management
- ✅ Webhook Reception:
/api/v1/public/webhooks/github
endpoint with signature verification - ✅ Installation Flow:
/api/v1/public/webhooks/github/auth
callback with database storage - ✅ Database Schema: Using existing
oauth_tokens
andintegrations
tables - ✅ User Management API: Generic
/api/v1/app/integrations
endpoints
Key Implementation Details:
- Database: Leverages existing OAuth infrastructure instead of separate GitHub tables
- API Design: Generic integrations API supports GitHub, Slack, and future providers
- Authentication: Proper JWT-based access control for user data
- Dual Processing: Stores in database AND forwards to workflow_scheduler
- Error Handling: Graceful failure handling with detailed logging
🔄 Phase 2: Event Processing (IN PROGRESS)
- ✅ Event Routing: Forward GitHub webhooks to workflow_scheduler service
- ✅ Basic Filtering: Installation and repository-level filtering
- 🚧 GitHub Trigger Enhancements: Enhanced trigger nodes with repository context
- 🚧 Repository Context: GitHub API client for accessing repository data
📋 Phase 3: Advanced Features (PLANNED)
- Specialized GitHub Nodes: PR analysis, code review, issue management
- Advanced Filtering: Branch patterns, file paths, user/label filters
- Monitoring Dashboard: Installation analytics and webhook metrics
- User Interface: Frontend components for GitHub integration management
📋 Phase 4: Production Readiness (PLANNED)
- Security Audit: Comprehensive security review and penetration testing
- Performance Optimization: Rate limiting, caching, and scaling
- Documentation: User guides and developer documentation
- Onboarding Flows: Guided setup and integration tutorials
Current Implementation Architecture:
Frontend App → GitHub App Install → GitHub Callback → API Gateway
↓
User clicks User authorizes GitHub redirects Stores in DB
"Connect GitHub" repositories with installation +
data Forwards to
Scheduler
Ready for Integration:
- ✅ Frontend can initiate GitHub connections via GitHub App install URL
- ✅ Backend properly handles installation callbacks and stores user mappings
- ✅ Generic API allows frontend to display user's connected integrations
- ✅ Webhook processing forwards events to workflow scheduling system
7. Monitoring and Observability
Metrics to Track
- Webhook delivery success rates
- API rate limit usage
- Installation/uninstallation events
- Workflow trigger success rates
- Token refresh frequency
Logging Strategy
- Structured logging for all GitHub API calls
- Webhook payload logging (sanitized)
- Error tracking and alerting
- Performance monitoring
8. Production Deployment Strategy
Step 1: Infrastructure Setup
Domain & SSL Requirements:
Primary Domain: api.aiworkflowteams.com
Webhook Endpoint: api.aiworkflowteams.com/webhooks/github
Auth Callback: api.aiworkflowteams.com/api/v1/public/webhooks/github/auth
SSL Certificate: Required (Let's Encrypt or commercial)
AWS ECS Deployment Architecture:
# docker-compose.production.yml
services:
api-gateway:
image: aiworkflowteams/api-gateway:latest
environment:
- GITHUB_APP_ID=${GITHUB_APP_ID}
- GITHUB_APP_PRIVATE_KEY=${GITHUB_APP_PRIVATE_KEY}
- GITHUB_WEBHOOK_SECRET=${GITHUB_WEBHOOK_SECRET}
ports:
- "443:8000"
volumes:
- ./ssl:/etc/ssl/certs
github-processor:
image: aiworkflowteams/github-processor:latest
environment:
- GITHUB_APP_ID=${GITHUB_APP_ID}
- GITHUB_APP_PRIVATE_KEY=${GITHUB_APP_PRIVATE_KEY}
depends_on:
- redis
- postgres
Step 2: Environment Configuration
Production Environment Variables:
# GitHub App Configuration
GITHUB_APP_ID=123456
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n..."
GITHUB_WEBHOOK_SECRET=prod_webhook_secret_here
GITHUB_API_BASE_URL=https://api.github.com
# Database
DATABASE_URL=postgresql://user:pass@prod-db:5432/aiworkflow
REDIS_URL=redis://prod-redis:6379
# Security
JWT_SECRET=prod_jwt_secret
ENCRYPTION_KEY=prod_encryption_key
# Monitoring
SENTRY_DSN=https://...
DATADOG_API_KEY=...
Secret Management:
# AWS Secrets Manager
aws secretsmanager create-secret \
--name "github-app-private-key" \
--secret-string file://github-private-key.pem
# ECS Task Definition
{
"secrets": [
{
"name": "GITHUB_APP_PRIVATE_KEY",
"valueFrom": "arn:aws:secretsmanager:region:account:secret:github-app-private-key"
}
]
}
Step 3: Load Balancer & Scaling
Application Load Balancer Configuration:
# ALB Rules
- Path: /webhooks/github
Target: github-webhook-service
Health Check: /health
- Path: /auth/github/*
Target: auth-service
Health Check: /health
# Auto Scaling
Min Capacity: 2
Max Capacity: 20
Target CPU: 70%
Scale Out: 2 instances
Scale In: 1 instance
Rate Limiting Strategy:
# API Gateway Rate Limits
@app.middleware("http")
async def rate_limit_middleware(request: Request, call_next):
# GitHub webhook endpoints: 1000 req/min per IP
# Auth endpoints: 100 req/min per IP
# API endpoints: 500 req/min per user
pass
Step 4: Database Migration & Setup
Production Database Schema:
-- Run database migrations
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- GitHub installations table
CREATE TABLE github_installations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id),
installation_id BIGINT UNIQUE NOT NULL,
account_id BIGINT NOT NULL,
account_login TEXT NOT NULL,
account_type TEXT NOT NULL,
repositories JSONB,
permissions JSONB,
access_token_expires_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Indexes for performance
CREATE INDEX idx_github_installations_user_id ON github_installations(user_id);
CREATE INDEX idx_github_installations_installation_id ON github_installations(installation_id);
CREATE INDEX idx_github_installations_account_id ON github_installations(account_id);
-- GitHub events log (for debugging/monitoring)
CREATE TABLE github_webhook_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
delivery_id TEXT UNIQUE NOT NULL,
event_type TEXT NOT NULL,
installation_id BIGINT,
repository_id BIGINT,
payload JSONB,
processed_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
Step 5: Monitoring & Alerting
Health Checks:
@app.get("/health")
async def health_check():
checks = {
"database": await check_database_connection(),
"github_api": await check_github_api_access(),
"redis": await check_redis_connection()
}
if all(checks.values()):
return {"status": "healthy", "checks": checks}
else:
raise HTTPException(500, {"status": "unhealthy", "checks": checks})
Monitoring Metrics:
# CloudWatch/DataDog Metrics
- github.webhook.received (counter)
- github.webhook.processed (counter)
- github.webhook.failed (counter)
- github.api.rate_limit_remaining (gauge)
- github.installations.active (gauge)
- github.token.refresh_rate (counter)
- workflow.triggers.executed (counter)
Alerting Rules:
# Critical Alerts
- Webhook failure rate > 5%
- GitHub API rate limit < 100 remaining
- Database connection failures
- SSL certificate expiring in 30 days
# Warning Alerts
- High webhook processing latency (>2s)
- Installation uninstall rate spike
- Unusual API usage patterns
Step 6: CI/CD Pipeline
GitHub Actions Deployment:
# .github/workflows/deploy-production.yml
name: Deploy Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker Images
run: |
docker build -t aiworkflowteams/api-gateway:${{ github.sha }} .
docker build -t aiworkflowteams/github-processor:${{ github.sha }} ./processors/github
- name: Push to ECR
run: |
aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY
docker push aiworkflowteams/api-gateway:${{ github.sha }}
docker push aiworkflowteams/github-processor:${{ github.sha }}
- name: Deploy to ECS
run: |
aws ecs update-service --cluster prod --service github-integration --force-new-deployment
Step 7: Go-Live Checklist
Pre-Launch Verification:
- GitHub App created and configured in production
- SSL certificates installed and verified
- Webhook endpoints responding correctly
- Database migrations completed
- Environment variables configured
- Rate limiting and security measures active
- Monitoring and alerting configured
- Load testing completed
- Security audit completed
Launch Steps:
- Soft Launch: Enable for internal team first
- Beta Testing: Invite select users to test
- GitHub Marketplace: Submit app for review and listing
- Public Launch: Announce availability
- Monitor & Scale: Watch metrics and scale as needed
Post-Launch Actions:
- Monitor webhook delivery rates
- Track user installation patterns
- Gather user feedback for improvements
- Scale infrastructure based on usage
- Plan feature enhancements
Step 8: Operational Procedures
Incident Response:
# Webhook endpoint down
1. Check ALB health checks
2. Verify ECS service status
3. Check application logs
4. Scale up if needed
5. Alert GitHub if widespread issues
# Rate limit exceeded
1. Check current usage patterns
2. Implement request queuing
3. Contact GitHub for limit increase if needed
4. Optimize API usage patterns
Maintenance Windows:
- Schedule during low-usage hours (typically 2-6 AM UTC)
- Notify users via status page 24 hours in advance
- Implement rolling updates to minimize downtime
- Test rollback procedures before deployments
This comprehensive deployment strategy ensures the GitHub App can be reliably used by all users while maintaining high availability, security, and performance standards.