feat: add repository rename orchestration CLI
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 25s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a049a4-ee9f-78e1-9d66-2cb0f9bea3e3
This commit is contained in:
tegwick 2026-08-29 12:00:22 +02:00
parent 6312db8700
commit 6b82215ae7
11 changed files with 1373 additions and 4 deletions

View file

@ -695,7 +695,22 @@ async def create_operation(
gateway: ForgeRepositoryGateway,
repo_id: uuid.UUID,
body: RepositoryRenameOperationCreate,
) -> RepositoryRenameOperation:
) -> tuple[RepositoryRenameOperation, bool]:
if body.operation_id is not None:
existing = await session.get(RepositoryRenameOperation, body.operation_id)
if existing is not None:
if (
existing.repo_id != repo_id
or existing.new_slug != body.new_slug
or existing.actor != body.actor
or body.confirmation
!= confirmation_for(repo_id, existing.old_slug, existing.new_slug)
):
raise RenamePreconditionFailed(
"Repository rename operation ID is already bound to another request"
)
return existing, True
token = _verify_preflight_token(body.preflight_token)
if token.get("repo_id") != str(repo_id) or token.get("new_slug") != body.new_slug:
raise RenamePreconditionFailed("Preflight token does not address this rename")
@ -730,6 +745,7 @@ async def create_operation(
forge = preflight["current"]["forge"]
now = utcnow()
operation = RepositoryRenameOperation(
id=body.operation_id or uuid.uuid4(),
repo_id=repo.id,
forge_identity_id=identity.id,
forge_identity_state="verified",
@ -777,10 +793,33 @@ async def create_operation(
await session.commit()
except IntegrityError as exc:
await session.rollback()
if body.operation_id is not None:
existing = await session.get(RepositoryRenameOperation, body.operation_id)
if (
existing is not None
and existing.repo_id == repo_id
and existing.new_slug == body.new_slug
and existing.actor == body.actor
and body.confirmation
== confirmation_for(repo_id, existing.old_slug, existing.new_slug)
):
return existing, True
raise RenamePreconditionFailed(
"A conflicting repository rename operation was created"
) from exc
await session.refresh(operation)
return operation, False
async def load_operation_by_id(
session: AsyncSession,
operation_id: uuid.UUID,
) -> RepositoryRenameOperation:
operation = await session.get(RepositoryRenameOperation, operation_id)
if operation is None:
raise RenameNotFound(
f"Repository rename operation {operation_id} was not found"
)
return operation