Files
computer-playbook/utils/github/variant/instructions.py
T
kevinveenbirkenbachandClaude Opus 5 7fd495cdfc feat(ci): replay a role's README instructions on its smallest deploy row
The instructions test held a job of its own that picked one random role per
run, so a README's Production block was proven roughly once per 265 roles.
The replay now rides on a deploy row instead: no extra runner, and every role
the sweep touches gets its documented one-command deploy exercised.

The row is the role's smallest variant -- fewest services enabled -- because
that is the shape the README describes, and it is chosen among the variants
the sweep actually deploys, so a row cut as redundant coverage cannot silently
drop the role from the test. A role qualifies only when its README carries a
Production block and the guide's own mode is one the role runs and tests.

The marked entry carries the guide mode in `instructions` and a 📖 in its job
title, between the variant number and a priority ⭐. The guide mode is
independent of the mode the rotation gave the row: a swarm row still replays
in compose. The step runs last in the deploy job, after the swarm teardown,
because the replay deploys the role a second time and needs the runner's
ports.

call-test-instructions.yml, cli.meta.ci.guide_select and the `instructions`
dispatch input go with it. `redundant()` moves next to the marker so the
chunker, the plan table and the marker share one definition.

The plan table trades its 📊 Weight column for 📖 Instructions; nothing read
the weight any more, so it leaves the matrix entries too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 16:57:04 +02:00

62 lines
2.3 KiB
Python

"""Which matrix entry replays its role's README instructions.
The replay used to be a job of its own, picking one random role per run. It
rides on a deploy row instead: the role's smallest variant among the rows this
sweep actually deploys, marked with ``instructions`` (the mode the replay runs
in) and a 📖 in the job title. :mod:`utils.roles.guide` decides which variant
that is; this module is what turns the decision into matrix entries.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from utils.roles.guide import guide_variant
from utils.symbol_glossary import to_emoji
if TYPE_CHECKING:
from collections.abc import Mapping, Sequence
from typing import Any
def redundant(entry: Mapping[str, str]) -> bool:
"""Whether the sweep drops this row as coverage an earlier row already has."""
if entry["priority"] == "true":
return False
return entry["clone"] == "true" or entry["covered"] != "0"
def mark(
entries: list[dict[str, str]],
variants_per_app: Mapping[str, Sequence[Mapping[str, Any]]] | None,
) -> list[dict[str, str]]:
"""Hand one entry per role the replay, and give its label the 📖.
Only the first entry of the chosen variant: a priority row runs every mode
and onion state it offers, and replaying the same README block in each of
them proves nothing the first replay did not. The glyph goes between the
variant number and the ⭐ of a priority row, with no space between the two:
they are one marker block, not two axes.
"""
deployed: dict[str, set[str]] = {}
for entry in entries:
if not redundant(entry):
deployed.setdefault(entry["apps"], set()).add(entry["variant"])
star = f" {to_emoji('priority')}"
marked: set[str] = set()
for entry in entries:
app = entry["apps"]
if app in marked or redundant(entry):
continue
variant, mode = guide_variant(app, variants_per_app, deployed.get(app, set()))
if not mode or entry["variant"] != variant:
continue
entry["instructions"] = mode
entry["label"] = (
entry["label"].removesuffix(star)
+ f" {to_emoji('instructions')}"
+ (to_emoji("priority") if entry["priority"] == "true" else "")
)
marked.add(app)
return entries