mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(git): coordination root cuts a Main-PM integration branch per repo (#58)
The coordination/fan-out root carries a product (cell->repo map) but no
project of its own, and was forced branchless — so a cell's parent-branch
resolution fell back to the project default (master), and cell completion
merged each cell straight to master, bypassing the Main-PM integration
point and the CEO merge gate.
Per the locked branch model (master <- feature/main_pm/{root} <- cell <-
dev), the root is now the Main-PM integration point: on claim it cuts
feature/main_pm/{root} off master in EACH distinct repo the product spans
(monorepo => 1, multi-repo => N). Cells then branch off it via the existing
ancestor-branch resolution, so cell work never targets master.
- ProductService.distinct_project_ids: enumerate the repos a product spans
- TaskService._create_branch_in_project: project-parameterized branch
creation split out of _auto_create_branch
- TaskService._ensure_coordination_root_branches: cut the integration
branch in each repo; graceful empty when the product has no cell map yet
- _ensure_branch_for_task routes a product-backed root here, not to no-op
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
co-authored by
Renn F
parent
f36fb67bec
commit
6cce556536
@@ -8,7 +8,7 @@ session boundary and checks the method's contract.
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
@@ -644,11 +644,32 @@ async def test_ensure_branch_returns_existing_branch() -> None:
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ensure_branch_skips_coordination_task() -> None:
|
||||
"""A product-backed task with no repo of its own gets no branch (not raised)."""
|
||||
async def test_ensure_branch_coordination_root_cuts_integration_branch() -> None:
|
||||
"""A product-backed root cuts feature/main_pm/{root} in each product repo."""
|
||||
svc = TaskService(MagicMock())
|
||||
task = MagicMock(branch_name=None, project_id=None, product_id=uuid4())
|
||||
assert await svc._ensure_branch_for_task(task, uuid4()) == ""
|
||||
create_in_project = AsyncMock(return_value="feature/main_pm/root1234")
|
||||
_bind(svc, "_create_branch_in_project", create_in_project)
|
||||
product_svc = MagicMock(distinct_project_ids=AsyncMock(return_value=[uuid4()]))
|
||||
project_svc = MagicMock(get=AsyncMock(return_value=MagicMock()))
|
||||
with (
|
||||
patch("roboco.services.product.get_product_service", return_value=product_svc),
|
||||
patch("roboco.services.project.get_project_service", return_value=project_svc),
|
||||
):
|
||||
result = await svc._ensure_branch_for_task(task, uuid4())
|
||||
assert result == "feature/main_pm/root1234"
|
||||
create_in_project.assert_awaited_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ensure_branch_coordination_root_no_cell_map_stays_branchless() -> None:
|
||||
"""A product with no cell->repo map yet stays branchless (graceful fallback)."""
|
||||
svc = TaskService(MagicMock())
|
||||
task = MagicMock(branch_name=None, project_id=None, product_id=uuid4())
|
||||
product_svc = MagicMock(distinct_project_ids=AsyncMock(return_value=[]))
|
||||
with patch("roboco.services.product.get_product_service", return_value=product_svc):
|
||||
result = await svc._ensure_branch_for_task(task, uuid4())
|
||||
assert result == ""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
Reference in New Issue
Block a user