New to Kestra?
Use blueprints to kickstart your first workflows.
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.
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.
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.download (io.kestra.plugin.core.http.Download) fetches the protobuf snapshot from feed_url.previous (io.kestra.plugin.core.kv.Get) reads the fingerprints of the alerts reported by earlier runs.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.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.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.
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.download and feed_changed, in the URL or as a header.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.SLACK_WEBHOOK_URL: Slack incoming webhook. Only needed when notify_slack is true.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.route_ids default. Set the min_severity default to INFO to see every alert. Triggered runs always use the defaults.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.feed_url and the trigger's uri to the same URL.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.