-
Notifications
You must be signed in to change notification settings - Fork 1
Pipeline Plan 23
The plan has been fully developed. Here's the implementation plan:
The webhook system bridges GitHub's push-based events with Shipwright's existing poll-based daemon. The dashboard server (Bun/TypeScript) receives GitHub webhook POSTs at /api/webhook/github, validates HMAC-SHA256 signatures, and writes validated issues.labeled events to a trigger file. The daemon's poll loop detects trigger files and runs an immediate poll, reducing latency from 0-30s to sub-second. Polling remains as the fallback when webhooks aren't configured.
Key design decision: The dashboard already runs an HTTP server with the /api/webhook/ci pattern. Adding /api/webhook/github here avoids a separate server. Daemon-dashboard communication uses the filesystem (same pattern as daemon-pause.flag).
| File | Action | Purpose |
|---|---|---|
scripts/sw-webhook-test.sh |
Create | Test suite for webhook trigger handling + CLI flag |
dashboard/server.ts |
Modify | Add /api/webhook/github + /api/webhook/status endpoints |
scripts/sw-daemon.sh |
Modify | Trigger file detection, --webhook flag, config loading |
scripts/sw-daemon-test.sh |
Modify | Add webhook config + trigger tests |
.claude/CLAUDE.md |
Modify | Document webhook configuration |
-
Daemon config schema — Add
webhook.secretandwebhook.dashboard_urltoload_config()(line ~362) and defaults (line ~207) -
Init template — Add
"webhook": { "secret": null, "dashboard_url": null }todaemon_init()heredoc (line ~4521) -
daemon init --webhook— Newdaemon_init_webhook()function: generates secret viaopenssl rand -hex 32, creates GitHub webhook viagh api repos/{owner}/{repo}/hooks, writes secret to config -
HMAC validation —
validateWebhookSignature()inserver.tsusing Web Crypto API with constant-time comparison -
POST /api/webhook/github— Public endpoint: validate signature, filterissues.labeledevents matchingwatch_label, write trigger file to~/.shipwright/webhook-triggers/<issue>.json, log delivery, broadcast to WS -
GET /api/webhook/status— Protected endpoint returning delivery history and stats fromwebhook-deliveries.jsonl -
FleetState webhook field — Add
webhooktoFleetStateinterface, populate from delivery log ingetFleetState() -
daemon_check_webhook_triggers()— Checks~/.shipwright/webhook-triggers/for files, removes them, callsdaemon_poll_issues - Poll loop integration — Call trigger check every second inside the existing 1-second sleep loop (line ~4197)
-
Test suite —
sw-webhook-test.sh+ additions tosw-daemon-test.sh -
Help text + docs — Update
show_help(), CLAUDE.md, register test inpackage.json -
Run
npm test— Ensure all 22+ test suites pass
- Task 1: Add webhook config fields to
load_config()and defaults - Task 2: Add webhook section to
daemon_init()generated config - Task 3: Implement
daemon_init_webhook()+--webhookCLI flag - Task 4: Add HMAC-SHA256 validation function in
server.ts - Task 5: Implement
POST /api/webhook/githubendpoint - Task 6: Implement
GET /api/webhook/statusendpoint - Task 7: Add webhook to
FleetStateinterface +getFleetState() - Task 8: Implement
daemon_check_webhook_triggers()insw-daemon.sh - Task 9: Integrate trigger checking into daemon poll loop sleep
- Task 10: Create
scripts/sw-webhook-test.sh - Task 11: Add webhook tests to
sw-daemon-test.sh - Task 12: Update help text, CLAUDE.md,
package.json - Task 13: Run full test suite and fix failures
-
/api/webhook/githubaccepts GitHub webhook payloads with HMAC-SHA256 validation -
issues.labeledevents matchingwatch_labeltrigger instant daemon polling (< 1s) - Polling continues as fallback when webhook is not configured
-
shipwright daemon init --webhookauto-configures GitHub webhook viagh api -
/api/webhook/statusshows delivery history and latency - New test suite passes + all 22 existing suites pass
- Bash 3.2 compatible throughout