Skip to content

feat(controller): git push webhook for immediate reconcile (homelab B3)#136

Merged
astrojerms merged 1 commit into
mainfrom
feat/homelab-gitops-webhook
Jul 13, 2026
Merged

feat(controller): git push webhook for immediate reconcile (homelab B3)#136
astrojerms merged 1 commit into
mainfrom
feat/homelab-gitops-webhook

Conversation

@astrojerms

Copy link
Copy Markdown
Owner

Roadmap target B3, completing Area B (git-as-source / the DriftlessAF loop). Adds a push-triggered reconcile so a git push converges the controller immediately instead of waiting for the pull interval.

What

  • server.GitOpsWebhook — a POST-only HTTP endpoint that verifies GitHub's HMAC-SHA256 X-Hub-Signature-256 header (constant-time compare) against a configured secret, then fires an async pull+reconcile and returns 202 Accepted (webhooks want a fast ack). An empty secret disables verification (trusted-network mode). Threaded through the HTTP gateway exactly like the OIDC handler (nil = not mounted).
  • Repo.PullAndReconcile — extracted the ticker's pull + HEAD-advance detection + onChange into a shared method, so the webhook and the periodic pull take the identical path (StartPeriodicPull now delegates to it).
  • Config: manifests.gitops.pull.webhook.{enabled, secret, path} (default path /gitops/webhook).

Point a GitHub push webhook (content-type JSON, secret set) at https://<controller>/gitops/webhook and pushes reconcile in ~seconds.

Area B complete (B1–B3)

git is now a first-class source, not just a sink:

All opt-in; defaults unchanged. (PR-based change proposal is intentionally left to Argo per the design doc — openctl reconciles the infra-coupled layer it owns.)

Tests

Valid / bad / missing signature, non-POST rejection, unsigned-mode accept, and route mounting (custom path mounts; a nil / trigger-less handler does not). Gateway signature change rippled to one test + ServeHTTPGateway + main.go.

Adds a push-triggered reconcile so a git push converges the controller
immediately instead of waiting for the pull interval.

- server.GitOpsWebhook: a POST-only HTTP endpoint that verifies GitHub's
  HMAC-SHA256 X-Hub-Signature-256 header (constant-time compare) against a
  configured secret, then fires an async pull+reconcile and returns 202. An
  empty secret disables verification (trusted-network mode). Threaded through
  the HTTP gateway exactly like the OIDC handler (nil = not mounted).
- Repo.PullAndReconcile: extracted the ticker's pull + HEAD-advance-detection +
  onChange body into a shared method, so the webhook and the periodic pull take
  the identical path (StartPeriodicPull now delegates to it).
- Config: manifests.gitops.pull.webhook.{enabled, secret, path} (default path
  /gitops/webhook).

Completes Area B (git-as-source): remote commits pull+reconcile (B1), removed
files prune with guards (B2), a push webhook converges immediately (B3). All
opt-in.

Tests: valid/bad/missing signature, non-POST, unsigned mode, and route
mounting (custom path mounts; nil/trigger-less handler does not).

Target B3 of Homelab-completion.
@astrojerms astrojerms merged commit 66ab568 into main Jul 13, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant