From c2aa026f6ce1c9e216b99d74f294fc133d5fcddd Mon Sep 17 00:00:00 2001 From: Claudomator Agent Date: Mon, 16 Mar 2026 05:08:00 +0000 Subject: feat: add GitHub webhook endpoint for automatic CI failure task creation Adds POST /api/webhooks/github that receives check_run and workflow_run events and creates a Claudomator task to investigate and fix the failure. - Config: new webhook_secret and [[projects]] fields in config.toml - HMAC-SHA256 validation when webhook_secret is configured - Ignores non-failure events (success, skipped, etc.) with 204 - Matches repo name to configured project dirs (case-insensitive) - Falls back to single project when no name match found - 11 new tests covering all acceptance criteria Co-Authored-By: Claude Sonnet 4.6 --- internal/api/server.go | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'internal/api/server.go') diff --git a/internal/api/server.go b/internal/api/server.go index 7988c4c..8a20349 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/thepeterstone/claudomator/internal/config" "github.com/thepeterstone/claudomator/internal/executor" "github.com/thepeterstone/claudomator/internal/notify" "github.com/thepeterstone/claudomator/internal/storage" @@ -47,6 +48,8 @@ type Server struct { notifier notify.Notifier apiToken string // if non-empty, required for WebSocket (and REST) connections elaborateLimiter *ipRateLimiter // per-IP rate limiter for elaborate/validate endpoints + webhookSecret string // HMAC-SHA256 secret for GitHub webhook validation + projects []config.Project // configured projects for webhook routing } // SetAPIToken configures a bearer token that must be supplied to access the API. @@ -59,6 +62,12 @@ func (s *Server) SetNotifier(n notify.Notifier) { s.notifier = n } +// SetGitHubWebhookConfig configures the GitHub webhook secret and project list. +func (s *Server) SetGitHubWebhookConfig(secret string, projects []config.Project) { + s.webhookSecret = secret + s.projects = projects +} + // SetWorkspaceRoot configures the root directory used by handleListWorkspaces. func (s *Server) SetWorkspaceRoot(path string) { s.workspaceRoot = path @@ -118,6 +127,7 @@ func (s *Server) routes() { s.mux.HandleFunc("GET /api/workspaces", s.handleListWorkspaces) s.mux.HandleFunc("GET /api/tasks/{id}/deployment-status", s.handleGetDeploymentStatus) s.mux.HandleFunc("GET /api/health", s.handleHealth) + s.mux.HandleFunc("POST /api/webhooks/github", s.handleGitHubWebhook) s.mux.Handle("GET /", http.FileServerFS(webui.Files)) } -- cgit v1.2.3