Skip to content

Repository files navigation

OpenActive Data Stewards Dashboard

Internal Streamlit app for the ODI tech team to monitor the health and quality of data published by the ~170 OpenActive publishers. Read-only, behind Google SSO, restricted to the theodi.org workspace.

Data comes from the stewards REST API, which fronts a daily BigQuery batch — every page states the snapshot date rather than implying live data.

Run it

uv sync --extra dev

Against the real API, copy .streamlit/secrets.toml.example to .streamlit/secrets.toml, fill in the Google OIDC client, the API token and — for the interim admin API — api_style = "admin" with api_token_param = "token", then run:

STEWARDS_ENV=dev STEWARDS_DISABLE_AUTH=true \
  uv run streamlit run src/stewards/app.py

Endpoints that a deployment has not implemented yet report themselves as not live on the page that needs them; nothing else on the app is affected. Today that is the fleet summary, the contact queue and every monitor except single-feed stalls.

Develop

uv run pytest -q --cov=src/stewards --cov-report=term-missing
uv run ruff check --fix . && uv run ruff format .
uv run mypy src

CI

.github/workflows/ci.yml runs on every pull request to main, and on pushes to main:

  • Lint — ruff check, ruff format --check, mypy --strict
  • Tests — pytest, with the coverage bars enforced rather than aspirational:

    = 80% project-wide, and >= 90% across monitors/, components/ and api/

Dependencies install with uv sync --extra dev --locked, so a pyproject.toml change committed without a refreshed uv.lock fails the build instead of silently resolving to something the lockfile does not describe.

Deploy

.github/workflows/cd.yml runs when a release is published — gh release create v1.2.3 --generate-notes is the deploy, and merging to main on its own changes nothing that is running. It builds Dockerfile, pushes the image to GHCR tagged with the release name (and sha-<commit>), and points an Azure App Service web app at it using that app's publish profile. A prerelease is built but not deployed, and a tag that is not an ancestor of main is refused, since only main has passed CI.

The container keeps the Google OIDC gate; docker/entrypoint.sh writes Streamlit's [auth] secrets file from app settings at start-up, so nothing is baked into a layer.

The web app, its GHCR pull credentials, its app settings and the publish profile are set up once by hand — the full procedure, plus rollback, is docs/deployment.md.

Where things are

  • BUILD_BRIEF.md — settled product decisions, page map, API contract, visual language
  • CLAUDE.md — architecture, hard rules, configuration, testing bar
  • .claude/skills/add-monitor/SKILL.md — how to add the next monitor
  • Data Stewards Dashboard.dc.html — the approved UI mockup

Two of the eight monitors are built (single_feed_stall, feed_ingestion_error), plus the overview, and the cross-monitor contact queue. The rest follow their API endpoints. Runbooks are published separately from docs/ to GitHub Pages.

About

Internal Streamlit app for the ODI tech team to monitor the health and quality of data published by the OpenActive publishers.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages