Recover external repository renames through verified Forgejo redirects
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 24s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a070b5-4994-7271-bd8b-7c3dbcedec4b
This commit is contained in:
tegwick 2026-09-05 18:57:15 +02:00
parent 022cf4b727
commit fe6b8d96c2
4 changed files with 166 additions and 2 deletions

View file

@ -929,3 +929,78 @@ async def test_every_forward_phase_failure_is_retry_safe(client, rename_setup):
"consumers-verified",
"completed",
}
@pytest.mark.asyncio
@pytest.mark.parametrize('location', [
'/api/v1/repos/coulomb/access-engine',
'https://forge.example/api/v1/repos/coulomb/access-engine',
])
async def test_resume_external_rename_with_verified_old_coordinate_redirect(client, rename_setup, location):
from api.services.forge_repository import ForgeRepositoryRedirected
repo, forge = rename_setup
operation, confirmation = await _operation(client, repo['id'], await _preflight(client, repo['id']))
forge.name = 'access-engine' # operator renamed before the journal advanced
inspect = forge.inspect
async def redirected(**kwargs):
if kwargs['name'] == 'flex-auth':
raise ForgeRepositoryRedirected('https://forge.example/api/v1/repos/coulomb/flex-auth', location)
return await inspect(**kwargs)
forge.inspect = redirected
result = await _phase(client, repo['id'], operation['id'], 'forge-renamed', 'preflighted', confirmation)
assert result['phase'] == 'forge-renamed'
assert forge.rename_calls == 0
rebound = await _phase(client, repo['id'], operation['id'], 'statehub-rebound', 'forge-renamed', confirmation)
assert rebound['phase'] == 'statehub-rebound'
@pytest.mark.asyncio
@pytest.mark.parametrize('location,wrong_identity', [
('https://evil.example/api/v1/repos/coulomb/access-engine', False),
('/api/v1/repos/other/access-engine', False),
('', False),
('/api/v1/repos/coulomb/access-engine', True),
])
async def test_redirect_resume_rejects_wrong_target_or_identity(client, rename_setup, location, wrong_identity):
from api.services.forge_repository import ForgeRepositoryRedirected
repo, forge = rename_setup
operation, confirmation = await _operation(client, repo['id'], await _preflight(client, repo['id']))
forge.name = 'access-engine'
if wrong_identity:
forge.repository_id += 1
inspect = forge.inspect
async def redirected(**kwargs):
if kwargs['name'] == 'flex-auth':
raise ForgeRepositoryRedirected('https://forge.example/api/v1/repos/coulomb/flex-auth', location)
return await inspect(**kwargs)
forge.inspect = redirected
response = await client.post(
f"/repos/{repo['id']}/rename/operations/{operation['id']}/phases/forge-renamed",
json={'expected_phase': 'preflighted', 'confirmation': confirmation},
)
assert response.status_code == 412
assert forge.rename_calls == 0
status = (await client.get(f"/repository-renames/operations/{operation['id']}")).json()
assert status['phase'] == 'preflighted'
@pytest.mark.asyncio
async def test_forge_http_redirect_is_reported_without_following(monkeypatch):
import httpx
from api.services.forge_repository import ForgejoRepositoryGateway, ForgeRepositoryRedirected
seen = []
def handler(request):
seen.append(str(request.url))
return httpx.Response(307, headers={'location': '/api/v1/repos/coulomb/access-engine'})
original = httpx.AsyncClient
monkeypatch.setattr(httpx, 'AsyncClient', lambda **kwargs: original(transport=httpx.MockTransport(handler), **kwargs))
with pytest.raises(ForgeRepositoryRedirected) as error:
await ForgejoRepositoryGateway()._inspect_with_token(instance='https://forge.example', owner='coulomb', name='flex-auth', token='test-only')
assert error.value.target_url == 'https://forge.example/api/v1/repos/coulomb/access-engine'
assert seen == ['https://forge.example/api/v1/repos/coulomb/flex-auth']