This directory contains the AWS Lambda adapter for the GitHub bot. Lambda is one of several deployment options - see the main README for alternatives like standard HTTP servers.
The Lambda adapter translates AWS-specific events into the unified
app.HandleRequest() interface:
- API Gateway (webhooks, status, config) →
app.Request{Type: HTTP} - EventBridge (scheduled sync) →
app.Request{Type: Scheduled}
# from repository root
make build-lambda
# creates dist/bootstrap (Lambda requires this exact name)- Runtime:
provided.al2023 - Handler:
bootstrap - Architecture:
x86_64 - Memory: 256 MB
- Timeout: 30 seconds
- IAM Role:
AWSLambdaBasicExecutionRole(no additional permissions needed)
Upload dist/bootstrap to your Lambda function via:
- AWS Console (function code upload)
- AWS CLI:
aws lambda update-function-code --function-name github-ops-app --zip-file fileb://dist/bootstrap.zip - Infrastructure as Code (Terraform, CDK, CloudFormation)
Set all required environment variables (see Configuration in main README).
Create an HTTP API Gateway:
- Create API: HTTP API (not REST API)
- Add Route:
POST /webhooks(orANY /{proxy+}for universal handler) - Integration: Lambda function (proxy integration enabled)
- Deploy: Note the invoke URL
- GitHub App: Set webhook URL to
https://<api-gateway-url>/webhooks
Headers: API Gateway automatically forwards all headers including
X-GitHub-Event and X-Hub-Signature-256.
Create EventBridge rules for each scheduled feature you use:
Okta Sync (sync Okta groups to GitHub teams):
- Rule Type: Schedule
- Schedule:
rate(1 hour)orrate(6 hours) - Target: Lambda function
- Input: Configure constant (JSON):
{
"source": "aws.events",
"detail-type": "Scheduled Event",
"detail": {
"action": "okta-sync"
}
}Security Alerts (report stale security alerts):
- Rule Type: Schedule
- Schedule:
rate(1 day)orcron(0 9 ? * MON *)(weekly Monday 9 AM) - Target: Lambda function
- Input: Configure constant (JSON):
{
"source": "aws.events",
"detail-type": "Scheduled Event",
"detail": {
"action": "security-alerts"
}
}The Lambda function uses a universal handler that detects event types and
converts them to the unified app.Request format:
func UniversalHandler(ctx context.Context, event json.RawMessage) (any, error)Supported Events:
APIGatewayV2HTTPRequest→ Converts toapp.Request{Type: HTTP}CloudWatchEvent(EventBridge) → Converts toapp.Request{Type: Scheduled}
All requests are then processed by app.HandleRequest() which routes based on
request type and path.
When invoked via API Gateway:
| Method | Path | Description |
|---|---|---|
| POST | /webhooks |
GitHub webhook receiver |
| POST | /scheduled/okta-sync |
Trigger Okta sync |
| POST | /scheduled/security-alerts |
Trigger security alerts check |
| POST | /scheduled/slack-test |
Send test notification to Slack |
| GET | /server/status |
Health check and feature flags |
| GET | /server/config |
Config inspection (secrets hidden) |
View logs:
aws logs tail /aws/lambda/your-function-name --followLambda automatically tracks:
- Invocations
- Duration
- Errors
- Throttles
Enable verbose logging:
aws lambda update-function-configuration \
--function-name github-ops-app \
--environment Variables="{APP_DEBUG_ENABLED=true,...}"Start with 256 MB and adjust based on CloudWatch metrics:
- Under-provisioned: Slow response times, timeouts
- Over-provisioned: Wasted cost
- Right-sized: <100ms execution time for webhooks, <5s for sync
- Webhooks: 15 seconds (GitHub timeout is 10s)
- Scheduled sync: 30-60 seconds (depends on org size)
Webhooks: Pay-per-use (only when events occur)
Scheduled Sync: Runs on schedule regardless of changes
- Hourly sync: ~730 invocations/month
- 6-hour sync: ~120 invocations/month
Cost Example (us-east-1, 256MB, 5s avg):
- Free tier: 1M requests, 400,000 GB-seconds/month
- Typical usage: <1000 invocations/month → free
Symptom: 401 unauthorized responses, logs show "webhook signature
validation failed"
Solutions:
- Verify
APP_GITHUB_WEBHOOK_SECRETmatches GitHub App settings - Check API Gateway forwards
X-Hub-Signature-256header - Ensure payload isn't modified by API Gateway (use proxy integration)
Symptom: No sync activity in logs
Solutions:
- Verify EventBridge rule is enabled
- Check rule target is configured correctly
- Verify input payload has correct structure
- Check Lambda has no concurrent execution limits
Symptom: Function execution exceeds configured timeout
Solutions:
- Increase timeout (max 15 minutes)
- Reduce Okta sync scope (fewer rules/groups)
- Check for slow API responses from GitHub/Okta
- Enable debug logging to identify bottleneck
Symptom: First webhook after idle period is slow
Solutions:
- Accept it (typically 100-500ms, GitHub webhooks tolerate this)
- Use Lambda provisioned concurrency (increases cost)
- Consider standard HTTP server for consistently low latency
To migrate to a standard HTTP server deployment:
- Build server:
make build-server - Deploy to VPS/container/K8s
- Update GitHub webhook URL to new server
- Setup external cron for
/scheduled/okta-syncendpoint - Delete Lambda function and API Gateway
No code changes needed - the core app is deployment-agnostic.
Consider non-Lambda deployments if you:
- Need consistently low latency (<50ms)
- Want to avoid AWS vendor lock-in
- Prefer traditional server management
- Have existing container infrastructure
See main README for standard HTTP server deployment.