Webhook icon
Schedule icon
WorkingDirectory icon
Commands icon
Docker icon
Script icon
If icon
SlackIncomingWebhook icon
Log icon

Gate Breaking AsyncAPI Changes Before Consumers See Them

Compare a candidate AsyncAPI document against the blessed baseline and escalate removed channels or required payload fields before consumers see them.

Categories
Data

REST contracts grew pull request gates years ago, but an event stream still ships a dropped required field straight into production because nothing compares the new AsyncAPI document against the one consumers built against. This blueprint takes the candidate document from CI, materializes it beside the blessed baseline in a shared workspace, diffs every publish and subscribe payload channel by channel, and escalates removals through Slack with the verdict published as outputs.

How it works

  1. post_candidate_spec (io.kestra.plugin.core.trigger.Webhook, keyed with the ASYNCAPI_WEBHOOK_KEY secret) accepts the candidate document as a raw YAML body from CI; nightly_contract_check (io.kestra.plugin.core.trigger.Schedule, cron 0 7 * * *) ships disabled: true until an operator switches it on.
  2. spec_workspace (io.kestra.plugin.core.flow.WorkingDirectory) opens one shared directory. write_specs (io.kestra.plugin.scripts.shell.Commands on the Docker runner, image python:3.12-slim) writes the blessed baseline with one quoted heredoc and the posted body, or the candidate_spec input default on manual runs, with a second, and compare_specs (io.kestra.plugin.scripts.python.Script) reads exactly those two files. Both children are scripts inside the workspace and every notification sits after the block, because default tasks are stateless and a temp dir is purged when a task completes.
  3. compare_specs installs PyYAML at the start of the container run, walks every channel and its publish and subscribe operations, collects each payload's required fields and properties, and diffs them against the baseline. A removed channel, a removed operation, a required field that left the required list or a property that left the payload is one breaking change, a channel the candidate adds is a compatible addition, and the verdict is printed as compatible, breaking, or error on one ::{"outputs": ...}:: line.
  4. gate_contract_changes (io.kestra.plugin.core.flow.If) escalates breaking into alert_breaking_change (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) with the removals and the CI build, an error run routes through check_parse_error and alert_unreadable_spec, and a clean contract lands in log_compatible_contract. The flow level errors handler reports any workspace or script failure with the execution id.

What you get

  • A contract gate for event streams that works the way OpenAPI gates work for REST, run before the branch merges instead of after consumers break.
  • The breaking removals as typed outputs, each one a removed channel, operation, required field or property in baseline order.
  • Escalation where the team already works, a Slack alert with the removals, both spec versions and the CI build to inspect.
  • A fail safe posture, an unreadable candidate escalates instead of reading as a compatible contract.
  • An execution history per candidate document that doubles as the contract review evidence.

Who it's for

  • Platform teams that own shared event schemas across many producing and consuming services.
  • Release engineers who need a contract verdict in the pipeline before a branch with schema changes merges.
  • API and event contract reviewers who want removals named in a channel instead of buried in a diff review.

Why orchestrate this with Kestra

AsyncAPI documents change in the same repositories as the services that emit them, and nothing stops a dropped field from reaching every consumer at once. Kestra gives the check a keyed webhook for CI, a shared workspace where the baseline and the candidate sit next to each other, the comparison logic versioned in the flow file, a verdict branch that separates breaking, unreadable and compatible, and an execution history per candidate that any parent pipeline can branch on. A lint step in CI gives you none of that, it only protects the repositories that remember to run it.

Prerequisites

  • A worker with Docker access, the comparison runs in python:3.12-slim and installs PyYAML at the start of each run.
  • A CI step that POSTs the candidate document as a raw YAML or JSON body, for example curl --data-binary @asyncapi.yaml against the webhook URL.
  • A Slack incoming webhook for the breaking change alert, the unreadable candidate alert and the failure handler.

Secrets

  • ASYNCAPI_WEBHOOK_KEY: key guarding the candidate webhook URL, anyone holding it can post a contract.
  • SLACK_WEBHOOK_URL: Slack incoming webhook URL used by the breaking change alert and the errors handler.

Quick start

  1. Add the two secrets to your Kestra namespace.
  2. Run the flow once with the default inputs and confirm verdict is breaking with breaking_count at 2, the fixture drops currency from order/created and removes the whole order/cancelled channel while adding order/refunded.
  3. POST the baseline document itself to the webhook and watch verdict flip to compatible with breaking_changes empty in the outputs.
  4. Point the event service pipeline at /api/v1/{tenant}/executions/webhook/{namespace}/asyncapi-contract-breaking-change-gate/{ASYNCAPI_WEBHOOK_KEY} and enable nightly_contract_check once every producer posts through it.

How to extend

  • Add server variable and message example checks to compare_specs so a renamed server or a dropped example also blocks the merge.
  • Gate many contracts at once with io.kestra.plugin.core.flow.ForEachItem over a spec list, each subflow posting its own candidate document.
  • Keep the previous breaking changes in the Kestra KV store and alert only when a new removal appears, so a known exception does not page every build.
  • Stop the promoting pipeline by adding io.kestra.plugin.core.execution.Fail under gate_contract_changes, and archive every candidate with io.kestra.plugin.aws.s3.Upload for the contract evidence pack.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.