run logs: --job and --failed, so one red job is not six jobs of noise (#8) #2
feat/8-run-logs-job-filter into main1f3fca34d9b6.- @ogirardot opened this merge request · Sep 7, 2026edited
Closes #8.
run logs <n>printed the whole run's interleaved output. A rickub CI run has six
jobs, so triaging one red job meant pulling a multi-megabyte log to read ~5 lines
— and the cost of not triaging is worse: it trains reviewers to blind-re-run red
MRs, which is how a real failure eventually gets waved through.The information was already there — the API returns logs per job, with a name and
a status — so this is pure client-side selection.What's new
rickub run logs 30 --job ssh # one job rickub run logs 30 --failed # every job whose status is not success rickub run logs 30 --job ssh --json # the filter applies to --json too--jobmatches case-insensitively: job names come from workflow YAML, and
SSHvssshis a typo worth forgiving rather than reporting.--failedis deliberately wider than "failure" — a cancelled job is also not
green, and "what isn't green?" is the actual question ~90% of the time.- The filter runs before the
--jsonbranch, so--job X --jsoncannot
silently return the whole run.
The part that matters
An unknown
--jobis an error listing the run's real job names, never a
fall-through to everything:$ rickub run logs 30 --job web rickub: no job named "web"; this run has: vet / vuln / gosec / staticcheck / modulesA typo that returned the full log would look like it worked — and a filter you
cannot trust is worse than no filter, because you stop believing the short output
and re-run without it, which is exactly the cost the flag was added to remove. An
empty--failedresult saysEvery job succeeded — nothing to show.rather than
ending on silence, for the same reason.--jobtogether with--failedis refused: intersecting them prints nothing
whenever the named job passed, which is indistinguishable from the typo case.The no-flag behaviour is unchanged, and a test pins that.
Verified
Against this repo's real runs, not only in tests:
--jobon a real name, the
case-insensitive form, the unknown-name error above, the both-flags refusal, an
empty--failedon a green run, and--failed --json.🤖 Generated with Claude Code
- @ogirardot · Sep 7, 2026edited
Reviewed at effort
high; four findings, two medium and two low. All four are
fixed in the follow-up commit — the two mediums were real holes in the flag's own
contract.1. An empty
--jobdisabled the filter (medium). The guard tested
runLogsJob != "", sorickub run logs 30 --job "$JOB"withJOBunset printed
all six jobs and exited 0 — exactly the "a typo that quietly printed the whole log
would look like it worked" failure the flag was added to prevent, arriving through
the shell instead of through a typo. It also defeated the mutual exclusion:
--job "" --failedwas accepted and silently behaved as--failed. The decision
now keys oncmd.Flags().Changed("job"), and an empty name is refused with the
run's job list.2. A jobless run was told "Every job succeeded" (medium). The empty-result
message branched onrunLogsFailed, butlogs.Jobshad already been overwritten
by the filter, solen(logs.Jobs) == 0could not distinguish "all green" from
"this run never produced a job". A run that failed before any job started — bad
workflow YAML, a dispatch error — was reported as all-green, which is the same
class of lie the rest of this MR is arguing against. It branches on the pre-filter
count now.3. Server-controlled job names reached the terminal unsanitized (low). In the
job header, and more importantly in the unknown-job error: that one goes out
throughmain's barefmt.Fprintf(os.Stderr, "rickub: %s\n", err), which applies
no cleaning of its own. Every other human-facing server string in this codebase is
clean()ed per b7e1d1f; a job named with an erase-line sequence could otherwise
repaint or hide lines for anyone inspecting that repo's runs. Both are cleaned now,
with a test that asserts the escape does not survive while the readable remainder
of the name is still listed.4.
--jobreturned only the first name match (low). A matrix leg or a
workflow called twice can emit two jobs sharing a name; one of them vanished with
no indication. That is the short-output-you-cannot-trust outcome the function's own
doc comment argues against. It returns every match.Each fix has a regression test. Verified live as well: an unset
--jobvariable
and--job "" --failedboth now exit non-zero instead of printing everything.
Sign in to comment.