Schedule icon
Download icon
Script icon
Get icon
If icon
Commands icon
Docker icon
Set icon
SlackIncomingWebhook icon
Fail icon
Log icon

Validate a transit agency's GTFS feed whenever it changes

Check a GTFS transit feed daily, run the official MobilityData validator when it changes, and alert or fail on errors. Runs with no setup.

Categories
Data

Transit agencies publish their schedules as GTFS feeds, and apps such as Google Maps, OneBusAway and trip planners read them. A broken feed means wrong or missing departures for riders, and agencies often republish without notice. This flow downloads a feed every day, validates it with the canonical MobilityData GTFS validator only when it changed since the last check, and reports the result.

It runs with no setup. The default feed is the Redding Area Bus Authority, Slack is off and errors do not fail the run.

How it works

  1. download (io.kestra.plugin.core.http.Download) fetches the zip from feed_url.
  2. fingerprint (io.kestra.plugin.scripts.python.Script) hashes the zip with SHA-256.
  3. previous_hash (io.kestra.plugin.core.kv.Get) reads the hash stored by the last validated run from the KV store. It is empty on the first run.
  4. feed_changed (io.kestra.plugin.core.flow.If) validates only when the hash differs, or when force_validation is true. Otherwise the run ends with a log line.
  5. validate runs the validator image ghcr.io/mobilitydata/gtfs-validator:8.0.1 on the feed and exports report.json and report.html.
  6. summarize (io.kestra.plugin.scripts.python.Script) counts ERROR, WARNING and INFO notices and lists the five error codes with the most notices.
  7. remember_hash (io.kestra.plugin.core.kv.Set) stores the new hash.
  8. errors_found posts to Slack when notify_slack is true, and ends the run as FAILED when fail_on_errors is true. A clean feed gets a log line with the warning and info counts.

Inputs

  • feed_url (STRING, default the Redding Area Bus Authority feed): the static GTFS zip to check.
  • force_validation (BOOL, default false): validate even when the feed is unchanged.
  • fail_on_errors (BOOL, default false): end the run as FAILED when the feed has ERROR notices.
  • notify_slack (BOOL, default false): post feeds with errors to Slack.

Prerequisites

  • A Kestra worker that can run Docker containers, for the validator and Python images.
  • Network access to the feed URL.

Secrets

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

Quick start

  1. Save the flow and run it with the defaults. The first run always validates, and the log shows the notice counts.
  2. Run it again. The feed has not changed, so log_unchanged skips validation.
  3. Run it with force_validation set to true to validate the same feed again.
  4. Point feed_url at your own agency's feed. The Mobility Database lists thousands of public feeds.
  5. Leave the daily_check schedule on to check the feed every morning.

Expected outputs

  • outputs.validate.outputFiles['report/report.html']: the full validation report to open in a browser.
  • outputs.validate.outputFiles['report/report.json']: the same report as JSON.
  • outputs.summarize.vars.errors, warnings, infos: notice counts by severity.
  • outputs.summarize.vars.top_errors: up to five error codes with their notice counts.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.