Skip to content

Commit 21697b1

Browse files
authored
Merge pull request #51 from Comfy-Org/sno-label-op-system
feat: implement long-running repository event monitoring system
2 parents e9f569e + e68c81e commit 21697b1

35 files changed

+2377
-38
lines changed

.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ [email protected]
1616
AUTH_ADMINS=[email protected]
1717

1818
SLACK_BOT_TOKEN="FILL_THIS_INTO_ .env.local"
19+
20+
# default port for GITHUB_WEBHOOK_PORT for webhook
21+
GITHUB_WEBHOOK_PORT=14215

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,10 @@ package-lock.json
5656
report
5757

5858
# bun crash dump
59-
core
59+
core
60+
61+
# gh-service sqlite cache
62+
gh-service/state.sqlite
63+
64+
**/*.sqlite
65+
**/*.sqlite-journal

CLAUDE.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Claude Development Notes
2+
3+
## General Development Flow for All Scripts
4+
5+
### Standard Development Pattern
6+
7+
1. **Install Dependencies**: Use `bun add <package>` for runtime deps, `bun add -d <package>` for dev deps
8+
2. **Create Implementation**: Write the main functionality in TypeScript
9+
3. **Add Testing**: Create `.spec.ts` files with comprehensive test coverage
10+
4. **Test Execution**: Use `bun <file.ts>` to run scripts directly with `if (import.meta.main)` blocks
11+
5. **Type Safety**: Ensure full TypeScript coverage and proper type definitions
12+
6. **Error Handling**: Handle errors gracefully and don't cache failed responses
13+
7. **Documentation**: Update CLAUDE.md with implementation details and usage examples
14+
15+
### Testing Standards
16+
17+
- **File Naming**: Use `.spec.ts` suffix for test files
18+
- **Mocking**: Mock external APIs and services to avoid real calls during tests
19+
- **Coverage Areas**: Test happy path, error cases, edge cases, concurrent scenarios
20+
- **Setup/Teardown**: Clean up resources (files, caches, etc.) in test lifecycle hooks
21+
22+
### Common Patterns
23+
24+
- **Caching**: Use Keyv with SQLite for persistent caching in `node_modules/.cache/Comfy-PR/`
25+
- **Configuration**: Store config in environment variables with sensible defaults
26+
- **Logging**: Use console.log sparingly, prefer structured logging for debugging
27+
- **File Organization**: Keep related functionality together, use clear module exports
28+
29+
### Repository Structure
30+
31+
- **`src/`**: Core utilities and shared functionality
32+
- **`app/tasks/`**: Specific task implementations
33+
- **`gh-service/`**: GitHub webhook service components
34+
- **`run/`**: Executable scripts and services
35+
- **Tests**: Co-located with source files using `.spec.ts` suffix
36+
37+
## Cached GitHub Client (ghc)
38+
39+
### Overview
40+
41+
Created a cached wrapper around the GitHub API client that transparently caches all API responses to improve performance and reduce API rate limiting.
42+
43+
### Implementation
44+
45+
- **File**: `src/ghc.ts`
46+
- **Cache Storage**: SQLite via Keyv in `node_modules/.cache/Comfy-PR/gh-cache.sqlite`
47+
- **Default TTL**: 5 minutes
48+
- **Cache Key Format**: `gh.{apiPath}({truncatedArgs})#{hash}`
49+
50+
### Key Features
51+
52+
1. **Transparent Caching**: Same interface as `gh` object, just import `ghc` instead
53+
2. **Smart Cache Keys**: Truncates long arguments but preserves full hash for accuracy
54+
3. **SQLite Storage**: Persistent cache across runs
55+
4. **Type Safety**: Maintains full TypeScript types from original GitHub client
56+
57+
### Usage
58+
59+
```typescript
60+
import { ghc } from "./src/ghc";
61+
62+
// Same as gh.repos.get() but with caching
63+
const repo = await ghc.repos.get({
64+
owner: "octocat",
65+
repo: "Hello-World",
66+
});
67+
68+
// Second call uses cache
69+
const cachedRepo = await ghc.repos.get({
70+
owner: "octocat",
71+
repo: "Hello-World",
72+
});
73+
```
74+
75+
### Cache Management
76+
77+
```typescript
78+
import { clearGhCache, getGhCacheStats } from "./src/ghc";
79+
80+
// Clear all cached data
81+
await clearGhCache();
82+
83+
// Get cache statistics
84+
const stats = await getGhCacheStats();
85+
```
86+
87+
### Testing
88+
89+
- **Test File**: `src/ghc.spec.ts`
90+
- **Coverage**: Cache hits/misses, error handling, concurrent requests, key generation
91+
- **Mocking**: Uses Jest mocks to avoid real API calls during tests
92+
93+
### Development Flow
94+
95+
1. Install dependencies: `bun add keyv @keyv/sqlite`
96+
2. Create cached wrapper with Proxy pattern
97+
3. Implement cache key generation with argument truncation
98+
4. Add comprehensive test suite
99+
5. Test with real API calls: `bun src/ghc.ts`
100+
101+
### Cache Key Examples
102+
103+
- Short args: `gh.repos.get({"owner":"octocat","repo":"Hello-World"})#b3117af2`
104+
- Long args: `gh.repos.get({"owner":"octocat","descripti...bbbbbbbbbb"})#4240f076`

WEBHOOK_SETUP.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# GitHub Repository Event Monitor - Webhook Setup
2+
3+
This system now supports both polling and real-time webhook-based monitoring.
4+
5+
## Quick Start
6+
7+
### Polling Mode (Default)
8+
9+
```bash
10+
bun run run/label-op.tsx
11+
```
12+
13+
### Webhook Mode (Real-time)
14+
15+
```bash
16+
# Set environment variables
17+
export USE_WEBHOOKS=true
18+
export GITHUB_WEBHOOK_SECRET=your-secure-secret-here
19+
export WEBHOOK_BASE_URL=https://your-domain.com # Your public URL
20+
21+
# Run the monitor
22+
bun run run/label-op.tsx
23+
```
24+
25+
## Webhook Setup Instructions
26+
27+
### 1. Environment Variables
28+
29+
- `USE_WEBHOOKS=true` - Enable webhook mode
30+
- `GITHUB_WEBHOOK_SECRET` - Secret for webhook security (recommended)
31+
- `WEBHOOK_BASE_URL` - Your public URL (for webhook endpoint)
32+
- `GH_TOKEN` - GitHub personal access token with repo permissions
33+
34+
### 2. Public URL Requirements
35+
36+
For webhooks to work, your server needs to be accessible from the internet:
37+
38+
- **Development**: Use ngrok, cloudflare tunnels, or similar
39+
- **Production**: Deploy to a cloud provider with a public domain
40+
41+
### 3. GitHub Permissions
42+
43+
The system will automatically attempt to create webhooks for repositories in `REPOLIST`. You need:
44+
45+
- Admin or write access to the repositories
46+
- GitHub token with `repo` permissions
47+
48+
### 4. Webhook Events Monitored
49+
50+
- Issues (opened, closed, labeled, etc.)
51+
- Pull Requests (opened, closed, merged, labeled, etc.)
52+
- Comments (issue comments, PR comments, review comments)
53+
- Labels (added, removed)
54+
55+
## Comparison: Polling vs Webhooks
56+
57+
| Feature | Polling (30s) | Webhooks |
58+
| ------------------ | ----------------- | ------------------- |
59+
| **Latency** | ~30 seconds | ~1 second |
60+
| **API Usage** | High (continuous) | Low (event-driven) |
61+
| **Setup** | Simple | Requires public URL |
62+
| **Reliability** | Always works | Depends on network |
63+
| **Resource Usage** | Higher | Lower |
64+
65+
## Troubleshooting
66+
67+
### Webhook Creation Failed
68+
69+
- Check GitHub token permissions
70+
- Ensure you have admin access to repositories
71+
- Verify the WEBHOOK_BASE_URL is publicly accessible
72+
73+
### Webhook Not Receiving Events
74+
75+
- Test the webhook endpoint: `curl -X POST http://your-url/webhook`
76+
- Check GitHub webhook delivery logs in repo settings
77+
- Verify webhook secret matches if configured
78+
79+
### Fallback Strategy
80+
81+
The system gracefully falls back to polling mode if webhook setup fails for any repository.

0 commit comments

Comments
 (0)