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
statuslist isn't imported because thesystem_defined_status_identifierfield is marked as ignored. Because of that, theProjectLabelis 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
labelis 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_identifieris 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.