Organizations Feature Parity: Create – Import
## Overview This epic tracks the work required to make **Import** features fully compatible with Organizations feature parity. ## Context - [Self-assessment](https://gitlab.com/gitlab-com/gl-infra/tenant-scale/organizations/organizations-feature-parity/-/work_items/14) - [Feature parity epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/work_items/1871) ## Components - Direct Transfer - GitHub Importer - Bitbucket Cloud - Bitbucket Server - Import by URL - FogBugz - Gitea - Manifest - File-based Import/Export - Webhooks ## Issues | Priority | Status | Issue | Milestone | Latest update | |----------|--------|-------|-----------|---------------| | 1 | :white_check_mark: Closed | [Scope DB uniqueness constraints (Direct Transfer) #595675](https://gitlab.com/gitlab-org/gitlab/-/issues/595675) | Completed in %19.1 | Closed 2026-06-03. `bulk_import_batch_trackers` org-scoped index shipped via [!237014](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/237014) + [!237069](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/237069). `bulk_import_trackers` resolved as not-needed (already cell-safe via the cluster-unique sequence FK). Third index split out to #600457. | | 2 | :white_check_mark: Closed | [Scope stale import queries (Direct Transfer) #595673](https://gitlab.com/gitlab-org/gitlab/-/issues/595673) | Completed in %19.1 | Closed 2026-06-10. Transformers + `GroupLoader` lookups scoped to the import organization via [!238772](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/238772) (MR-C). Earlier resolver MR [!238181](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/238181) closed by design (made the `isolated?` gate dead code; reverted to the [!236603](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/236603) baseline). Cron-worker portion is a no-op per the cell-wide cron decision. | | 3 | :white_check_mark: Closed | [Cross-org entity validation (Direct Transfer) #595674](https://gitlab.com/gitlab-org/gitlab/-/issues/595674) | Completed in %19.1 | Closed 2026-05-21 via [!236603](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/236603). Rejects Direct Transfer imports crossing org boundaries when either side is `isolated?`; mirrors `Members::CreatorService#commit_member`, no-op for non-isolated orgs. | | 4 | :white_check_mark: Closed | [Update organization_transfer_support YAMLs #595676](https://gitlab.com/gitlab-org/gitlab/-/issues/595676) | Completed in %19.0 | Closed 2026-05-12. Marked import-related tables (`bulk_import_*`, `web_hooks`, `integrations`, `web_hook_logs_daily`) as `no_work_needed`. Shipped via [!233779](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/233779) + [!234790](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/234790). | | 5 | :yellow_circle: In Review | [Add org scoping to import routes (GitHub, Gitea, BulkImports API) #595677](https://gitlab.com/gitlab-org/gitlab/-/issues/595677) | Planned for %19.1 | In review. Community contribution from @DhairyaMajmudar — [!237093](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/237093) scopes GitHub controller params + service `target_namespace`, adds GitHub API `set_current_organization`, and moves BulkImports API org-setting to a top-level `before`. Gitea fixed via controller inheritance. File-based + admin Webhooks split out to #600458. | | 6 | :white_check_mark: Closed | [Scope prune_expired_export_jobs (File-based) #595681](https://gitlab.com/gitlab-org/gitlab/-/issues/595681) | Completed in %19.0 | Closed 2026-05-13 as no-op. Cell-wide cleanup crons don't need per-org iteration; the sharding key already scopes per cell ([decision](https://gitlab.com/gitlab-com/gl-infra/tenant-scale/organizations/organizations-feature-parity/-/work_items/14#note_3338397127)). [!234874](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/234874) closed without merging. | | 7 | :white_check_mark: Closed | [Propagate org context in Webhook workers #595678](https://gitlab.com/gitlab-org/gitlab/-/issues/595678) | Completed in %19.1 | Closed 2026-05-21. Derives `organization_id` from the hook record in `web_hook_worker.rb` and `log_execution_worker.rb` (approach confirmed by @rutgerwessels; `GroupHook` is EE-only, so the fix has a FOSS/EE split). | | 8 | :white_check_mark: Closed | [Add organization_id to logs/audit/usage (Direct Transfer + GitHub) #595679](https://gitlab.com/gitlab-org/gitlab/-/issues/595679) | Completed in %19.1 | Closed 2026-06-15 via [!239120](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/239120). Adds `organization_id` to structured logs for Direct Transfer + GitHub. Remaining 8 components split out to #600459. | | 9 | :large_blue_circle: Open | [Add org context to RSpec/QA tests (Direct Transfer + GitHub) #595680](https://gitlab.com/gitlab-org/gitlab/-/issues/595680) | Planned for %19.1 | Ready for development, no MR yet. Will use `create(:organization)` and assert `organization_id` in Direct Transfer + GitHub specs. Remaining 7 components split out to #600460. | | 10 | :white_circle: Spike | [Spike: Investigate org-level CRUD for Integrations and System Hooks #598315](https://gitlab.com/gitlab-org/gitlab/-/issues/598315) | Backlog | In refinement. Scoping doc for moving instance-level Integrations and System Hooks to org level. Ownership question (Import team vs Organizations-team framework) still open. | | 11 | :white_check_mark: Closed | [Resolve `BulkImport.organization_id` decoupling #598525](https://gitlab.com/gitlab-org/gitlab/-/issues/598525) | Completed in %19.1 | Closed 2026-05-20. Resolution: both tables `no_work_needed` (follow parent `BulkImport`, which isn't group-transferred). | | 12 | :yellow_circle: In Review | [[1/3] Add organization_id to bulk_import_exports (parent table) #600457](https://gitlab.com/gitlab-org/gitlab/-/issues/600457) | Milestone **%19.2** | In review. Step 1 of 3 (split out of #595675, then split again for milestone viability). Adds `organization_id` + index + FK + sharding-key trigger + queue backfill to the **parent** `bulk_import_exports` (must be scoped before the child). MRs [!241088](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/241088) + [!241089](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/241089). Production row counts (~7.6M parent / ~808K child) ruled out inline backfill, so BBM path across 3 milestones. | | 13 | :large_blue_circle: Open | [Add org scoping to File-based controllers + admin Webhooks #600458](https://gitlab.com/gitlab-org/gitlab/-/issues/600458) | Milestone **%19.2** | Open. Split out of #595677. File-based `imports_controller.rb` (projects/groups) + `admin/hooks_controller.rb`. | | 14 | :large_blue_circle: Open | [Add `organization_id` to remaining 8 Import component loggers #600459](https://gitlab.com/gitlab-org/gitlab/-/issues/600459) | Milestone **%19.2** | Open. Split out of #595679. Bitbucket Cloud/Server, Import-by-URL, FogBugz, Gitea, Manifest, File-based, Webhooks. | | 15 | :large_blue_circle: Open | [Add organization context to remaining 7 Import component specs #600460](https://gitlab.com/gitlab-org/gitlab/-/issues/600460) | Milestone **%19.2** | Open. Split out of #595680. Matches the logger work in #600459. | | 16 | :white_check_mark: Closed | [Cross-org validation (Offline Transfer) #600608](https://gitlab.com/gitlab-org/gitlab/-/issues/600608) | Completed in %19.1 | Closed 2026-06-15 via [!239611](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/239611). Applies the same `isolated?`-gated cross-org check from #595674 to `Import::Offline::Imports::CreateService`. | | 17 | :large_blue_circle: Open | [[2/3] Add organization_id to bulk_import_export_batches (child table) #603592](https://gitlab.com/gitlab-org/gitlab/-/issues/603592) | Milestone **%19.3** | Open. Step 2 of 3, follows #600457. Finalize the parent backfill, then add `organization_id` + index + FK + single-hop backfill (from the parent row) to the **child** `bulk_import_export_batches`. Gated on the parent backfill completing on prod. | | 18 | :large_blue_circle: Open | [[3/3] Org-scoped unique index + NOT NULL on bulk_import_export_batches #603593](https://gitlab.com/gitlab-org/gitlab/-/issues/603593) | Milestone **%19.4** | Open. Step 3 of 3, follows #603592. The original goal: swap the unique index to the org-scoped variant `(export_id, batch_number, organization_id)`, drop the legacy index, add NOT NULL + validate FKs, move `organization_id` into the active sharding key. Gated on the child backfill completing on prod. | **Priority rationale**: - [DB index changes #595675](https://gitlab.com/gitlab-org/gitlab/-/issues/595675) go first since they require longer review cycles. - Core data scoping issues ([stale queries #595673](https://gitlab.com/gitlab-org/gitlab/-/issues/595673), [cross-org validation #595674](https://gitlab.com/gitlab-org/gitlab/-/issues/595674)) follow. - [YAML updates #595676](https://gitlab.com/gitlab-org/gitlab/-/issues/595676) are mechanical `no_work_needed` flips; the blocked subset is split out into [#598525](https://gitlab.com/gitlab-org/gitlab/-/issues/598525). - [Route scoping #595677](https://gitlab.com/gitlab-org/gitlab/-/issues/595677) is the most complex functional change. - Low-hanging infra fixes ([prune jobs #595681](https://gitlab.com/gitlab-org/gitlab/-/issues/595681), [webhook workers #595678](https://gitlab.com/gitlab-org/gitlab/-/issues/595678)) next. - [Observability #595679](https://gitlab.com/gitlab-org/gitlab/-/issues/595679) and [tests #595680](https://gitlab.com/gitlab-org/gitlab/-/issues/595680) last since they benefit from the functional changes landing first. - [Spike #598315](https://gitlab.com/gitlab-org/gitlab/-/issues/598315) and [blocked subset #598525](https://gitlab.com/gitlab-org/gitlab/-/issues/598525) run in parallel, gated on external decisions. - The `bulk_import_export_batches` sharding-key work (originally #600457) was further split into 3 milestone-scoped issues (#600457 → #603592 → #603593) for viability: the parent table must be org-scoped and backfilled on prod before the child, and each batched background migration must run on prod between milestones. **Blocking**: None of these issues strictly block each other. They can be worked in parallel. [Tests #595680](https://gitlab.com/gitlab-org/gitlab/-/issues/595680) have a soft dependency on the functional issues since tests should reflect those changes. The 3-part `bulk_import_export_batches` chain (#600457 → #603592 → #603593) is strictly sequential across milestones. ## People - DRI: `@reza-marandi` - Engineering Manager: `@thiagocsf`
epic