[go: up one dir, main page]

Add support for migration of statuses in direct transfer

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Currently Issue statuses, or custom statuses, aren't imported during direct transfer. Without these, project board lists based on statuses cannot be imported either.

Statuses are found through the Issue#current_status method:

pry(main)> issue.current_status

WorkItems::Statuses::CurrentStatus Load (0.8ms)  SELECT "work_item_current_statuses".* FROM "work_item_current_statuses" WHERE "work_item_current_statuses"."work_item_id" = 1747 LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_hostname:cdrago--20250425-7XQVQ,console_username:carladrago,line:(pry):57:in `__pry__'*/

=> #<WorkItems::Statuses::CurrentStatus:0x000000033675c3d8
 id: 18,
 namespace_id: 407,
 work_item_id: 1747,
 system_defined_status_id: 2,
 custom_status_id: nil,
 updated_at: Thu, 28 Aug 2025 15:35:50.692281000 UTC +00:00>

The Gitlab::ImportExport::Base::ObjectBuilder then needs to be updated to connect/create the status records.

From discussion on a related MR:

For context, when the import process needs to associate records with existing records, it finds the existing records using Gitlab::ImportExport::Base::ObjectBuilder, which relies on unique attributes to locate the corresponding record. For example, to find an existing label, the title is used.

On Project, I think the status list isn't imported because the system_defined_status_identifier field is marked as ignored. Because of that, the ProjectLabel is built without the required field, making the list invalid.

Take the tree below:

tree:
  project:
    boards:
      - lists:
        - label:

And the following NDJSON file:

{
  "name": "Board"
  "lists": [
    {
      "list_type": "label",
      "label": {
        "title": "Label 1",
        "type": "ProjectLabel"
      }
    },
    {
      "list_type": "status",
      "system_defined_status_identifier: 2
    }
  ]
}

During the import process, a Board object is created along with the nested lists. Since label is marked as EXISTING_OBJECT_RELATIONS, the object builder attempts to find an existing label with the title "Label 1" and associates it with the list.

As mentioned above, the system_defined_status_identifier is ignored. So, the second list is created without the field.

So, at the end, the following object is built:

Board.new(
  name: "Board", 
  lists: [
    ProjectLabel.new(list_type: "label", label_id: <ID of the existing "Label 1" found via Object builder>,
    ProjectLabel.new(list_type: "status"]
  ]
)

Then, when the board record is saved by Gitlab::ImportExport::Base::RelationObjectSaver, the status list should be ignored, as it is invalid.

By the way, List status also supports Custom Status, which is a different association that appears to be stored in the top-level group.

Edited by 🤖 GitLab Bot 🤖