Render group level work item label notes against the group

This fixes the resource parent used when rendering a label system note on a group-level work item. work_item_synthetic_system_note in app/models/concerns/work_item_resource_event.rb passed work_item.project as the note's resource parent. A group-level work item has no project, so the parent came out nil, the Banzai label reference filter had nothing to resolve against, and the note fell back to raw text such as "added ~52 label" instead of a linked label chip.

Issue#resource_parent already returns the project for project-level issuables and the namespace (group) otherwise, so the fix is to call that instead of reading project directly. Project-level work items are unaffected.

Part of the stack for #628135 (INC-12449), targeting master. Merge in this order. The numbers follow the branch names, so there is no MR 2: that change was folded into MR 3 and !255083 (closed) is closed.

  • MR 1 (!255082 (merged)): Render group level work item label notes against the group <-- this MR
  • MR 3 (!255091 (merged)): Store the label event reference when the event is written
  • MR 4 (!255092): Delete label events when their label is deleted
    • MR 4c (!257979): Validate the cascade foreign key, %19.6, branches off MR 4 and merges after MR 4 is deployed
  • MR 4b (!255238): Record deleted label events in the label audit event
  • MR 5 (!255093): Link a project label in a group context to its project
  • MR 6 (!255096): Backfill the reference on existing label events
  • MR 7 (!255097): Stop writing the label event reference on a read request

This is the first MR of a 7-part stack that fixes INC-12449: a GET request to Projects::NotesController#index was lazily computing and saving resource_label_events.reference, turning a read into a write. This MR does not touch that write path; it fixes a separate rendering bug in the group-level case that the rest of the stack builds on.

How to reproduce and check by hand

On a group-level work item (an epic), the label system note renders as raw text, "added ~52 label", instead of a clickable label chip. Project-level issues are not affected.

In the UI:

  1. Create a group and a group label in it.
  2. Create an epic in that group and add the label to it.
  3. Open the epic and read the activity feed entry.

In a rails console (gdk rails console), wrapped in a transaction that rolls back, so it leaves nothing behind:

ActiveRecord::Base.transaction do
  user   = User.find_by_username('root')
  org    = user.organizations.first
  suffix = SecureRandom.hex(4)

  group = Groups::CreateService.new(user, name: "repro-#{suffix}", path: "repro-#{suffix}",
                                    organization_id: org.id).execute[:group]
  group.add_owner(user)
  label = Labels::CreateService.new(user, title: 'grouplabel').execute(group: group)
  epic  = WorkItem.create!(
    namespace: group, author: user, title: 'repro 628135',
    work_item_type: WorkItems::TypesFramework::Provider.new(group).find_by_base_type(:epic)
  )

  ResourceEvents::ChangeLabelsService.new(epic, user).execute(added_labels: [label])
  note = epic.resource_label_events.last.work_item_synthetic_system_note

  puts "resource_parent: #{note.resource_parent.inspect}"
  puts "html:            #{note.note_html}"

  raise ActiveRecord::Rollback
end

Observed output

The script above was run on the parent branch and on this branch; what follows is the actual output from both runs.

Before, on master:

resource_parent: nil
html:            <p dir="auto">added ~1 label</p>
pushed label:      live-before (id=3)
resource_parent:   nil
subscription html: <p dir="auto">added ~3 label</p>

After, on 628135-01-work-item-note-parent:

resource_parent: #<Group id:98 @repro-095de8c9>
html:            <p dir="auto">added <span class="gl-label"><a href="/groups/repro-095de8c9/-/work_items?label_name=grouplabel" title="" class="gfm gfm-label has-tooltip gl-link gl-label-link" data-original="~6" data-link="false" data-link-reference="false" data-label="6" data-group="98" data-namespace="98" data-html="true" data-container="body" data-placement="top" data-reference-type="label"><span class="gl-label-text gl-label-text-light" data-container="body" data-html="true" style="background-color: #6699cc">grouplabel</span></a></span> label</p>

The same thing in the browser. First, the epic's activity feed at page load on the parent branch, before anything is added out of band:

mr01-before-1-feed-at-load

Then the same open page after a label is added from a second session:

Before, on master After, on 628135-01-work-item-note-parent
mr01-before-2-feed-after-live-add mr01-after-2-feed-after-live-add
The feed still ends at live-before-2. The new entry is in the database and shows on reload, but never arrives live. live-after-1 appears on the open page, timestamped "just now", with no reload.

work_item_synthetic_system_note is called only by the workItemNoteCreated GraphQL subscription, so this fix changes what an already-open page receives, not what a fresh page load renders. With an epic open, adding a label out of band never showed up in the activity feed on the parent branch; on this branch it appeared right away, timestamped "just now", with no reload. A manual reload showed the note on both branches, so the stored row was fine all along; the subscription payload was the broken part.

Both runs were done on a disposable GDK box whose GDK was at master 8d8af6729f, with each branch applied over it as a runtime-only patch and migrations run for real where the branch adds them.

Testing

resource_label_event_spec gains coverage for the group-level case in the work_item_synthetic_system_note shared examples, and fails on this branch without the change. The surrounding set - resource_label_event_spec, label_note_spec (CE and EE), and the synthetic label notes builder service spec - runs 109 examples, 0 failures.

Related to #628135

Edited by Alexandru Croitor

Merge request reports

Loading
Loading