List the monitored repos explicitly, and reorder the board - #12
Merged
Conversation
Template drift is a rhiza concern, and most people looking at this board do not use the template at all. It was sitting a third of the way down, directly under the trend chart, with its headline count in the top row of tiles between "CI red on main" and "PRs with red checks" - the most prominent spot on the page. That ordering asserts the number matters to the reader, and for most readers it does not. The section now comes last on both boards, and "Behind template" moves out of the header to sit above the bargauge and the pinned-ref table as that section's own headline. The five remaining tiles widen to 5/5/5/5/4 so the header still fills the grid rather than trailing a gap where the sixth used to be. make-public-dashboard.py needed the same edit: its LAYOUT dict positions the header tiles by title, so leaving "Behind template" listed there would have pinned it back into the header on the public copy no matter where fleet.json put it. Dropping it from LAYOUT lets it keep its order from the source instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
It was second from the bottom, below every detail table, which is where you put something nobody needs to look at. But it answers the question that qualifies everything else on the page: is this data current? A red CI count is meaningless if the last GitHub refresh failed an hour ago, and the reader has no way to know that without scrolling past four tables to find out. It now sits directly under "Trend and CI history" - after the summary tiles and the trend, before the detail. On the laptop board it is a collapsed row, so the cost is one line of vertical space; on the public copy the generator expands it, so rate limit, time since last refresh and refresh duration are visible without scrolling to the end. Section order on both boards is now: Fleet at a glance, Trend and CI history, Collector health, Detail, the per-repo drill-down, Template drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A server has no checkouts, so it names its fleet directly in .env - which left the one list that decides the board's contents existing twice, in two formats, kept in step by hand. Nothing reports the drift: add a repo to repos.yml and the laptop board grows a row while the public board silently does not. `gen-repos.py --env` resolves repos.yml exactly as the normal run does and prints the JQ_REPOS= line, writing nothing. Run it where the checkouts are and copy the one line over, or pipe it straight at the host. The server still keeps its fleet in .env rather than reading repos.yml, because every path in that file describes a machine the server is not - but the line is now derived rather than transcribed. Two tests: that --env prints the list and leaves the compose override untouched (so it is safe to run where no stack exists), and that an unknown flag is refused rather than silently treated as a normal run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Moving the section to the bottom was not enough: template drift is a rhiza concern, and to a visitor who does not use the template "three releases behind" reads as a defect rather than as something that does not apply to them. Dropping the section alone would not have removed it. The same metrics were on the board in two other places - a "Repos behind the template" table in the drill-down, and a "Behind template" series on the trend chart - so a headline tile could disappear while a chart carried on plotting the number. All five panels are handled together. The mechanism already existed for jq_local_*: a panel whose every query reads a dropped family goes, a panel that also reads something else keeps its other series. That is now a list, DROPPED_METRICS, with jq_rhiza_* alongside, plus drop_empty_rows so the Template drift heading does not survive its own contents. The final guard checks every family rather than just the one, so a future panel reading either cannot reach the public copy unnoticed. The private board is untouched: the section, the tile, the drill-down table and the trend series are all still there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three commits. The first decides which repos are on the board; the other two decide where things sit on it.
List the monitored repos explicitly, in
repos.yml(33dcceb)The fleet used to be assembled two ways at once, neither under our control: a whole-org GitHub sweep let the org side decide membership (a shared org like
cvxgrpdragged in 100+ repos that were not ours), and a directory walk under one mounted root let the disk side decide it.Both are replaced by
repos.yml— one entry per repo,path:for a checkout or a barerepo:for one not cloned locally.scripts/gen-repos.pyturns it intodocker-compose.repos.yml, so an unlisted repo is not merely filtered out, it is never visible to the container.repos.ymland the generated override are gitignored: they describe one machine's folder layout.Breaking change for the server.
JQ_ORGis gone.docker-compose.server.ymlnow requiresJQ_REPOSand refuses to start without it rather than serving an empty board.JQ_TEMPLATE_REPOalso takesowner/namenow, not a bare name.Demote template drift to the bottom (80e9b58)
Template drift is a rhiza concern and most readers of this board do not use the template. It sat a third of the way down with its count in the top row of tiles. The section is now last, and
Behind templatemoves out of the header to head that section. The five remaining tiles widen to 5/5/5/5/4 so the header still fills the grid.make-public-dashboard.pyneeded the same edit — itsLAYOUTdict positions header tiles by title, so leaving the entry in would have pinned the tile back into the header on the public copy.Put Collector health under the trend chart (022121e)
It was second from the bottom, but it answers the question that qualifies everything else: is this data current? A red CI count means nothing if the last refresh failed an hour ago. Collapsed on the laptop board (one line), expanded on the public copy.
Section order on both boards is now: Fleet at a glance → Trend and CI history → Collector health → Detail → per-repo drill-down → Template drift.
Verification
scripts/check-dashboard.pypasses on both boards (33 and 26 panels, no duplicate ids, no dangling links). The server stack was brought up from this branch on the live Hetzner host andscripts/check-public-safe.shpasses all seven checks — 4 exported repos, all public on GitHub, no anonymous query path, no published ports on Prometheus or the collector.Note for whoever deploys
After merging, on the server:
git pull, then nothing else — Grafana re-reads provisioned dashboards every 30s. But.envthere must already haveJQ_REPOSset, or the stack will not start.🤖 Generated with Claude Code