Commands icon
ZulipIncomingWebhook icon
Webhook icon

Announce deployment results to Zulip

Trigger a serialized deploy chain via a Kestra webhook and announce the validated result to a Zulip stream with retry.

Categories
Business

This flow wraps a deployment in an announcement loop. An external system (CI, a release tool, a chatops command) calls a Kestra webhook to start the flow. A shell deploy step applies the change, captures the rolled-out revision, and derives its result from the real command exit code, then ZulipIncomingWebhook announces the result (service, version, environment, revision, status) to the engineering stream. A flow-level errors handler posts a separate failure notice if the deploy step exits non-zero, so the stream always reflects the true outcome.

The deploy step shown here is a runnable stand-in: it echoes the steps, emits a revision, and exits non-zero when the fail_deploy input is true, so you can exercise both the success and failure announcement paths before wiring in your real rollout. Replace the commands with your real rollout (for example kubectl apply and kubectl rollout status, an argocd app sync, or a helm upgrade), keeping the final ::{...}:: outputs line so the announcement can reference the revision and result. The base image is pinned to ubuntu:24.04; your real rollout needs an image (or a task runner) that actually contains your deploy CLI, since stock Ubuntu ships none of them.

Safety and operability

  • concurrency: { limit: 1 } serializes the flow so two CI calls (or a caller's retry storm) cannot start overlapping deploys of the same service at once; concurrent webhook calls queue instead of racing. For per-service isolation, split into per-service flows or add labels and a queue key.
  • service and environment are SELECT inputs and version is constrained by a validator regex, so a sloppy CI variable or a hostile webhook body cannot put arbitrary content into the channel that engineers trust as deployment truth.
  • Every value interpolated into the Zulip payload is passed through | toJson, so even if an input slips past validation, a stray quote or newline cannot break the JSON or inject markdown.
  • The deploy task has a timeout (PT15M) so a hung rollout status cannot wedge a worker indefinitely, and both Zulip tasks carry a retry. Note that ZulipIncomingWebhook does not raise on a non-200 response, so a lost success message does not by itself mean the deploy failed; confirm against the Kestra execution state.

How it works

  • io.kestra.plugin.core.trigger.Webhook starts the flow when your release pipeline POSTs to the webhook URL with the secret key.
  • deploy (shell) runs the rollout, exits non-zero on failure, and on success prints a Kestra outputs line exposing revision and result.
  • announce renders those values plus the inputs into a markdown payload and POSTs it to Zulip on success.
  • announce_failure posts a failure message if any task in the flow fails.

Prerequisites

  • A Kestra instance able to run Docker-based script tasks and reach your deployment target.
  • A release pipeline or operator that can POST to the Kestra webhook trigger URL.
  • A Zulip organization with an Incoming Webhook integration for the engineering stream.
  • The Zulip webhook URL and the trigger key stored as Kestra secrets.

Secrets

  • ZULIP_WEBHOOK: the full Zulip incoming webhook URL, including the integration path and API key, in the form https://yourZulipDomain.zulipchat.com/api/v1/external/INTEGRATION_NAME?api_key=API_KEY. Used by both ZulipIncomingWebhook tasks to post to the stream.
  • DEPLOY_WEBHOOK_KEY: the secret key segment for the Kestra Webhook trigger. The caller must include it in the trigger URL so only authorized systems can start the deploy.

Quick start

  1. Create an Incoming Webhook integration in Zulip and copy its URL; store it as the ZULIP_WEBHOOK secret.
  2. Choose a random key value, store it as DEPLOY_WEBHOOK_KEY, and build the trigger URL https://<your-kestra>/api/v1/executions/webhook/company.platform/zulip-deployment-notification/<DEPLOY_WEBHOOK_KEY>.
  3. Add your service names to the service SELECT and replace the shell commands with your real deployment commands on an image that contains your deploy CLI.
  4. Have your CI or operator POST to the trigger URL (optionally with a JSON body to override the service, version, and environment inputs).
  5. Confirm a success message lands in the engineering stream, then start a run with fail_deploy: true to confirm the failure path.

Expected outputs

  • {{ outputs.deploy.vars.revision }} and {{ outputs.deploy.vars.result }} carry the rollout details into the announcement.
  • Both Zulip tasks are notification tasks and produce no internal-storage artifact, so there is no {{ outputs.announce.uri }}. Success is a message in the engineering stream plus a SUCCESS state on the announcing task.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.