Fix scoped label wildcards not persisting in saved views

What does this MR do and why?

Saved Views silently drop scoped label wildcard filters (e.g. label = workflow::*). Saving a view with this filter succeeds with no error, but the filter is gone on reload.

WorkItems::SavedViews::FilterNormalizerService only recognized the literal strings Any/None as label wildcards. A scoped wildcard like workflow::* fell through to find_label_ids, which does an exact-title lookup via LabelsFinder — workflow::* never matches a real label title, so it resolved to label_ids: [] and was saved as an empty filter with no warning.

The scoped-wildcard resolution needed here already exists and is used correctly by the live work items list filter (EE::Issuables::LabelFilter#find_label_ids_uncached, LIKE-based). Saved Views persistence just never reused it.

How this MR fixes it

Extends the EE override of label_wildcard? (ee/app/services/ee/work_items/saved_views/filter_normalizer_service.rb) to also recognize key::* patterns when scoped_labels is licensed. This routes the wildcard through the existing label_wildcard_id pass-through mechanism already used for Any/None — the pattern is stored as a literal string rather than resolved to IDs at save time, and gets correctly re-expanded via the existing LIKE-based logic when the saved view is actually loaded and queried. No changes needed on the read/sanitize side — that's already an unconditional pass-through for label_wildcard_id → label_name.

Screenshots (Before vs After)

image image

How to set up and validate locally

Requires a license with the scoped_labels feature (Premium/Ultimate).

  1. In a group with a licensed scoped_labels feature, create a couple of scoped labels, e.g. workflow::in dev, workflow::in review.
  2. Navigate to the group or project's Work Items list.
  3. Apply a scoped label wildcard filter: label = workflow::*.
  4. Save the view.
  5. Refresh the page or open the view in a new tab.
  6. Before this fix: the label filter is silently dropped on reload.
  7. After this fix: the saved view retains workflow::* and applies it on load, matching all labels under that scope.

Also verifiable directly against the service:

result = WorkItems::SavedViews::FilterNormalizerService.new(
  filter_data: { label_name: ['workflow::*'] },
  container: project, # or group, with scoped_labels licensed
  current_user: user
).execute

result.payload[:label_wildcard_id] # => "workflow::*" (previously label_ids: [])
  1. Confirm the added specs pass: bundle exec rspec ee/spec/services/ee/work_items/saved_views/filter_normalizer_service_spec.rb spec/services/work_items/saved_views/filter_sanitizer_service_spec.rb

References

Edited by Aryann Dwivedi

Merge request reports

Loading
Loading