test(ci-trigger): pin the workspace suite rule

The rule lived only in suite_passed's body, and it inverts easily on a
casual read: ask for the suite again when it failed. Under that reading
the retrigger aliases would drop the suite in their most common case,
because they force-cancel the source run before reading it, so a shard
that was still running comes back cancelled rather than red.

Only an all-green suite is retired. Failed, cancelled, skipped, timed
out, still running and never dispatched all keep it on the retrigger,
and each of those now has a test. The two docstrings enumerate them, and
so does the i8ciall description, which is where an operator reads it.
This commit is contained in:
kevinveenbirkenbach committed 2026-09-03 17:37:33 +02:00
1 parent 9c355a85c3
commit 8600f1d9aa
3 files changed
+34 -6

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ alias i8ceco='m clean-container-owned'
alias i8cepa='m clean-pycache-dirs'
alias i8cesa='m clean-stale-nfs'
alias i8cesu='m clean-sudo'
alias i8ciall='__i8ciall(){ [ -z "${1:-}" ] && { echo "usage: i8ciall <run-id|url>" >&2; return 2; }; ghaf "$1" || echo "i8ciall: force-cancel of run $1 reported nothing to cancel; continuing" >&2; infinito administration deploy ci trigger --failed --strict --roles-only --run "$1"; }; __i8ciall' # retrigger run $1 (id or url): only the roles that truly failed take the priority line, by name, letting the rotation pick the axes, plus the priority entries that run never deployed, axes and all; the aborted, the still-running and the never-reached stay on the regular line, which resumes behind the green stretch the run added to the offset it was given; force-cancels the run first so it stops holding runner slots
alias i8ciall='__i8ciall(){ [ -z "${1:-}" ] && { echo "usage: i8ciall <run-id|url>" >&2; return 2; }; ghaf "$1" || echo "i8ciall: force-cancel of run $1 reported nothing to cancel; continuing" >&2; infinito administration deploy ci trigger --failed --strict --roles-only --run "$1"; }; __i8ciall' # retrigger run $1 (id or url): only the roles that truly failed take the priority line, by name, letting the rotation pick the axes, plus the priority entries that run never deployed, axes and all; the aborted, the still-running and the never-reached stay on the regular line, which resumes behind the green stretch the run added to the offset it was given; the workspace suite comes back unless every one of its jobs went green; force-cancels the run first so it stops holding runner slots
alias i8ciallon='__i8ciallon(){ [ -z "${1:-}" ] && { echo "usage: i8ciallon <run-id|url>" >&2; return 2; }; ghaf "$1" || echo "i8ciallon: force-cancel of run $1 reported nothing to cancel; continuing" >&2; infinito administration deploy ci trigger --failed --strict --roles-only --chunk-gate false --run "$1"; }; __i8ciallon' # like i8ciall, but the retrigger keeps deploying the remaining chunks after a failed one (chunk_gate=false) instead of stopping the chain; the run still ends red
alias i8cifail='__i8cifail(){ [ -z "${1:-}" ] && { echo "usage: i8cifail <run-id|url>" >&2; return 2; }; ghaf "$1" || echo "i8cifail: force-cancel of run $1 reported nothing to cancel; continuing" >&2; infinito administration deploy ci trigger --failed --run "$1"; }; __i8cifail' # retrigger the exact failed selections (role#variant@mode+tor) of run $1 (id or url) across every mode, plus its never-deployed priority entries, reproducing every other input of that run; force-cancels the run first so it stops holding runner slots
alias i8cifo='__i8cifo(){ [ -z "${1:-}" ] && { echo "usage: i8cifo <run-id|url>" >&2; return 2; }; ghaf "$1" || echo "i8cifo: force-cancel of run $1 reported nothing to cancel; continuing" >&2; infinito administration deploy ci trigger --failed --strict --run "$1"; }; __i8cifo' # like i8cifail but only hard-failed selections, excluding cancelled/aborted; force-cancels the run first
+10 -5
View File
@@ -376,9 +376,13 @@ SUITE_JOB_IDS = {"workspace": "test-workspace"}
def suite_passed(jobs: list[dict], suite: str) -> bool:
"""Whether ``suite`` ('workspace') ran to success in this run. A suite that
was skipped, cancelled or never dispatched has not passed, so a retrigger
keeps asking for it."""
"""Whether every job of ``suite`` ('workspace') completed successfully.
Only a clean sweep of successes retires the suite. A shard that failed,
was cancelled, timed out or skipped did not run through, and a run that
holds no job for the suite at all never started it -- none of those is
evidence the suite is good, so the retrigger keeps asking for it.
"""
job_id = SUITE_JOB_IDS[suite]
outcomes = [
_effective(job)
@@ -403,8 +407,9 @@ def config_from_run(
so the retrigger leaves it on that same default rather than pinning
today's default into a run that never asked for it.
A suite the source run already passed is turned off rather than carried
over, so a retrigger spends its runners on what actually failed.
A suite is turned off only when every job of it came back green; one that
failed, was cancelled or never ran at all keeps it on the retrigger, so a
retrigger spends its runners on what is not yet proven.
Args:
title: the source run's display title.
@@ -464,10 +464,33 @@ class TestConfigFromTitle(unittest.TestCase):
self.assertEqual(runs.config_from_run(title, jobs=jobs)[suite], "true")
def test_a_suite_that_never_ran_is_asked_for_again(self) -> None:
"""No job at all means it never started, which proves nothing."""
title = render({"workspace": "true"})
jobs = [{"name": "🧹 Lint", "status": "completed", "conclusion": "success"}]
self.assertEqual(runs.config_from_run(title, jobs=jobs)["workspace"], "true")
def test_a_shard_that_did_not_run_through_is_asked_for_again(self) -> None:
"""Only a success retires the suite; every other outcome, a mid-run
force-cancel included, leaves it unproven."""
for conclusion in ("cancelled", "skipped", "timed_out"):
with self.subTest(conclusion):
title = render({"workspace": "true"})
jobs = [self._suite_job("workspace", conclusion)]
self.assertEqual(
runs.config_from_run(title, jobs=jobs)["workspace"], "true"
)
def test_a_still_running_shard_is_asked_for_again(self) -> None:
title = render({"workspace": "true"})
jobs = [
{
"name": f"🎛️ Orchestrate CI (manual) / {runs.SUITE_JOB_IDS['workspace']}",
"status": "in_progress",
"conclusion": None,
}
]
self.assertEqual(runs.config_from_run(title, jobs=jobs)["workspace"], "true")
def test_one_failing_shard_keeps_the_whole_suite(self) -> None:
title = render({"workspace": "true"})
jobs = [