Trigger icon
Download icon
Get icon
Script icon
If icon
Log icon
SlackIncomingWebhook icon
Set icon

Report new and updated GTFS-Realtime service alerts for the routes you watch

Watch a GTFS-Realtime ServiceAlerts feed with an HTTP trigger, filter by route and severity, and post only new or updated alerts to Slack. Runs with no setup.

Categories
Data

Transit agencies publish disruptions, detours and shuttle replacements in a GTFS-Realtime ServiceAlerts feed. The feed is a full snapshot of every active alert, so the people running a rider app, a station screen or an operations channel have to work out which alerts are new for the routes they own. This flow checks the feed with an HTTP trigger, starts a run only when the agency has published a new version, and reports the alerts that are new or updated since the last run, filtered by route and severity.

It runs with no setup. The default feed is the MBTA's public alerts feed, watching the subway lines, and Slack is off.

How it works

  1. feed_changed (io.kestra.plugin.core.http.Trigger) sends a HEAD request every five minutes and fires only when the feed's ETag differs from the one saved in the KV store. It uses HEAD because the trigger reads the response body as text, and a protobuf body is binary. The MBTA republishes its feed every minute, so the default feed starts a run on every check. A feed that is only republished when an alert changes starts no runs in between.
  2. download (io.kestra.plugin.core.http.Download) fetches the protobuf snapshot from feed_url.
  3. previous (io.kestra.plugin.core.kv.Get) reads the fingerprints of the alerts reported by earlier runs.
  4. diff (io.kestra.plugin.scripts.python.Script) decodes the feed with gtfs-realtime-bindings, keeps the alerts that affect route_ids at min_severity or above, and fingerprints each one from its text, effect and severity. An alert whose fingerprint is not in the KV store is new or updated. Active periods are left out because some agencies, the MBTA included, move the end time of an ongoing alert forward every minute, which would report the same alert again on every run. It outputs count, watched, cleared, seen and summary.
  5. report (io.kestra.plugin.core.flow.If) logs the new or updated alerts as one warning and posts them to Slack when notify_slack is true. When nothing changed, it logs how many alerts are active and how many cleared.
  6. remember_alerts and remember_etag (io.kestra.plugin.core.kv.Set) save the fingerprints and the feed's ETag for the next run.

The flow runs one execution at a time (concurrency.limit: 1), so a slow run never reports the same alerts twice.

Inputs

  • feed_url (STRING, default the MBTA alerts feed): the GTFS-Realtime ServiceAlerts URL.
  • route_ids (STRING, default the MBTA subway lines): comma-separated route IDs to watch. Empty watches every route.
  • min_severity (SELECT, default WARNING): the lowest severity to report, one of INFO, WARNING or SEVERE.
  • notify_slack (BOOL, default false): post new and updated alerts to Slack.

Prerequisites

  • A Kestra worker that can run Docker containers, for the Python script.
  • Network access to the feed URL. Some agencies require an API key; add it to both download and feed_changed, in the URL or as a header.
  • A feed URL that answers a HEAD request with an ETag header. Most CDNs do. If yours does not, replace feed_changed with a Schedule trigger and delete remember_etag. The flow still reports only new or updated alerts.

Secrets

  • SLACK_WEBHOOK_URL: Slack incoming webhook. Only needed when notify_slack is true.

Quick start

  1. Save the flow. feed_changed checks the feed right away and starts the first run, which logs a warning listing each current subway alert at WARNING or above.
  2. Run the flow yourself. Unless an alert changed in between, it logs only how many alerts are active and how many cleared.
  3. To watch other routes, change the route_ids default. Set the min_severity default to INFO to see every alert. Triggered runs always use the defaults.
  4. Leave the feed_changed trigger on. It checks the feed every five minutes and starts a run when the agency has published a new version. Lower its interval for faster alerts.
  5. When pointing at another agency, set feed_url and the trigger's uri to the same URL.

Expected outputs

  • outputs.diff.vars.count: how many alerts are new or updated.
  • outputs.diff.vars.summary: a heading followed by one line per new or updated alert, with severity, routes, header, effect and link.
  • outputs.diff.vars.watched: how many active alerts match the filters.
  • outputs.diff.vars.cleared: how many previously reported alerts are no longer in the feed.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.