Skip to content

Add a test suite and CI that catch the bugs this repo has shipped - #4

Merged
tschm merged 2 commits into
mainfrom
add/test-suite-and-ci
Aug 29, 2026
Merged

Add a test suite and CI that catch the bugs this repo has shipped#4
tschm merged 2 commits into
mainfrom
add/test-suite-and-ci

Conversation

@tschm

@tschm tschm commented Aug 29, 2026

Copy link
Copy Markdown
Member

Why

Three bugs reached main in short order:

  1. an undefined Config attribute that crashed every GitHub refresh (Fix broken main: define Config.public_only, and add a reviewed path to public serving #1)
  2. deleted and renamed workflows counted as live, reddening a repo for 12 weeks (Take the workflow list from GitHub, not from run history #2)
  3. a paginated runs feed that hid failing jobs entirely (Ask per workflow for whatever the runs feed missed #3)

CodeQL — the only check on this repo — passed on all three, because it never executes this code. Every one was caught by hand.

What the suite covers

Targeted at exactly those failure modes rather than chasing coverage:

  • test_config walks the AST for every cfg.<attr> the package reads and asserts Config defines it. That catches the whole class, not just the attribute that bit us.
  • test_workflows drives the GitHub client against canned responses: deleted and disabled workflows ignored; a renamed workflow yielding one series under its current name; "latest" decided by completion time, not feed order; workflows missing from the feed fetched directly; workflows that never ran absent rather than assumed green; an unreadable listing degrading to over-reporting; two workflows sharing a name getting distinct labels.
  • test_metrics asserts the exposition is valid and never overstates health: a repo is green only when every workflow is, and no duplicate label sets are emitted.

No test touches the network.

Verified by reintroducing each bug

Bug reintroduced Result
Config.public_only removed 6 failed, 14 passed
deleted-workflow filter removed 2 failed, 18 passed
feed backfill removed 1 failed, 19 passed

It already found something

render() trusted github.py to hand it unique workflow names. When that invariant broke upstream, Prometheus silently dropped 16 samples per scrape ("samples with different value but same timestamp" — visible only in its logs, target still "up"). This layer owns the exposition contract, so it now collapses duplicates itself, newest run winning.

The workflow

Lint, format, the suite, the dashboard validator, a staleness check on the generated public dashboard, and compose validation.

Two things worth noting, both found by dry-running the steps locally before writing them down:

  • the overlays are validated as overlays — they only patch services and are not valid alone
  • the base compose file needs GITHUB_TOKEN set to anything, or interpolation fails

ruff's line-length moves into pyproject.toml so check and format cannot disagree — passing the flag to one and not the other silently fails CI. The second commit is the resulting reformat: pure formatting, no behaviour change, separated so it can be skimmed.

Full pipeline dry-run from a clean git archive of this branch, on top of current main: all steps green, 20 tests passing.

🤖 Generated with Claude Code

tschm and others added 2 commits August 29, 2026 13:24
Three bugs reached main: an undefined Config attribute that crashed every
GitHub refresh, deleted and renamed workflows counted as live, and a paginated
runs feed that hid failing jobs. CodeQL - the only check here - passed on all
three, because it never executes this code.

The suite targets exactly those failure modes rather than chasing coverage:

- test_config walks the AST for every `cfg.<attr>` the package reads and
  asserts Config defines it. That catches the whole class, not just the one
  attribute that bit us, and it would have failed on the commit that shipped it.
- test_workflows drives the GitHub client against canned responses: deleted and
  disabled workflows ignored, a renamed workflow yielding one series under its
  current name, "latest" decided by completion time rather than feed order,
  workflows missing from the feed fetched directly, workflows that never ran
  absent rather than assumed green, an unreadable listing degrading to
  over-reporting, and two workflows sharing a name getting distinct labels.
- test_metrics asserts the exposition is valid and never overstates health: a
  repo is green only when every workflow is, and no duplicate label sets are
  emitted.

Each was verified by reintroducing the original bug and watching the relevant
test fail - 6, 2 and 1 failures respectively.

That last test found a live weakness. render() trusted github.py to hand it
unique workflow names; when that invariant broke upstream, Prometheus silently
dropped 16 samples per scrape. This layer owns the exposition contract, so it
now collapses duplicates itself, newest run winning.

CI runs lint, format, the suite, the dashboard validator, a check that the
generated public dashboard is not stale, and compose validation. The overlays
are validated as overlays because they only patch services and are not valid
alone; the base file needs GITHUB_TOKEN set to anything to interpolate. Every
step was dry-run locally before being written down.

ruff's line-length moves into pyproject so `check` and `format` cannot
disagree - passing the flag to one and not the other silently fails CI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pure reformatting, no behaviour change: the package had been formatted at
ruff's default 88 while lint ran at 100, so the first `ruff format --check` in
CI would have failed on untouched files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Config field defaults bind at import, so re-evaluate the expression.
import importlib

import jq_collector.config as mod
@tschm
tschm merged commit b866478 into main Aug 29, 2026
4 checks passed
@tschm
tschm deleted the add/test-suite-and-ci branch August 30, 2026 04:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant