Write status rows on create and move without a license
What does this MR do and why?
Create and move only write a work_item_current_statuses row when the root namespace has the work_item_status license, because the status callback only runs when the license puts the widget on the work item. Items created or moved while a group was unlicensed never get a row, and the row backfills cannot cover future items. That breaks the status filter once it stops falling back to "no row" (!260617 (merged)).
This MR writes the row whenever the type has a lifecycle, behind work_item_status_rows_without_license (gitlab_com_derisk, removed in 19.7):
- Create: adds the status callback when the license filtered it out of the widget list, so the default row is written.
- Move and clone: adds the data-sync status handler the same way, and drops its license and widget early returns.
- The widget stays hidden where the tier does not expose it. Unlicensed namespaces get the row only: no status system note and no status event. Close and reopen keep the row in sync through the same service.
- The row write adds four queries to work item creation, which tips the REST create endpoint over the query limit it already sat at, so the endpoint threshold is raised to 110.
Flag-gated types (epic) keep the license gate: their validation still checks widget visibility, so an unlicensed epic row would fail. Separate change.
Not covered: imports and insert_all paths, tracked in the issue.
Open for discussion: the create hook lives in the EE create service override because the widget system assumes "no widget, no callback". Happy to move it.
References
- #633143 (closed)
- #633159
- Unblocks the wider rollout of !260617 (merged)
Screenshots or screen recordings
No UI change.
How to set up and validate locally
-
Run GDK with
GITLAB_SIMULATE_SAAS=1and use a group on the Free plan. In the console,group.licensed_feature_available?(:work_item_status)isfalse. -
Flag off: create an issue in a project of that group.
WorkItem.order(:created_at).last.current_status # => nil -
Enable the flag and create another issue.
Feature.enable(:work_item_status_rows_without_license)wi = WorkItem.order(:created_at).last wi.current_status # => row with system_defined_status_id 1 wi.widgets.map(&:type) # no :status, the widget stays hidden -
Move the issue to a project in another Free group: the new work item has a row, the original row is removed.
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.