Commit Graph
6 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 6b3ed82aa0 fix(ci): resolve deploy job titles through the display-name codec
report_failures matched job names against a raw role id
((?:web-app|web-svc|svc|sys)-[a-z0-9-]+), but job titles have carried
display names for a while, so the regex matched nothing and every failed
deploy on main went unreported. runs.py had the same shape and stopped
at the first mode glyph, which swallowed a caller path like
'z / Host / sys-front-proxy' into the role name.

Both now go through axes.parse_label, kept next to the function that
builds the label so the two cannot drift, and resolve the middle through
the display-name codec. The parser anchors on the LAST mode glyph so a
reusable-workflow caller path carrying one of its own cannot capture the
role.

The onion state is part of what identifies a job, because a priority row
runs the same mode and variant twice; artifact_name takes it so the
reporter looks for the artifact the run actually uploaded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 06:09:05 +02:00
kevinveenbirkenbachandClaude Opus 5 bc1d2d86f6 feat(ci): carry the tor mode into a retrigger, read from the job log
A retrigger reproduces its source run's configuration, and the tor axis was
missing from it: rerunning a run dispatched with 'exclusive' silently fell back
to 'auto' and tested a different matrix than the one whose failures it was meant
to chase.

The mode is read from the job log's Inputs block, not from the run title. The
title renders it as a glyph, so recovering it there would mean translating a
symbol back into a word on every retrigger; the log already holds what the
operator picked, and inputs_from_jobs reads that same block for the priority
list today. LOG_INPUTS names the inputs that take this route.

That also removes a trap the glyph created. The tor segment renders through
format('{0} ', ...) with no opening literal, and run_name locates a value by
searching for its head - str.find('') matches at position 0, so the parser would
have handed back the title's own prefix as the tor value, plausibly and without
raising. segments() now skips a headless segment; its glyphs stay openings, so
they still terminate the value before them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 12:22:20 +02:00
kevinveenbirkenbachandClaude Opus 5 910748ec41 refactor(ci): mark deploy-mode sequencing with a many-legged crawler
The traffic light said "gate" everywhere else in the pipeline, on the PR
scope check and on the dependency gate, so reusing it for the deploy-mode
order made an ordering knob look like another pass/fail barrier. A crawler
reads as what sequencing is: segments following each other in a line.

Both failure-report entries in the orchestrator move to the ladybug in the
same commit, because they already held the caterpillar and one workflow
cannot spend the same glyph on ordering and on failures. The ladybug is what
the bug-report issue template already uses.

Only the test fixture spells the glyph out; the parser derives its segment
heads from the workflow's own run-name, so it follows the change on its own.
The traffic light stays where it means a gate, and as the release-candidate
symbol in the glossary.

A run title created before this commit still carries the traffic light, so
recovering its sequencing input from the title yields nothing and a retrigger
leaves that one input on the workflow default.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 20:58:36 +02:00
kevinveenbirkenbachandClaude Opus 5 3883d73c43 feat(ci): retrigger reproduces the source run
The REST API answers inputs: null for a finished workflow_dispatch, so
the run name is the only record of what a manual run was dispatched
with. It carried one value, distros; everything else silently fell back
to the workflow defaults, and a failure that only reproduces on swarm
with btrfs came back green from a run that deployed all three modes on
whatever filesystem it drew.

Render every input as its own <emoji><value> segment instead, omitted
when it holds its default, so the title carries exactly what deviates
and an absent input means 'leave it on the default'. run_name derives
those segments from the workflow rather than knowing them, so the format
cannot drift away from the parser without a failing test.

distros no longer defaults to debian -- empty draws one at random, the
way untagged pushes already do. That leaves nothing in the title, so the
effective list is recovered from the discover job names, matched by
content against the meta/distros.yml SPOT rather than by job-name shape.

Priority roles that fell behind the budget cut in every mode hold no job
at all, so failed_roles cannot see them: they are neither green nor red,
they never ran. Carry them along or they never deploy.

--run now resolves before the selection, so it reproduces a run whatever
picks the roles, not only with --failed.

tests/utils/ci_*.py move into tests/utils/ci/ -- two files sharing a
delimiter-bounded prefix are a folder in disguise, and the structure
lint says so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 10:47:40 +02:00
kevinveenbirkenbach 93eea4c415 Autoformat 2026-08-04 13:27:35 +02:00
kevinveenbirkenbachandClaude Fable 5 65d2aa028e feat(ci): emoji entry names and a symbol-framed manual run title
The three CI entry workflows drop the "⚡ CI:" prefix for one emoji each -
🕹️ Manual, 🔀 Pull Request, 📤 Push - completing the trigger triad by symbol.
The manual run-name loses its prose prefix and separator dots; the segments now
frame themselves: 🕹️ for the dispatch, 🐧 before the distro sweep, ⭐ for the
priority line, 🎯 for a verbatim whitelist, 🔀 for diff derivation.

  before: Manual CI triggered: debian arch; web-app-x ⭐; diff-derived (origin/main)
  after:  🕹️ 🐧 debian arch ⭐ web-app-x 🔀 diff (origin/main)

Dropping the dots removes the fixed literal after inputs.distros that
utils/github/run_name.py cut the distro list at - the list is itself
space-separated, and the next segment starts with a branch-dependent emoji.
value_from_title therefore derives the terminator dynamically when the framing
literal is whitespace-only: _openings_after collects what any later template
segment can render first (the leading literal of each quoted string in later
expressions, format placeholders stripped, plus later inter-expression
literals) and cuts at the earliest occurrence. The SPOT property holds: the
openings are read from the workflow's own run-name, so a future emoji change
flows into the parser without touching it.

Titles from before this change no longer match the template and yield '' - the
documented unknown-title behaviour, so a retrigger of a pre-rename run falls
back to the workflow's distro default instead of guessing.

The dispatch CLI is unaffected (it targets entry-manual.yml by file name), job
names and the orchestrator are untouched, and no workflow_run trigger
references the old names. Required status checks configured against the old
workflow names in repository settings are the one surface this repo cannot
see - re-check them after the rename lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 13:27:34 +02:00