devs-webhook 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. devs_webhook-0.1.0/LICENSE +21 -0
  2. devs_webhook-0.1.0/PKG-INFO +664 -0
  3. devs_webhook-0.1.0/README.md +607 -0
  4. devs_webhook-0.1.0/devs_webhook/__init__.py +21 -0
  5. devs_webhook-0.1.0/devs_webhook/app.py +321 -0
  6. devs_webhook-0.1.0/devs_webhook/cli/__init__.py +6 -0
  7. devs_webhook-0.1.0/devs_webhook/cli/worker.py +296 -0
  8. devs_webhook-0.1.0/devs_webhook/config.py +319 -0
  9. devs_webhook-0.1.0/devs_webhook/core/__init__.py +1 -0
  10. devs_webhook-0.1.0/devs_webhook/core/claude_dispatcher.py +420 -0
  11. devs_webhook-0.1.0/devs_webhook/core/container_pool.py +1109 -0
  12. devs_webhook-0.1.0/devs_webhook/core/deduplication.py +113 -0
  13. devs_webhook-0.1.0/devs_webhook/core/repository_manager.py +197 -0
  14. devs_webhook-0.1.0/devs_webhook/core/task_processor.py +286 -0
  15. devs_webhook-0.1.0/devs_webhook/core/test_dispatcher.py +448 -0
  16. devs_webhook-0.1.0/devs_webhook/core/webhook_config.py +16 -0
  17. devs_webhook-0.1.0/devs_webhook/core/webhook_handler.py +57 -0
  18. devs_webhook-0.1.0/devs_webhook/github/__init__.py +15 -0
  19. devs_webhook-0.1.0/devs_webhook/github/app_auth.py +226 -0
  20. devs_webhook-0.1.0/devs_webhook/github/client.py +472 -0
  21. devs_webhook-0.1.0/devs_webhook/github/models.py +424 -0
  22. devs_webhook-0.1.0/devs_webhook/github/parser.py +325 -0
  23. devs_webhook-0.1.0/devs_webhook/main_cli.py +386 -0
  24. devs_webhook-0.1.0/devs_webhook/sources/__init__.py +7 -0
  25. devs_webhook-0.1.0/devs_webhook/sources/base.py +24 -0
  26. devs_webhook-0.1.0/devs_webhook/sources/sqs_source.py +306 -0
  27. devs_webhook-0.1.0/devs_webhook/sources/webhook_source.py +82 -0
  28. devs_webhook-0.1.0/devs_webhook/utils/__init__.py +1 -0
  29. devs_webhook-0.1.0/devs_webhook/utils/async_utils.py +86 -0
  30. devs_webhook-0.1.0/devs_webhook/utils/github.py +43 -0
  31. devs_webhook-0.1.0/devs_webhook/utils/logging.py +34 -0
  32. devs_webhook-0.1.0/devs_webhook/utils/serialization.py +102 -0
  33. devs_webhook-0.1.0/devs_webhook.egg-info/PKG-INFO +664 -0
  34. devs_webhook-0.1.0/devs_webhook.egg-info/SOURCES.txt +43 -0
  35. devs_webhook-0.1.0/devs_webhook.egg-info/dependency_links.txt +1 -0
  36. devs_webhook-0.1.0/devs_webhook.egg-info/entry_points.txt +3 -0
  37. devs_webhook-0.1.0/devs_webhook.egg-info/requires.txt +31 -0
  38. devs_webhook-0.1.0/devs_webhook.egg-info/top_level.txt +1 -0
  39. devs_webhook-0.1.0/pyproject.toml +95 -0
  40. devs_webhook-0.1.0/setup.cfg +4 -0
  41. devs_webhook-0.1.0/tests/test_allowlist.py +226 -0
  42. devs_webhook-0.1.0/tests/test_authentication.py +192 -0
  43. devs_webhook-0.1.0/tests/test_authorized_users.py +228 -0
  44. devs_webhook-0.1.0/tests/test_single_queue.py +431 -0
  45. devs_webhook-0.1.0/tests/test_webhook_parser.py +178 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Dan Lester
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,664 @@
1
+ Metadata-Version: 2.4
2
+ Name: devs-webhook
3
+ Version: 0.1.0
4
+ Summary: GitHub webhook handler for automated devcontainer operations with Claude Code
5
+ Author: Dan Lester
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/ideonate/devs
8
+ Project-URL: Repository, https://github.com/ideonate/devs
9
+ Project-URL: Issues, https://github.com/ideonate/devs/issues
10
+ Project-URL: Documentation, https://github.com/ideonate/devs/tree/main/packages/webhook
11
+ Keywords: webhook,github,devcontainer,claude,automation
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Web Environment
14
+ Classifier: Framework :: FastAPI
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: fastapi>=0.68.0
29
+ Requires-Dist: uvicorn[standard]>=0.15.0
30
+ Requires-Dist: pydantic>=2.0.0
31
+ Requires-Dist: pydantic-settings>=2.0.0
32
+ Requires-Dist: httpx>=0.24.0
33
+ Requires-Dist: GitPython>=3.1.0
34
+ Requires-Dist: PyGithub>=1.55.0
35
+ Requires-Dist: cryptography>=3.4.0
36
+ Requires-Dist: PyJWT>=2.0.0
37
+ Requires-Dist: structlog>=21.1.0
38
+ Requires-Dist: tenacity>=8.0.0
39
+ Requires-Dist: click>=8.0.0
40
+ Requires-Dist: devs-common>=0.1.0
41
+ Provides-Extra: sqs
42
+ Requires-Dist: boto3>=1.18.0; extra == "sqs"
43
+ Provides-Extra: all
44
+ Requires-Dist: boto3>=1.18.0; extra == "all"
45
+ Provides-Extra: dev
46
+ Requires-Dist: pytest>=6.0; extra == "dev"
47
+ Requires-Dist: pytest-cov; extra == "dev"
48
+ Requires-Dist: pytest-asyncio; extra == "dev"
49
+ Requires-Dist: black; extra == "dev"
50
+ Requires-Dist: mypy; extra == "dev"
51
+ Requires-Dist: flake8; extra == "dev"
52
+ Requires-Dist: httpx; extra == "dev"
53
+ Requires-Dist: boto3>=1.18.0; extra == "dev"
54
+ Requires-Dist: build>=0.10.0; extra == "dev"
55
+ Requires-Dist: twine>=4.0.0; extra == "dev"
56
+ Dynamic: license-file
57
+
58
+ # devs-webhook - GitHub Webhook Handler
59
+
60
+ A GitHub webhook handler that automatically responds to @mentions in issues and pull requests using Claude Code to analyze and solve problems in devcontainers.
61
+
62
+ ## Features
63
+
64
+ - **Smart @mention Detection**: Responds when a configured user is @mentioned in GitHub issues/PRs
65
+ - **Multiple Task Sources**: Support for direct webhook reception (FastAPI) or polling from AWS SQS queues
66
+ - **Container Pool Management**: Manages a pool of named devcontainers (eamonn, harry, darren by default)
67
+ - **Claude Code Integration**: Uses Claude Code SDK to analyze issues and implement solutions
68
+ - **GitHub Checks API CI**: Automated test execution on push/PR events with status reporting
69
+ - **Environment Variable Management**: Layered DEVS.yml configuration with user-specific overrides
70
+ - **Repository Management**: Automatically clones and caches GitHub repositories
71
+ - **Automated Responses**: Creates pull requests, commits changes, and comments back on issues
72
+ - **Scalable Architecture**: Deploy as a single server or scale horizontally with SQS-based worker pools
73
+
74
+ ## Quick Start
75
+
76
+ ### Installation
77
+
78
+ ```bash
79
+ # Install the webhook package
80
+ cd packages/webhook
81
+ pip install -e .
82
+
83
+ # Or install from the monorepo root
84
+ pip install -e packages/webhook/
85
+ ```
86
+
87
+ ### Configuration
88
+
89
+ Set up environment variables:
90
+
91
+ ```bash
92
+ # Required settings
93
+ export GITHUB_WEBHOOK_SECRET="your-webhook-secret"
94
+ export GITHUB_TOKEN="ghp_your-github-token"
95
+ export GITHUB_MENTIONED_USER="your-github-username"
96
+ export CLAUDE_API_KEY="your-claude-api-key"
97
+
98
+ # Admin authentication (required for production)
99
+ export ADMIN_USERNAME="admin" # Default: admin
100
+ export ADMIN_PASSWORD="your-secure-password" # Required in production
101
+
102
+ # Access control settings
103
+ export ALLOWED_ORGS="myorg,anotherorg" # GitHub orgs allowed to use webhook
104
+ export ALLOWED_USERS="user1,user2" # GitHub users allowed to use webhook
105
+ export AUTHORIZED_TRIGGER_USERS="danlester,admin" # Users who can trigger processing
106
+
107
+ # Optional settings (with defaults)
108
+ export CONTAINER_POOL="eamonn,harry,darren"
109
+ export CONTAINER_TIMEOUT_MINUTES="30"
110
+ export MAX_CONCURRENT_TASKS="3"
111
+ export WEBHOOK_HOST="0.0.0.0"
112
+ export WEBHOOK_PORT="8000"
113
+ ```
114
+
115
+ ### Start the Server
116
+
117
+ ```bash
118
+ # Start webhook server (default mode)
119
+ devs-webhook serve
120
+
121
+ # Or with custom options
122
+ devs-webhook serve --host 127.0.0.1 --port 8080 --reload
123
+
124
+ # Start in SQS polling mode for scalable deployments
125
+ export TASK_SOURCE=sqs
126
+ export AWS_SQS_QUEUE_URL="https://sqs.us-east-1.amazonaws.com/123456789/devs-webhook-queue"
127
+ devs-webhook serve --source sqs
128
+ ```
129
+
130
+ ## Deployment Options
131
+
132
+ ### Webhook Mode (Default)
133
+
134
+ Direct webhook reception using FastAPI. Suitable for:
135
+ - Simple VPS deployments
136
+ - Single-server setups
137
+ - Low to moderate traffic
138
+
139
+ ```bash
140
+ # GitHub Webhook → devs-webhook server (FastAPI) → Container Pool
141
+ export TASK_SOURCE=webhook # or omit (default)
142
+ devs-webhook serve
143
+ ```
144
+
145
+ ### SQS Mode (Scalable)
146
+
147
+ Decoupled architecture using AWS SQS. Suitable for:
148
+ - High-traffic scenarios
149
+ - Multiple worker instances
150
+ - Better fault tolerance and retry logic
151
+
152
+ ```bash
153
+ # GitHub Webhook → Lambda/API Gateway → SQS Queue → devs-webhook workers
154
+ export TASK_SOURCE=sqs
155
+ export AWS_SQS_QUEUE_URL="https://sqs.us-east-1.amazonaws.com/..."
156
+ devs-webhook serve --source sqs
157
+ ```
158
+
159
+ **Security**: Both modes validate GitHub webhook signatures for defense-in-depth security.
160
+
161
+ For detailed configuration and deployment guides, see:
162
+ - [Task Sources Documentation](docs/TASK_SOURCES.md) - Complete guide to webhook vs SQS modes
163
+ - [Lambda Example](examples/sqs_webhook_forwarder.py) - Example Lambda function for SQS forwarding
164
+
165
+ ## How It Works
166
+
167
+ 1. **GitHub Webhook**: Receives webhook events from GitHub when issues/PRs are created or commented on
168
+ 2. **@mention Detection**: Checks if the configured user is @mentioned in the content
169
+ 3. **Container Allocation**: Allocates an available container from the pool (eamonn, harry, darren)
170
+ 4. **Repository Setup**: Clones/updates the repository and sets up the devcontainer workspace
171
+ 5. **Claude Code Execution**: Uses Claude Code SDK to analyze the issue and implement solutions
172
+ 6. **Automated Response**: Comments back on the issue/PR with results, creates PRs if needed
173
+
174
+ ## Usage Examples
175
+
176
+ ### Basic Issue Resolution
177
+
178
+ Create a GitHub issue:
179
+
180
+ ```
181
+ There's a bug in the user authentication system where passwords aren't being validated properly.
182
+
183
+ @your-username can you take a look at this?
184
+ ```
185
+
186
+ The webhook will:
187
+
188
+ 1. Detect the @mention
189
+ 2. Allocate a container
190
+ 3. Clone the repository
191
+ 4. Use Claude Code to analyze the auth system
192
+ 5. Implement a fix
193
+ 6. Create a pull request
194
+ 7. Comment back with the solution
195
+
196
+ ### Feature Requests
197
+
198
+ Create an issue:
199
+
200
+ ```
201
+ Can we add a dark mode toggle to the settings page?
202
+
203
+ @your-username please implement this feature.
204
+ ```
205
+
206
+ Claude Code will:
207
+
208
+ 1. Analyze the current UI structure
209
+ 2. Implement the dark mode functionality
210
+ 3. Create appropriate tests
211
+ 4. Submit a pull request
212
+ 5. Update the original issue
213
+
214
+ ## Container Pool
215
+
216
+ The webhook manages a pool of named containers:
217
+
218
+ - **eamonn**: First container in rotation
219
+ - **harry**: Second container in rotation
220
+ - **darren**: Third container in rotation
221
+
222
+ Each container:
223
+
224
+ - Gets a fresh workspace copy of the repository
225
+ - Has a 30-minute timeout (configurable)
226
+ - Is automatically cleaned up after use
227
+ - Can handle one task at a time
228
+
229
+ ## CLI Commands
230
+
231
+ ```bash
232
+ # Start the webhook server
233
+ devs-webhook serve
234
+
235
+ # Check server status
236
+ devs-webhook status
237
+
238
+ # View configuration
239
+ devs-webhook config
240
+
241
+ # Stop a specific container
242
+ devs-webhook stop-container eamonn
243
+
244
+ # Test setup and dependencies
245
+ devs-webhook test-setup
246
+ ```
247
+
248
+ ## API Endpoints
249
+
250
+ - `POST /webhook` - GitHub webhook endpoint
251
+ - `GET /health` - Health check
252
+ - `GET /status` - Detailed status information
253
+ - `GET /containers` - List container status
254
+ - `POST /container/{name}/stop` - Stop specific container
255
+
256
+ ## GitHub Webhook Setup
257
+
258
+ 1. Go to your repository Settings → Webhooks
259
+ 2. Add webhook with URL: `https://your-domain.com/webhook`
260
+ 3. Set Content Type: `application/json`
261
+ 4. Set Secret: Use your `GITHUB_WEBHOOK_SECRET`
262
+ 5. Select events: Issues, Pull requests, Issue comments, Pull request reviews
263
+
264
+ ## Dependencies
265
+
266
+ - **Python 3.8+**: Runtime environment
267
+ - **Docker**: Container management
268
+ - **GitHub CLI**: `gh` command for GitHub operations
269
+ - **DevContainer CLI**: `devcontainer` command for container operations
270
+ - **Claude API Key**: For Claude Code SDK access
271
+
272
+ ## Architecture
273
+
274
+ ```
275
+ GitHub → Webhook → FastAPI → Container Pool → Claude Code → GitHub Response
276
+ ↓ ↓ ↓ ↓ ↓ ↓
277
+ Issue Parse Allocate Clone Repo Analyze & Comment/PR
278
+ Created Event Container & Setup Solve Issue Back
279
+ ```
280
+
281
+ ### Key Components
282
+
283
+ - **WebhookHandler**: Main orchestrator
284
+ - **ContainerPool**: Manages eamonn/harry/darren containers
285
+ - **RepositoryManager**: Clones and caches repositories
286
+ - **ClaudeDispatcher**: Executes tasks with Claude Code SDK
287
+ - **GitHubClient**: Handles GitHub API operations
288
+
289
+ ## Configuration
290
+
291
+ ### Repository Configuration (DEVS.yml)
292
+
293
+ Repositories can include a `DEVS.yml` file in their root directory to customize how the webhook handler interacts with them:
294
+
295
+ ```yaml
296
+ # DEVS.yml - Repository-specific configuration
297
+ default_branch: develop # Default branch name (default: main)
298
+ prompt_extra: | # Additional instructions for Claude
299
+ This project uses a specific code style:
300
+ - Always use tabs for indentation
301
+ - Keep functions under 50 lines
302
+ - Add JSDoc comments to all public functions
303
+ direct_commit: true # Commit directly to default branch instead of creating PRs
304
+ single_queue: true # Process all events for this repo sequentially in same container
305
+ prompt_override: | # Complete replacement for the default prompt (optional)
306
+ Custom prompt template here...
307
+ Available variables: {event_type}, {event_type_full}, {task_description},
308
+ {repo_name}, {workspace_path}, {github_username}
309
+ ci_enabled: true # Enable CI mode for push/PR events
310
+ ci_test_command: npm test # Command to run for CI tests
311
+ ci_branches: # Branches to run CI on
312
+ - main
313
+ - develop
314
+
315
+ env_vars: # Environment variables for containers
316
+ default: # Default values for all containers
317
+ NODE_ENV: production
318
+ API_URL: https://api.example.com
319
+ DEBUG: "false"
320
+
321
+ eamonn: # Container-specific overrides
322
+ DEBUG: "true"
323
+ EAMONN_SPECIAL: "enabled"
324
+
325
+ harry:
326
+ NODE_ENV: staging
327
+ API_URL: https://staging-api.example.com
328
+ ```
329
+
330
+ Available options:
331
+
332
+ - **`default_branch`**: The main branch name for the repository (e.g., `main`, `master`, `develop`)
333
+ - Used when pulling latest changes before starting work
334
+ - Default: `main`
335
+
336
+ - **`prompt_extra`**: Additional instructions appended to Claude's prompt
337
+ - Use for project-specific guidelines, coding standards, or constraints
338
+ - Can be multi-line using YAML's `|` syntax
339
+ - Default: empty string
340
+
341
+ - **`direct_commit`**: Whether to commit directly to the default branch
342
+ - When `true`, Claude will commit directly to the default branch instead of creating PRs
343
+ - When `false`, Claude will create feature branches and pull requests (default behavior)
344
+ - Only creates PRs if there would be merge conflicts
345
+ - Default: `false`
346
+
347
+ - **`single_queue`**: Process all events for this repository sequentially
348
+ - When `true`, all webhook events for this repository are processed by the same container in order
349
+ - Prevents conflicts when multiple events would modify the same files
350
+ - Useful for repositories where strict ordering is important
351
+ - Default: `false` (events can be processed in parallel by different containers)
352
+
353
+ - **`prompt_override`**: Complete replacement for the default prompt (advanced)
354
+ - Allows full customization of Claude's instructions
355
+ - Use Python string formatting with available variables
356
+ - Variables: `{event_type}`, `{event_type_full}`, `{task_description}`, `{repo_name}`, `{workspace_path}`, `{github_username}`
357
+ - Takes precedence over all other prompt settings
358
+ - Default: not set (uses standard prompt)
359
+
360
+ - **`ci_enabled`**: Enable continuous integration mode
361
+ - When `true`, webhook responds to push and PR events by running tests
362
+ - Tests are executed in containers and results reported via GitHub Checks API
363
+ - Default: `false`
364
+
365
+ - **`ci_test_command`**: Command to run for CI tests
366
+ - Shell command executed in container for CI test runs
367
+ - Should exit with code 0 for success, non-zero for failure
368
+ - Default: `runtests.sh`
369
+
370
+ - **`ci_branches`**: Branches to run CI on for push events
371
+ - List of branch names to trigger CI for push events
372
+ - PR events always trigger CI regardless of target branch
373
+ - Default: `["main", "master"]`
374
+
375
+ - **`env_vars`**: Environment variables for containers
376
+ - Supports `default` section for all containers and container-specific overrides
377
+ - Container-specific variables override defaults
378
+ - User-specific overrides can be configured via `~/.devs/envs/{org-repo}/DEVS.yml`
379
+ - Variables are passed to container during startup
380
+ - Default: empty
381
+
382
+ ### User-Specific Configuration
383
+
384
+ Users can override repository settings with their own DEVS.yml files:
385
+
386
+ ```bash
387
+ # Global defaults for all projects
388
+ mkdir -p ~/.devs/envs/default
389
+ cat > ~/.devs/envs/default/DEVS.yml << 'EOF'
390
+ env_vars:
391
+ default:
392
+ GLOBAL_SETTING: "user_preference"
393
+ MY_SECRET: "user_secret"
394
+ EOF
395
+
396
+ # Project-specific overrides (org-repo format)
397
+ mkdir -p ~/.devs/envs/myorg-myrepo
398
+ cat > ~/.devs/envs/myorg-myrepo/DEVS.yml << 'EOF'
399
+ env_vars:
400
+ eamonn:
401
+ DEBUG: "true"
402
+ LOCAL_SECRET: "dev_secret"
403
+ ci_enabled: true
404
+ ci_test_command: "npm run test:full"
405
+ EOF
406
+ ```
407
+
408
+ **Priority order for configuration:**
409
+ 1. `~/.devs/envs/{org-repo}/DEVS.yml` (user-specific project overrides)
410
+ 2. `~/.devs/envs/default/DEVS.yml` (user defaults)
411
+ 3. `{repo-root}/DEVS.yml` (repository configuration)
412
+
413
+ 📖 **[See ../../example-usage.md for detailed examples and scenarios](../../example-usage.md)**
414
+
415
+ The webhook handler automatically detects and uses these settings when processing tasks for the repository.
416
+
417
+ ### Environment Variables
418
+
419
+ | Variable | Default | Description |
420
+ | --------------------------- | ---------------------------- | ---------------------------------------- |
421
+ | `GITHUB_WEBHOOK_SECRET` | Required | GitHub webhook secret |
422
+ | `GITHUB_TOKEN` | Required | GitHub personal access token |
423
+ | `GITHUB_MENTIONED_USER` | Required | Username to watch for @mentions |
424
+ | `CLAUDE_API_KEY` | Required | Claude API key |
425
+ | `ALLOWED_ORGS` | (empty) | Comma-separated list of allowed GitHub orgs |
426
+ | `ALLOWED_USERS` | (empty) | Comma-separated list of allowed GitHub users |
427
+ | `AUTHORIZED_TRIGGER_USERS` | (empty - allows all) | Comma-separated list of users who can trigger events |
428
+ | `CONTAINER_POOL` | `eamonn,harry,darren` | Container names |
429
+ | `CONTAINER_TIMEOUT_MINUTES` | `30` | Container timeout |
430
+ | `MAX_CONCURRENT_TASKS` | `3` | Max parallel tasks |
431
+ | `REPO_CACHE_DIR` | `~/.devs-webhook/repos` | Repository cache |
432
+ | `WORKSPACE_DIR` | `~/.devs-webhook/workspaces` | Container workspaces |
433
+ | `WEBHOOK_HOST` | `0.0.0.0` | Server host |
434
+ | `WEBHOOK_PORT` | `8000` | Server port |
435
+
436
+ ### GitHub App Authentication (Optional)
437
+
438
+ For enhanced GitHub Checks API support, you can optionally configure GitHub App authentication. This provides better permissions and rate limits for API operations, especially when using the Checks API to report test results.
439
+
440
+ #### When to Use GitHub App Authentication
441
+
442
+ - **Enhanced Checks API**: GitHub Apps have better permissions for creating and updating check runs
443
+ - **Better Rate Limits**: GitHub Apps get higher API rate limits
444
+ - **Organization Repositories**: Required for some organization-level permissions
445
+ - **Better Security**: App-based authentication is more secure than personal tokens
446
+
447
+ If GitHub App authentication is not configured, the webhook will fall back to personal token authentication.
448
+
449
+ #### Setting Up a GitHub App
450
+
451
+ 1. **Create a GitHub App**:
452
+ - Go to GitHub Settings → Developer settings → GitHub Apps
453
+ - Click "New GitHub App"
454
+ - Fill in the app details:
455
+ - **App name**: `devs-webhook-your-org`
456
+ - **Homepage URL**: Your webhook server URL
457
+ - **Webhook URL**: `https://your-domain.com/webhook`
458
+ - **Webhook secret**: Use your `GITHUB_WEBHOOK_SECRET`
459
+
460
+ 2. **Configure Permissions**:
461
+ - **Repository permissions**:
462
+ - Contents: Read & Write
463
+ - Issues: Read & Write
464
+ - Pull requests: Read & Write
465
+ - Checks: Write
466
+ - Metadata: Read
467
+ - **Subscribe to events**:
468
+ - Issues
469
+ - Pull request
470
+ - Issue comments
471
+ - Pull request reviews
472
+ - Push (for CI features)
473
+
474
+ 3. **Generate Private Key**:
475
+ - In the app settings, scroll down to "Private keys"
476
+ - Click "Generate a private key"
477
+ - Download the `.pem` file
478
+
479
+ 4. **Install the App**:
480
+ - Go to the app's public page or your organization/account settings
481
+ - Install the app on the repositories you want to use
482
+ - Note the installation ID from the URL (e.g., `/installations/12345`)
483
+
484
+ #### Configuration
485
+
486
+ Add these environment variables to enable GitHub App authentication:
487
+
488
+ ```bash
489
+ # GitHub App authentication (optional)
490
+ export GITHUB_APP_ID="123456"
491
+ export GITHUB_APP_PRIVATE_KEY="/path/to/private-key.pem"
492
+ export GITHUB_APP_INSTALLATION_ID="12345" # Optional, can be auto-discovered
493
+
494
+ # Or provide private key content directly
495
+ export GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
496
+ MIIEowIBAAKCAQEA...
497
+ -----END RSA PRIVATE KEY-----"
498
+ ```
499
+
500
+ #### Environment Variables for GitHub App
501
+
502
+ | Variable | Default | Description |
503
+ | --------------------------- | ------------ | ---------------------------------------- |
504
+ | `GITHUB_APP_ID` | (empty) | GitHub App ID (e.g., 123456) |
505
+ | `GITHUB_APP_PRIVATE_KEY` | (empty) | Private key content or path to .pem file |
506
+ | `GITHUB_APP_INSTALLATION_ID` | (empty) | Installation ID (auto-discovered if empty) |
507
+
508
+ #### How It Works
509
+
510
+ When GitHub App authentication is configured:
511
+
512
+ 1. **Checks API Operations**: The webhook will use GitHub App authentication for creating and updating check runs, providing better permissions and reliability
513
+ 2. **Fallback Behavior**: If GitHub App authentication fails, the webhook automatically falls back to personal token authentication
514
+ 3. **Auto-Discovery**: If `GITHUB_APP_INSTALLATION_ID` is not provided, the webhook will automatically discover the installation ID for each repository
515
+ 4. **Selective Usage**: GitHub App auth is only used when beneficial (like Checks API), while other operations may still use personal tokens
516
+
517
+ #### Troubleshooting GitHub App Setup
518
+
519
+ - **"Installation not found"**: Ensure the app is installed on the repository
520
+ - **"Invalid private key"**: Verify the private key format and content
521
+ - **"Permission denied"**: Check the app has required permissions (Contents, Issues, Pull requests, Checks)
522
+ - **"App authentication failed"**: Verify the App ID and private key are correct
523
+
524
+ ## Deployment
525
+
526
+ ### Local Development
527
+
528
+ ```bash
529
+ # Install dependencies
530
+ pip install -e ".[dev]"
531
+
532
+ # Set environment variables
533
+ export GITHUB_WEBHOOK_SECRET="dev-secret"
534
+ # ... other vars
535
+
536
+ # Start with reload
537
+ devs-webhook serve --reload
538
+ ```
539
+
540
+ ### Production with Docker
541
+
542
+ ```bash
543
+ # Build image
544
+ docker build -t devs-webhook .
545
+
546
+ # Run container
547
+ docker run -d \
548
+ --name devs-webhook \
549
+ -p 8000:8000 \
550
+ -v /var/run/docker.sock:/var/run/docker.sock \
551
+ -e GITHUB_WEBHOOK_SECRET="your-secret" \
552
+ -e GITHUB_TOKEN="your-token" \
553
+ -e GITHUB_MENTIONED_USER="your-username" \
554
+ -e CLAUDE_API_KEY="your-key" \
555
+ devs-webhook
556
+ ```
557
+
558
+ ### Semi-permanent with nohup
559
+
560
+ ```bash
561
+ # Start in background
562
+ nohup devs-webhook serve &
563
+
564
+ # View logs
565
+ tail -f nohup.out
566
+
567
+ # Find and kill the process
568
+ ps aux | grep devs-webhook
569
+ kill <PID>
570
+ ```
571
+
572
+ ### Production with Systemd (Ubuntu/Debian)
573
+
574
+ For running as a system service on Ubuntu:
575
+
576
+ ```bash
577
+ # Install the webhook package
578
+ pip install -e packages/webhook/
579
+
580
+ # Use the systemd setup script
581
+ cd packages/webhook/systemd
582
+ ./setup-systemd.sh --user dan --working-dir /home/dan/Dev/devs --env-file /home/dan/Dev/devs/.env
583
+
584
+ # Manage the service
585
+ sudo systemctl start devs-webhook # Start service
586
+ sudo systemctl status devs-webhook # Check status
587
+ sudo journalctl -u devs-webhook -f # View logs
588
+ ```
589
+
590
+ See [`systemd/README.md`](systemd/README.md) for detailed systemd setup instructions.
591
+
592
+ ## Security
593
+
594
+ ### Access Control
595
+
596
+ The webhook handler implements multiple layers of access control:
597
+
598
+ 1. **Authorized Trigger Users** (`AUTHORIZED_TRIGGER_USERS`):
599
+ - Only users in this list can trigger webhook processing
600
+ - If empty, all users are allowed (backward compatibility)
601
+ - Prevents unauthorized users from triggering actions
602
+ - Example: `AUTHORIZED_TRIGGER_USERS="danlester,teamlead"`
603
+
604
+ 2. **Repository Allowlist** (`ALLOWED_ORGS` and `ALLOWED_USERS`):
605
+ - Restricts which repositories can use the webhook
606
+ - Checks repository owner against allowed organizations and users
607
+ - Both settings work together (any match allows access)
608
+ - Example: `ALLOWED_ORGS="mycompany"` and `ALLOWED_USERS="trusted-user"`
609
+
610
+ 3. **@mention Detection** (`GITHUB_MENTIONED_USER`):
611
+ - Only processes events where the configured user is @mentioned
612
+ - Prevents accidental or unwanted processing
613
+
614
+ ### Other Security Features
615
+
616
+ - **Webhook Signatures**: All webhooks are verified using HMAC signatures
617
+ - **Token Scope**: GitHub token should have minimal required permissions
618
+ - **Container Isolation**: Each task runs in an isolated devcontainer
619
+ - **Timeout Protection**: Containers automatically timeout and cleanup
620
+
621
+ ## Troubleshooting
622
+
623
+ ### Common Issues
624
+
625
+ 1. **"No containers available"**: All containers are busy, wait or increase pool size
626
+ 2. **"Repository clone failed"**: Check GitHub token permissions
627
+ 3. **"Claude Code execution failed"**: Check Claude API key and model availability
628
+ 4. **"Invalid webhook signature"**: Verify webhook secret matches
629
+
630
+ ### Debugging
631
+
632
+ ```bash
633
+ # Check configuration
634
+ devs-webhook config
635
+
636
+ # View server status
637
+ devs-webhook status
638
+
639
+ # Test dependencies
640
+ devs-webhook test-setup
641
+
642
+ # Check logs (when running with structured logging)
643
+ tail -f /var/log/devs-webhook.log
644
+ ```
645
+
646
+ ## Development
647
+
648
+ ```bash
649
+ # Install in development mode
650
+ pip install -e ".[dev]"
651
+
652
+ # Run tests
653
+ pytest
654
+
655
+ # Format code
656
+ black devs_webhook tests
657
+
658
+ # Type checking
659
+ mypy devs_webhook
660
+ ```
661
+
662
+ ## License
663
+
664
+ MIT License - see the main repository for details.