Files
computer-playbook/tests/unit/python/cli/meta/ci/test_matrix.py
T
kevinveenbirkenbachandClaude Opus 5 c32bf320ff feat(ci): add a fourth deploy chunk so a short priority chunk strands no budget
A sweep may deploy 210 rows (available) in chunks of 80. Three declared
blocks hold exactly that when there is no priority line, but priority
rows get a chunk of their own that is never topped up with regular rows.
Nine priority rows therefore occupied a whole block, left the regular
rows 2 x 80 = 160, and 42 rows of budget went unused.

Adding a block to the YAML alone would not have changed that:
matrix.chunks_of handed the split slots.chunk_count(), which is
min(ceil(available / chunk size), INFINITO_CI_MAX_CHUNKS) and ignores
the priority seam, so the plan still stopped at three blocks.

call-orchestrator.yml now declares test-deploy-chunk-3, gated on chunks
0 to 2 like every chunk gates on all before it, and report-main-failures
and done need it. INFINITO_CI_MAX_CHUNKS is 4, one above what the budget
fills, and slots.chunk_blocks() returns it. chunks_of hands the split
every declared block; available still caps the rows, and a chunk whose
slice comes back empty skips its deploy. chunk_count() stays the "chunks
filled" figure of the budget report.

Tests: the split spends 9 + 80 + 80 + 41 = 210 rows with a spare block;
chunks_of plans three chunks from chunk_blocks=3 while chunk_count=2
(the previous wiring yields [1, 10]); an integration guard requires the
declared chunk jobs to equal INFINITO_CI_MAX_CHUNKS and to exceed
ceil(available / chunk size) by one, and fails on the stale value 3.

A shell that inherited INFINITO_CI_MAX_CHUNKS=3 keeps failing that guard
until it is restarted; make dotenv-force rewrites .env.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 23:46:48 +02:00

197 lines
7.1 KiB
Python

from __future__ import annotations
import unittest
import unittest.mock as mock
from typing import ClassVar
from cli.meta.ci import matrix
def _entry(
app: str,
variant: str,
mode: str,
*,
priority: bool = False,
covered: str = "0",
clone: bool = False,
) -> dict:
return {
"apps": app,
"variant": variant,
"mode": mode,
"tor": "false",
"priority": "true" if priority else "false",
"covered": covered,
"clone": "true" if clone else "false",
}
class TestChunksOf(unittest.TestCase):
def _chunks(self, entries: list[dict], *, size: int) -> list[list[dict]]:
with (
mock.patch.object(matrix.slots, "chunk_size", return_value=size),
mock.patch.object(matrix.slots, "chunk_blocks", return_value=4),
mock.patch.object(matrix.slots, "available", return_value=99),
):
return matrix.chunks_of(entries, 0)
def test_a_chunk_is_sorted_by_name_then_variant(self) -> None:
entries = [
_entry("web-app-b", "1", "compose"),
_entry("web-app-a", "1", "compose"),
_entry("web-app-a", "0", "compose"),
]
chunk = self._chunks(entries, size=9)[0]
self.assertEqual(
[(e["apps"], e["variant"]) for e in chunk],
[("web-app-a", "0"), ("web-app-a", "1"), ("web-app-b", "1")],
)
def test_the_split_still_follows_the_discovery_ranking(self) -> None:
entries = [
_entry("web-app-z", "0", "compose"),
_entry("web-app-a", "0", "compose"),
]
chunks = self._chunks(entries, size=1)
self.assertEqual(
[chunk[0]["apps"] for chunk in chunks], ["web-app-z", "web-app-a"]
)
def test_a_short_priority_chunk_leaves_the_regular_rows_a_spare_block(
self,
) -> None:
entries = [_entry("web-app-p", "0", "compose", priority=True)] + [
_entry(f"web-app-{index:02d}", "0", "compose") for index in range(20)
]
with (
mock.patch.object(matrix.slots, "chunk_size", return_value=10),
mock.patch.object(matrix.slots, "chunk_count", return_value=2),
mock.patch.object(matrix.slots, "chunk_blocks", return_value=3),
mock.patch.object(matrix.slots, "available", return_value=21),
):
chunks = matrix.chunks_of(entries, 0)
self.assertEqual(
[len(chunk) for chunk in chunks],
[1, 10, 10],
"the split must get every declared block, not only the ones the "
"budget fills, or the rows a short priority chunk leaves go unplanned",
)
def test_priority_chunks_are_sorted_on_their_own(self) -> None:
entries = [
_entry("web-app-z", "0", "compose", priority=True),
_entry("web-app-a", "0", "compose", priority=True),
_entry("web-app-b", "0", "compose"),
]
chunks = self._chunks(entries, size=9)
self.assertEqual([e["apps"] for e in chunks[0]], ["web-app-a", "web-app-z"])
self.assertEqual([e["apps"] for e in chunks[1]], ["web-app-b"])
_REGULAR = [
_entry("web-app-a", "0", "compose"),
_entry("web-app-b", "1", "swarm"),
_entry("web-app-b", "2", "compose"),
]
class TestRedundant(unittest.TestCase):
def _chunked(self, entries: list[dict]) -> list[dict]:
with (
mock.patch.object(matrix.slots, "chunk_size", return_value=10),
mock.patch.object(matrix.slots, "chunk_blocks", return_value=4),
mock.patch.object(matrix.slots, "available", return_value=99),
):
return [row for chunk in matrix.chunks_of(entries, 0) for row in chunk]
def test_a_covered_row_never_reaches_a_chunk(self) -> None:
entries = [_entry("web-app-a", "0", "compose", covered="7")]
self.assertEqual(self._chunked(entries), [])
def test_a_clone_never_reaches_a_chunk(self) -> None:
entries = [_entry("web-app-a", "0", "compose", clone=True)]
self.assertEqual(self._chunked(entries), [])
def test_a_plain_row_still_reaches_a_chunk(self) -> None:
entries = [_entry("web-app-a", "0", "compose")]
self.assertEqual(len(self._chunked(entries)), 1)
def test_a_pinned_clone_is_kept(self) -> None:
entries = [_entry("web-app-a", "0", "compose", priority=True, clone=True)]
self.assertEqual(len(self._chunked(entries)), 1)
class TestOffsetIndex(unittest.TestCase):
def test_nothing_given_starts_at_the_head(self) -> None:
for raw in (None, "", 0, "0"):
with self.subTest(raw=raw):
self.assertEqual(matrix.offset_index(raw, _REGULAR), 0)
def test_a_number_is_a_row_count(self) -> None:
self.assertEqual(matrix.offset_index("2", _REGULAR), 2)
def test_a_negative_count_reads_as_the_head(self) -> None:
self.assertEqual(matrix.offset_index("-5", _REGULAR), 0)
def test_a_role_token_starts_at_its_first_row(self) -> None:
self.assertEqual(matrix.offset_index("web-app-b", _REGULAR), 1)
def test_a_pinned_variant_starts_at_that_variant(self) -> None:
self.assertEqual(matrix.offset_index("web-app-b#2", _REGULAR), 2)
def test_a_pinned_mode_picks_the_row_of_that_mode(self) -> None:
self.assertEqual(matrix.offset_index("web-app-b#1@swarm", _REGULAR), 1)
def test_a_token_naming_no_regular_row_aborts(self) -> None:
with self.assertRaises(SystemExit):
matrix.offset_index("web-app-gone#3", _REGULAR)
def _row(app: str, variant: int) -> dict:
return {"name": app, "variant": variant, "test_compose": True}
class TestCandidates(unittest.TestCase):
_DISCOVERED: ClassVar[list] = [
_row("web-app-a", 0),
_row("web-app-b", 0),
_row("web-app-b", 1),
]
def _candidates(self, priority: str) -> list[dict]:
with mock.patch.object(
matrix.query, "discover_rows", return_value=list(self._DISCOVERED)
):
return matrix.candidates(
modes=("compose",), whitelist="", priority=priority, lifecycles=""
)
def _regular(self, priority: str) -> set[tuple[str, int]]:
return {
(row["name"], row["variant"])
for row in self._candidates(priority)
if not row["priority"]
}
def test_a_pinned_variant_leaves_its_siblings_in_the_regular_line(self) -> None:
self.assertEqual(
self._regular("web-app-b#0"), {("web-app-a", 0), ("web-app-b", 1)}
)
def test_a_pinned_variant_does_not_come_back_as_a_regular_row(self) -> None:
self.assertNotIn(("web-app-b", 0), self._regular("web-app-b#0"))
def test_a_bare_token_withdraws_the_whole_role(self) -> None:
with mock.patch.object(
matrix.query, "discover_rows", return_value=list(self._DISCOVERED)
) as discovered:
matrix.candidates(
modes=("compose",), whitelist="", priority="web-app-b", lifecycles=""
)
self.assertEqual(discovered.call_args.kwargs["blacklist"], "web-app-b")
if __name__ == "__main__":
unittest.main()