[F102] make project_id mandatory on pr_target (close cross-repo pr_number collision)

This commit is contained in:
Renn F
2026-06-28 21:32:52 +02:00
parent c34e978f9e
commit f8cd5c5e7f
3 changed files with 34 additions and 33 deletions
+12 -9
View File
@@ -3955,8 +3955,8 @@ class GitService(BaseService):
self,
pr_number: int,
*,
project_id: UUID,
actor_agent_id: UUID | None = None,
project_id: UUID | None = None,
) -> str:
"""Return the current target (base) branch of an open PR.
@@ -3965,19 +3965,22 @@ class GitService(BaseService):
``submit_qa`` has cleared ``assigned_to`` without ValidationError.
``pr_number`` alone is ambiguous across projects (GitHub numbers PRs
per-repo), so when the caller knows which project the PR belongs to it
MUST pass ``project_id`` — the task lookup is then scoped to it so a
same-numbered PR in another project's repo is never resolved by
accident (mirrors ``close_pull_request``).
per-repo, but ``tasks.pr_number`` stores the bare integer with no repo
scoping, so two tasks on different repos can share a number). The
caller MUST pass the ``project_id`` the PR belongs to — the task lookup
is scoped to it so a same-numbered PR in another project's repo is
never resolved by accident. Mirrors :meth:`pr_merge`.
"""
from sqlalchemy import select
from roboco.db.tables import TaskTable as _TaskTable
stmt = select(_TaskTable).where(_TaskTable.pr_number == pr_number)
if project_id is not None:
stmt = stmt.where(_TaskTable.project_id == project_id)
result = await self.session.execute(stmt.limit(1))
result = await self.session.execute(
select(_TaskTable)
.where(_TaskTable.pr_number == pr_number)
.where(_TaskTable.project_id == project_id)
.limit(1)
)
task = result.scalar_one_or_none()
if task is None:
raise NotFoundError("PR", str(pr_number))