gitFlow/cmd/gitflow
dimitar 68930b4a05 feat: M6 — webhook config + watch wiring
Wire the webhook dispatcher into configuration resolution and the watch
command so scan results are relayed to external services on every frame.

Config (internal/config):
- Config gains Webhooks []webhook.Config (yaml: "webhooks", mapstructure
  tags for viper compatibility; duration fields use mapstructure:"-" and
  are backfilled via fixWebhookDurations calling v.GetDuration)
- validateWebhook enforces: name non-empty, type in (slack|discord|
  generic), URL starts with http/https, rate_limit >= 1s, retry
  max_attempts <= 5, min_priority 0-2
- Dump includes the webhooks section

Watch command (cmd/gitflow):
- At startup, builds a webhook.Dispatcher from cfg.Webhooks
- After each scan frame, fires dispatchWebhooks in a goroutine so a slow
  webhook never blocks the scan interval
- dispatchWebhooks constructs a webhook.Payload from the scan result,
  computes changed repositories, and fans out via d.Dispatch; errors
  are printed to stderr

Config tests:
- Webhooks parse from YAML (type, URL, on_change_only, rate_limit,
  retry.backoff) with duration fixup verified
- Bad webhooks rejected: unknown type, empty URL, non-http URL,
  sub-second rate_limit

Verified: go build, go vet, go test -race (13 packages), gofmt clean.
2026-08-02 09:23:52 +02:00
..
main.go feat: phase 2 — CLI commands and configuration resolution 2026-08-02 08:38:55 +02:00
prompt.go feat: phase 5 — AI agent integration (OpenAI, Ollama, Anthropic) 2026-08-02 08:48:27 +02:00
root.go feat: M2 — TUI skeleton (bubbletea model/view/styles) 2026-08-02 09:08:10 +02:00
scan.go feat: phase 6 — polish: completions, notifications, themes, rules, docs 2026-08-02 08:52:50 +02:00
tui.go feat: M2 — TUI skeleton (bubbletea model/view/styles) 2026-08-02 09:08:10 +02:00
watch.go feat: M6 — webhook config + watch wiring 2026-08-02 09:23:52 +02:00