mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(docs): documenter output is committed to the project repo, not just the knowledge store
Documenter docs only ever reached DOCS_BASE_PATH=/app/docs (a host-mounted, RAG-indexed knowledge store) and were never committed to the project's git repository — so the documenter's deliverable never landed in the repo. write_doc now also writes the doc into the agent's workspace clone under docs/<type>/<file> and commits it onto the task branch via GitService.commit, so it rides the existing PR into the repository on merge. Best-effort: a documenter without a cloned workspace or task branch still succeeds (logged, never fatal); the /app/docs knowledge store + RAG indexing are unchanged. Adds tests that the doc is written into the workspace and committed onto the task branch, and that it no-ops cleanly without a branch.
This commit is contained in:
@@ -802,3 +802,69 @@ async def test_list_docs_for_team_shallow_path_infers_readme(
|
||||
):
|
||||
docs = await svc._list_docs_for_team("backend")
|
||||
assert any(d.doc_type == "readme" for d in docs)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_commit_doc_to_repo_writes_into_workspace_and_commits(
|
||||
docs_setup: dict,
|
||||
db_session: AsyncSession,
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""A doc write also commits the file into the project repo on the task branch."""
|
||||
svc = docs_setup["svc"]
|
||||
task_id = docs_setup["task_id"]
|
||||
agent_uuid = docs_setup["agent_id"]
|
||||
|
||||
task = (
|
||||
await db_session.execute(select(TaskTable).where(TaskTable.id == task_id))
|
||||
).scalar_one()
|
||||
task.branch_name = "feature/backend/ABC12345"
|
||||
await db_session.flush()
|
||||
|
||||
mock_git = MagicMock()
|
||||
mock_git.get_workspace = AsyncMock(return_value=tmp_path)
|
||||
mock_git.commit = AsyncMock(return_value={"sha": "deadbeef"})
|
||||
monkeypatch.setattr(
|
||||
"roboco.services.git.get_git_service", lambda _session: mock_git
|
||||
)
|
||||
|
||||
req = WriteDocInput(
|
||||
task_id=task_id,
|
||||
filename="guide.md",
|
||||
doc_type="api",
|
||||
title="API Guide",
|
||||
content="# API Guide\n",
|
||||
)
|
||||
await svc._commit_doc_to_repo(str(agent_uuid), req, "api")
|
||||
|
||||
# The doc landed in the workspace repo under docs/...
|
||||
assert (tmp_path / "docs" / "api" / "guide.md").read_text() == "# API Guide\n"
|
||||
# ...and was committed onto the task branch.
|
||||
mock_git.commit.assert_awaited_once()
|
||||
kwargs = mock_git.commit.await_args.kwargs
|
||||
assert kwargs["branch_name"] == "feature/backend/ABC12345"
|
||||
assert kwargs["files"] == ["docs/api/guide.md"]
|
||||
assert kwargs["task_id"] == task_id
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_commit_doc_to_repo_skips_without_task_branch(
|
||||
docs_setup: dict, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""No task branch yet → best-effort no-op (no git commit, no raise)."""
|
||||
svc = docs_setup["svc"]
|
||||
mock_git = MagicMock()
|
||||
mock_git.commit = AsyncMock()
|
||||
monkeypatch.setattr(
|
||||
"roboco.services.git.get_git_service", lambda _session: mock_git
|
||||
)
|
||||
req = WriteDocInput(
|
||||
task_id=docs_setup["task_id"],
|
||||
filename="x.md",
|
||||
doc_type="api",
|
||||
title="X",
|
||||
content="x",
|
||||
)
|
||||
await svc._commit_doc_to_repo(str(docs_setup["agent_id"]), req, "api")
|
||||
mock_git.commit.assert_not_awaited()
|
||||
|
||||
Reference in New Issue
Block a user