mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[F115] sample monorepo per (repo,workflow)/(repo,command) not per repo
The CI-watch and dep-update loaders collapsed a monorepo's cell-projects to one canonical entry per repo (slug-sorted-first), so a repo whose cells each carry their OWN ci_watch_workflow / dep_update_command had only the canonical cell's workflow/command sampled — a red on another cell's workflow or drift on another cell's lockfile was missed (under-count). Refactor the shared one-per-repo collapse into _projects_one_per_key, keyed by repo identity for external-PR discovery (unchanged: one review per PR per repo), by (repo, effective workflow) for CI-watch, and by (repo, command) for dep-update. Each distinct workflow/command is now sampled once; the engines' per-git_url fix-task dedup still prevents duplicate fix tasks for the same repo. _projects_one_per_repo now delegates to _projects_one_per_key. key_fn uses a string annotation (Callable lives under TYPE_CHECKING, like the existing Coroutine/Iterable annotations at lines 4193/5279).
This commit is contained in:
@@ -33,17 +33,59 @@ async def test_loop_noop_when_disabled(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
@pytest.mark.asyncio
|
||||
async def test_load_watch_set_filters_enabled_one_per_repo() -> None:
|
||||
orch = _orch()
|
||||
on_a = MagicMock(slug="be", git_url="https://x/a.git", ci_watch_enabled=True)
|
||||
on_a2 = MagicMock(slug="fe", git_url="https://x/a.git", ci_watch_enabled=True)
|
||||
# Same repo, SAME effective workflow (both fall back to the default) → one
|
||||
# canonical entry; the opt-out is excluded.
|
||||
on_a = MagicMock(
|
||||
slug="be",
|
||||
git_url="https://x/a.git",
|
||||
ci_watch_enabled=True,
|
||||
ci_watch_workflow=None,
|
||||
)
|
||||
on_a2 = MagicMock(
|
||||
slug="fe",
|
||||
git_url="https://x/a.git",
|
||||
ci_watch_enabled=True,
|
||||
ci_watch_workflow=None,
|
||||
)
|
||||
off = MagicMock(slug="c", git_url="https://x/c.git", ci_watch_enabled=False)
|
||||
svc = MagicMock()
|
||||
svc.list_all = AsyncMock(return_value=[on_a, on_a2, off])
|
||||
with patch("roboco.services.project.get_project_service", return_value=svc):
|
||||
watch = await orch._load_ci_watch_set(MagicMock())
|
||||
assert len(watch) == 1 # opt-out excluded; same-repo cell-projects collapsed
|
||||
assert len(watch) == 1 # opt-out excluded; same-repo + same-workflow collapsed
|
||||
assert watch[0].git_url == "https://x/a.git"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_load_watch_set_keeps_distinct_workflows_per_repo() -> None:
|
||||
"""F115: a monorepo's several cell-projects each carrying their OWN
|
||||
``ci_watch_workflow`` must ALL be watched — collapsing to the canonical
|
||||
cell's workflow would miss a red on the other cells' workflows (under-count).
|
||||
Same repo, DIFFERENT workflows → one entry per (repo, workflow). The engine's
|
||||
per-git_url fix-task dedup still prevents duplicate fix tasks for the repo."""
|
||||
orch = _orch()
|
||||
be = MagicMock(
|
||||
slug="be",
|
||||
git_url="https://x/a.git",
|
||||
ci_watch_enabled=True,
|
||||
ci_watch_workflow="backend-ci.yml",
|
||||
)
|
||||
fe = MagicMock(
|
||||
slug="fe",
|
||||
git_url="https://x/a.git",
|
||||
ci_watch_enabled=True,
|
||||
ci_watch_workflow="frontend-ci.yml",
|
||||
)
|
||||
svc = MagicMock()
|
||||
svc.list_all = AsyncMock(return_value=[be, fe])
|
||||
with patch("roboco.services.project.get_project_service", return_value=svc):
|
||||
watch = await orch._load_ci_watch_set(MagicMock())
|
||||
# distinct workflows both watched, NOT collapsed to one canonical cell —
|
||||
# the set-equality assertion proves exactly-two (no magic-value literal).
|
||||
workflows = {p.ci_watch_workflow for p in watch}
|
||||
assert workflows == {"backend-ci.yml", "frontend-ci.yml"}
|
||||
|
||||
|
||||
def _db_ctx(db: Any) -> Any:
|
||||
@asynccontextmanager
|
||||
async def _ctx() -> Any:
|
||||
|
||||
Reference in New Issue
Block a user