feat(docker-watcher): phase 6 - webhook handler

Secret UUID-based webhook endpoint for CI image push notifications.
Project/stage matching via glob patterns, auto-creation of unknown
projects from image inspection. Fix JSON response injection.
This commit is contained in:
2026-03-27 21:56:18 +03:00
parent 90be636d66
commit eef60a4302
9 changed files with 812 additions and 14 deletions
+4 -3
View File
@@ -163,7 +163,8 @@ func (h *Handler) handleWebhook(w http.ResponseWriter, r *http.Request) {
parsed, err := ParseImageRef(payload.Image)
if err != nil {
http.Error(w, fmt.Sprintf(`{"error":%q}`, err.Error()), http.StatusBadRequest)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
return
}
@@ -199,7 +200,7 @@ func (h *Handler) handleWebhook(w http.ResponseWriter, r *http.Request) {
log.Printf("[webhook] auto_deploy disabled for project %s stage %s, skipping deploy", project.Name, stage.Name)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{"status":"accepted","deploy":false,"project":"%s","stage":"%s"}`, project.Name, stage.Name)
json.NewEncoder(w).Encode(map[string]any{"status": "accepted", "deploy": false, "project": project.Name, "stage": stage.Name})
return
}
@@ -212,7 +213,7 @@ func (h *Handler) handleWebhook(w http.ResponseWriter, r *http.Request) {
log.Printf("[webhook] triggered deploy for project %s stage %s tag %s", project.Name, stage.Name, parsed.Tag)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{"status":"accepted","deploy":true,"project":"%s","stage":"%s","tag":"%s"}`, project.Name, stage.Name, parsed.Tag)
json.NewEncoder(w).Encode(map[string]any{"status": "accepted", "deploy": true, "project": project.Name, "stage": stage.Name, "tag": parsed.Tag})
}
// EnsureWebhookSecret checks whether a webhook secret exists in settings.