Skip to content

Add Zoom alert provider - #1349

Merged
matheuscscp merged 1 commit into
fluxcd:mainfrom
xchose:zoom-provider
Jul 22, 2026
Merged

Add Zoom alert provider#1349
matheuscscp merged 1 commit into
fluxcd:mainfrom
xchose:zoom-provider

Conversation

@xchose

@xchose xchose commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Fixes #434

Adds a zoom Provider type for sending Flux alerts to Zoom Team Chat via the Incoming Webhook chatbot. The generic provider cannot be used for this because Zoom expects a specific JSON payload shape.

Implementation

  • Events are posted with the rich full message format: the involved object (kind/name.namespace) as the head, severity as sub head, the event message as body text, and event metadata as key/value fields.
  • format=full is appended to the webhook URL unless the user already pinned a format query parameter.
  • The connection's verification token (Secret key token) is sent raw in the Authorization header, per Zoom's Incoming Webhook docs.
  • Proxy and TLS configuration from the Provider spec are respected; HTTP goes through the shared postMessage client.

Sample rendered payload:

{
  "content": {
    "head": {
      "text": "gitrepository/webapp.gitops-system",
      "sub_head": { "text": "info" }
    },
    "body": [
      { "type": "message", "text": "Fetched revision: main@sha1:..." },
      { "type": "fields", "items": [ { "key": "revision", "value": "main@sha1:..." } ] }
    ]
  }
}

Testing

  • internal/notifier/zoom_test.go: asserts payload structure, Authorization header, format=full query param, format preservation, and constructor validation against an httptest server.
  • Full make test (envtest suite) passes; make generate manifests api-docs tidy fmt vet leave a clean tree.

🤖 Generated with Claude Code

@matheuscscp

Copy link
Copy Markdown
Member

@xchose Looks good, but to merge this we need manual testing with a real Zoom account, with screenshots, etc.

@xchose

xchose commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Manual testing done with a real Zoom account (free tier, Team Chat enabled). ✅

Setup

  • Installed the Incoming Webhook chatbot from the Zoom App Marketplace.
  • Connected it to a Team Chat channel with /inc connect flux-test, which returns the endpoint URL and verification token.

Method

Ran a temporary Go test (in package notifier, this branch) that calls NewZoom(...) + zoom.Post(ctx, event) with a realistic Flux event. The provider's request was routed through a local pass-through proxy that logs the exact outbound request and forwards it unchanged to the real Zoom endpoint — so everything below (URL query, headers, payload) was produced by the provider code itself, not hand-crafted:

=== RUN   TestZoom_LiveSend
    PROVIDER REQUEST   POST /?format=full
    PROVIDER HEADER    Content-Type: application/json
    PROVIDER HEADER    Authorization: <redacted>
    PROVIDER PAYLOAD   {"content":{"head":{"text":"kustomization/podinfo.flux-system","sub_head":{"text":"info"}},"body":[{"type":"message","text":"Live test from notification-controller zoom-provider branch: reconciliation finished, applied revision main@sha1:abcdef12"},{"type":"fields","items":[{"key":"revision","value":"main@sha1:abcdef12"},{"key":"summary","value":"manual live-send test"}]}]}}
    ZOOM RESPONSE      200 OK in 487ms
    ZOOM RESPONSE BODY OK
    RESULT             zoom.Post returned nil error — Zoom accepted the message
--- PASS: TestZoom_LiveSend (0.49s)
PASS

Result in Zoom Team Chat

Head = involved object, sub head = severity, body = event message, fields = event metadata, as described in the PR:

Error path

Also verified error handling against the real API: after revoking the webhook connection (/inc disconnect), Zoom returns 404 Connection not found, which the provider correctly surfaces:

postMessage failed: request failed: request failed with status code 404: Connection not found
zoom-provider-proof

@matheuscscp

matheuscscp commented Jul 22, 2026

Copy link
Copy Markdown
Member

Ran a temporary Go test (in package notifier, this branch) that calls NewZoom(...) + zoom.Post(ctx, event)

Sorry to be a pain here @xchose, but AI tends to do this kind of shallow testing. We need an e2e manual test.

To accept new providers here in notification-controller, we normally ask contributors to: create a kind cluster in your computer, install Flux inside, update notification-controller with an image built from this PR, update the CRD with the changes from this PR as well, and we need to see an e2e test of the feature with screenshots.

@xchose

xchose commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

My testing at KIND cluster (in docker):

~ kind get clusters
flux-zoom-e2e~ kubectl cluster-info --context kind-flux-zoom-e2e
Kubernetes control plane is running at https://127.0.0.1:55575
CoreDNS is running at https://127.0.0.1:55575/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.~ kubectl get nodes -o wide
NAME                          STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION             CONTAINER-RUNTIME
flux-zoom-e2e-control-plane   Ready    control-plane   7m38s   v1.36.1   172.18.0.2    <none>        Debian GNU/Linux 13 (trixie)   6.12.76-linuxkit (arm64)   containerd://2.3.1
Screenshot 2026-07-22 at 7 26 34

notification-controller runs the image built from this PR

~ kubectl -n flux-system get deploy notification-controller -o jsonpath='{.spec.template.spec.containers[0].image}'
test/notification-controller:zoom-e2e~ kubectl -n flux-system get pods
NAME                                       READY   STATUS    RESTARTS   AGE
helm-controller-5f98857c49-twftc           1/1     Running   0          2m53s
kustomize-controller-5c867fd7bd-v5pg9      1/1     Running   0          2m53s
notification-controller-649bc89b74-k2vv7   1/1     Running   0          103s
source-controller-854fd9756d-25sbl         1/1     Running   0          2m53s

Built with make docker-build IMG=test/notification-controller:zoom-e2e from this branch and loaded via kind load docker-image.

CRD from this PR accepts type: zoom

Applied config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml from this branch — the Provider validates and is reconciled (the stock CRD enum rejects zoom):

~ kubectl get crd providers.notification.toolkit.fluxcd.io -o yaml | grep zoom
                - zoom~ kubectl -n flux-system get provider zoom -o jsonpath='{.spec}'
{"secretRef":{"name":"zoom-webhook"},"type":"zoom"}

Events dispatched end-to-end (info, error, recovery)

Used a podinfo GitRepository as event source; triggered an info event (reconcile), an error event (nonexistent branch), and a recovery event (branch restored):

~ kubectl -n flux-system logs deploy/notification-controller | grep dispatch
{"level":"info","ts":"2026-07-22T05:03:47.614Z","logger":"event-server","msg":"dispatching event",...,"message":"stored artifact for commit 'Merge pull request #505 from stefanprodan/dependab...'"}
{"level":"info","ts":"2026-07-22T05:04:08.853Z","logger":"event-server","msg":"dispatching event",...,"message":"failed to checkout and determine revision: unable to clone 'https://github.com/stefanprodan/podinfo': couldn't find remote ref \"refs/heads/does-not-exist\""}
{"level":"info","ts":"2026-07-22T05:04:44.777Z","logger":"event-server","msg":"dispatching event",...,"message":"stored artifact for commit 'master@sha1:46b93c870014ed9ee43488f0463b0f0744ac327c'"}

No notifier errors in the log — Zoom returned 2xx for all three POSTs, and all three messages arrived in the Zoom Team Chat channel (screenshot above) rendered in the full format: header gitrepository/podinfo.flux-system, severity as sub-head, revision metadata as fields.

Full Report of testing step by step:

ZOOM_E2E_REPORT.md


Thanks @matheuscscp for the support during testing! 🙏

@matheuscscp matheuscscp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 🚀

@matheuscscp
matheuscscp requested a review from stefanprodan July 22, 2026 05:32
@stefanprodan

Copy link
Copy Markdown
Member

@xchose can you please rebase with upstream main and force push.

Add the zoom Provider type for Zoom Team Chat. Events are posted to the Incoming Webhook chatbot endpoint using the rich full-format payload, with the verification token sent in the Authorization header.

Assisted-by: Claude Code/claude-fable-5
Signed-off-by: Chose Carreras <xchose@gmail.com>
@stefanprodan stefanprodan added enhancement New feature or request area/alerting Alerting related issues and PRs labels Jul 22, 2026

@stefanprodan stefanprodan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Thanks @xchose

@matheuscscp
matheuscscp merged commit c52f594 into fluxcd:main Jul 22, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/alerting Alerting related issues and PRs enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Zoom as an Alert Provider

3 participants