The status hub¶
Each project already watches itself: its collect workflow opens a repair issue when a
source fails or is degraded. A hub watches many projects together. It is one small repo
whose scheduled workflow reads every project's status.json, keeps one issue per active
problem, posts a weekly digest, and shows an overview of all projects.
Set one up in five minutes¶
-
Create the hub. Either let it find your projects by topic, or list them:
-
Push
my-hubto GitHub as a new repo. Private is fine. - If any watched repo is private, give the hub read access (see Access).
-
Run the
hubworkflow once from the Actions tab. Its first step runsgleanyard hub check, which lists what works and what is missing, each with the step that fixes it:ok hub.yaml is valid ok found 2 repo(s) of my-org by topic ok my-org/events: 3 sources, last run 5 hours ago FAIL my-org/markets: status.json not found, or the repo is not readable fix: give the token read access to its contents and pull requests, run its `collect` workflow once, or list its status.json URL instead
Run gleanyard hub check locally at any time, with GH_TOKEN set if repos are private.
Which projects it watches¶
# hub.yaml
repos:
- my-org/events # a GitHub repo: read through the API
- https://example.org/markets/status.json # a URL: fetched with no GitHub token
- {name: Markets, url: https://example.org/markets/status.json} # a URL with a name
discover: # optional: also every repo of an owner with a topic
owner: my-org
topic: gleanyard
missed_run_hours: 36 # a report older than this means a scheduled run was missed
pr_waiting_days: 7
digest_weekday: 0 # Monday; null turns the weekly digest off
viewer: false # true adds a searchable table of each project's export
gleanyard init reminds you to add the topic gleanyard to a new project's repo, which is
all a discovering hub needs. Listed repos and discovered ones are merged.
Access¶
| Project | What the hub needs |
|---|---|
| Public repo | Nothing: the workflow's own token reads it. |
| Private repo | A fine-grained token with Contents: read and Pull requests: read on it, saved in the hub as the Actions secret HUB_TOKEN. |
| status.json URL | Nothing. The URL must be reachable without signing in. Pull request alerts are not available. |
The hub writes issues only in its own repo, with the workflow's own token, so HUB_TOKEN never
needs write access. If you would rather not create a token at all, publish each project's
status.json somewhere readable (a raw file of a public repo, the project's own Pages site,
any static host) and list the URLs. The file holds health only: source names, counts, fill
rates and errors, never records.
The overview¶
By default nothing is published. Every run writes the overview to the workflow's summary
page, which only people with access to the hub repo see, and attaches the full dashboard
page to the run. gleanyard hub init --pages publishes the dashboard on GitHub Pages
instead. On most GitHub plans a Pages site is public, so choose it only when it is fine for
anyone to see the source names, record counts and error messages.
The dashboard is one static page (no JavaScript): a row per project with a red, amber or
green marker, opening to its sources, their last success and error or warning, and the
setup or repair pull requests waiting for review. Under each source a folded table shows how
often each field is filled now and in the baseline run; a field below 80% of its baseline is
marked amber and the table starts open, before the 50% fill_rate_drop warning fires. A
project that needs attention starts open. The page follows the reader's light or dark
setting and works on a phone.
The record viewer¶
With viewer: true in hub.yaml, the hub also reads each project's public export
(exports/records.jsonl, or export_path) and gleanyard hub build writes a page per project
under records/, linked from the dashboard as "Browse N records". The page is a table with a
search box that filters in the browser; it needs no server. A project listed by URL shows a
viewer when it names its export:
repos:
- {name: Markets, url: https://example.org/markets/status.json,
export_url: https://example.org/markets/records.jsonl}
viewer: true
viewer_rows: 2000 # rows per project in the viewer; the rest are counted
The viewer reads one JSON lines file. A project whose export is CSV only (export: null) or
split into parts (export_partition) has no single file to read, so it shows no viewer;
point export_url at one JSON lines file if it has one.
The export holds only fields each source's rights allow, so the viewer shows nothing the
project does not already publish. Once the dashboard is on a public Pages site, though,
anyone can read the export of every watched project, private repos included. Leave viewer
off unless that is what you want. The hub needs no extra access: it reads the export with
the same token as status.json.
Alerts fire on change¶
Every problem has a stable key, such as my-org/events:city-events:failing. A problem that
starts opens an issue, a problem that is still there changes nothing, and a problem that
ends closes its issue with a note. A source that stays down for a week is one issue, not
seven.
| Alert | Active while |
|---|---|
| Source failing | A source's health in status.json is failing. |
| Lost records | A source has a record_drop warning: over 25% fewer records than its last good run. |
| Fields stopped filling | A source has a fill_rate_drop warning, such as dates that stopped parsing. |
| More records rejected | A source has a rejection_spike warning. |
| Data stopped changing | A source has an unchanged warning (only with expect_change_days). |
| Terms changed | Terms pages or robots.txt changed since their last review (watching the terms). One alert per repo, listing each changed page with the sources that rely on it. |
| Missed run | The report's generated_at is older than missed_run_hours. |
| PR waiting | A setup or repair pull request has been open longer than pr_waiting_days. |
| No report | status.json is missing or invalid, or the repo cannot be read. |
| Hub problem | Discovery failed, for example because the token cannot search the owner. |
| Weekly digest | Every digest_weekday, even when everything is green; one issue per week. |
The warnings behind the degraded alerts are explained in Health.
Running it by hand¶
export GH_TOKEN=... # read access to the watched repos; also issues:write on the hub
gleanyard hub check --hub-repo my-org/my-hub
gleanyard hub run --hub-repo my-org/my-hub --dry-run # look first: reads, opens nothing
gleanyard hub run --hub-repo my-org/my-hub
gleanyard hub build # site/index.html and site/summary.md
A hub that lists only status.json URLs can --dry-run with no token at all.