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.
- devs_webhook-0.1.0/LICENSE +21 -0
- devs_webhook-0.1.0/PKG-INFO +664 -0
- devs_webhook-0.1.0/README.md +607 -0
- devs_webhook-0.1.0/devs_webhook/__init__.py +21 -0
- devs_webhook-0.1.0/devs_webhook/app.py +321 -0
- devs_webhook-0.1.0/devs_webhook/cli/__init__.py +6 -0
- devs_webhook-0.1.0/devs_webhook/cli/worker.py +296 -0
- devs_webhook-0.1.0/devs_webhook/config.py +319 -0
- devs_webhook-0.1.0/devs_webhook/core/__init__.py +1 -0
- devs_webhook-0.1.0/devs_webhook/core/claude_dispatcher.py +420 -0
- devs_webhook-0.1.0/devs_webhook/core/container_pool.py +1109 -0
- devs_webhook-0.1.0/devs_webhook/core/deduplication.py +113 -0
- devs_webhook-0.1.0/devs_webhook/core/repository_manager.py +197 -0
- devs_webhook-0.1.0/devs_webhook/core/task_processor.py +286 -0
- devs_webhook-0.1.0/devs_webhook/core/test_dispatcher.py +448 -0
- devs_webhook-0.1.0/devs_webhook/core/webhook_config.py +16 -0
- devs_webhook-0.1.0/devs_webhook/core/webhook_handler.py +57 -0
- devs_webhook-0.1.0/devs_webhook/github/__init__.py +15 -0
- devs_webhook-0.1.0/devs_webhook/github/app_auth.py +226 -0
- devs_webhook-0.1.0/devs_webhook/github/client.py +472 -0
- devs_webhook-0.1.0/devs_webhook/github/models.py +424 -0
- devs_webhook-0.1.0/devs_webhook/github/parser.py +325 -0
- devs_webhook-0.1.0/devs_webhook/main_cli.py +386 -0
- devs_webhook-0.1.0/devs_webhook/sources/__init__.py +7 -0
- devs_webhook-0.1.0/devs_webhook/sources/base.py +24 -0
- devs_webhook-0.1.0/devs_webhook/sources/sqs_source.py +306 -0
- devs_webhook-0.1.0/devs_webhook/sources/webhook_source.py +82 -0
- devs_webhook-0.1.0/devs_webhook/utils/__init__.py +1 -0
- devs_webhook-0.1.0/devs_webhook/utils/async_utils.py +86 -0
- devs_webhook-0.1.0/devs_webhook/utils/github.py +43 -0
- devs_webhook-0.1.0/devs_webhook/utils/logging.py +34 -0
- devs_webhook-0.1.0/devs_webhook/utils/serialization.py +102 -0
- devs_webhook-0.1.0/devs_webhook.egg-info/PKG-INFO +664 -0
- devs_webhook-0.1.0/devs_webhook.egg-info/SOURCES.txt +43 -0
- devs_webhook-0.1.0/devs_webhook.egg-info/dependency_links.txt +1 -0
- devs_webhook-0.1.0/devs_webhook.egg-info/entry_points.txt +3 -0
- devs_webhook-0.1.0/devs_webhook.egg-info/requires.txt +31 -0
- devs_webhook-0.1.0/devs_webhook.egg-info/top_level.txt +1 -0
- devs_webhook-0.1.0/pyproject.toml +95 -0
- devs_webhook-0.1.0/setup.cfg +4 -0
- devs_webhook-0.1.0/tests/test_allowlist.py +226 -0
- devs_webhook-0.1.0/tests/test_authentication.py +192 -0
- devs_webhook-0.1.0/tests/test_authorized_users.py +228 -0
- devs_webhook-0.1.0/tests/test_single_queue.py +431 -0
- 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.
|