mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
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:
1 parent
9c355a85c3
commit
8600f1d9aa
3 files changed
+34
-6
No files matched your search
@@ -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
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
Reference in new issue
Block a user