Support transferring burned_project_routes and agent_organization_authorizations on org group transfer
Depends on !247673 (merged)
What does this MR do and why?
Adds organization transfer support for 2 infrastructure tables during group organization transfer:
burned_project_routes— filtered by path prefix (LOWER(path) LIKE '<group full path>/%') usingsanitize_sql_liketo escape special characters. Conflicting source-org burns (where the target org already has a burn for the same path) are deleted before the remaining burns are moved — the target org's row already protects those paths, making the source row redundant.agent_organization_authorizations— correlatedEXISTSonnamespaces.traversal_idsto find agents belonging to projects in the hierarchy.
Both tables are on gitlab_main_org schema, so they are updated
synchronously inside the GroupsService transaction using the existing
update_organization_id_for helper from OrganizationUpdater.
The transfer_infrastructure step runs after transfer_topics and before
schedule_ci_runners_transfer / event publishing.
Migration
AddPatternOpsIndexToBurnedProjectRoutes adds a text_pattern_ops index on
(organization_id, lower(path)) to support the LIKE prefix query used by
transfer_burned_project_routes.
Why pool_repositories is no_work_needed
pool_repositories is a shared resource: a single pool can serve multiple
member projects (forks) across different groups and organizations. During org
transfer, all transferred projects are disconnected from their pool via
LeavePoolRepositoryWorker, so the pool record stays behind for its
remaining members in the old organization. Updating its organization_id
to the new org would break it for those other projects. The table is
therefore marked organization_transfer_support: no_work_needed.
config/organizations/transfer_support.yml changes
burned_project_routes:todo→supportedagent_organization_authorizations:todo→supportedpool_repositories:todo→no_work_needed
References
- Parent issue: #611975 (closed)
- Related epic: &21846
How to set up and validate locally
- Create two organizations, a top-level group in the first org, with a subgroup and projects
- Create records for each table linked to the projects:
burned = Authn::BurnedProjectRoute.create!(organization: org1, project_id: project.id, path: project.full_path, burned_at: Time.current) agent = Clusters::Agent.create!(project: project, name: 'test') auth = Clusters::Agents::Authorizations::CiAccess::OrganizationAuthorization.create!(agent: agent, organization: org1, config: {}) - Transfer the group:
Organizations::Transfer::GroupsService.new(group: group, new_organization: org2, current_user: user).execute - Verify all records now have
organization_idmatchingorg2
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.