diff options
Diffstat (limited to 'app/services/merge_requests/update_service.rb')
-rw-r--r-- | app/services/merge_requests/update_service.rb | 191 |
1 files changed, 124 insertions, 67 deletions
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index 1707daff734..f5e14797f7e 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -31,54 +31,37 @@ module MergeRequests old_mentioned_users = old_associations.fetch(:mentioned_users, []) old_assignees = old_associations.fetch(:assignees, []) old_reviewers = old_associations.fetch(:reviewers, []) + old_timelogs = old_associations.fetch(:timelogs, []) + changed_fields = merge_request.previous_changes.keys - if has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees, old_reviewers: old_reviewers) - todo_service.resolve_todos_for_target(merge_request, current_user) - end + resolve_todos(merge_request, old_labels, old_assignees, old_reviewers) if merge_request.previous_changes.include?('title') || merge_request.previous_changes.include?('description') todo_service.update_merge_request(merge_request, current_user, old_mentioned_users) end - if merge_request.previous_changes.include?('target_branch') - create_branch_change_note(merge_request, - 'target', - target_branch_was_deleted ? 'delete' : 'update', - merge_request.previous_changes['target_branch'].first, - merge_request.target_branch) - - abort_auto_merge(merge_request, 'target branch was changed') - end - + handle_target_branch_change(merge_request) handle_assignees_change(merge_request, old_assignees) if merge_request.assignees != old_assignees - handle_reviewers_change(merge_request, old_reviewers) if merge_request.reviewers != old_reviewers - - if merge_request.previous_changes.include?('target_branch') || - merge_request.previous_changes.include?('source_branch') - merge_request.mark_as_unchecked - end - handle_milestone_change(merge_request) + handle_draft_status_change(merge_request, changed_fields) - added_labels = merge_request.labels - old_labels - if added_labels.present? - notification_service.async.relabeled_merge_request( - merge_request, - added_labels, - current_user - ) - end + track_title_and_desc_edits(changed_fields) + track_discussion_lock_toggle(merge_request, changed_fields) + track_time_estimate_and_spend_edits(merge_request, old_timelogs, changed_fields) + track_labels_change(merge_request, old_labels) - added_mentions = merge_request.mentioned_users(current_user) - old_mentioned_users + notify_if_labels_added(merge_request, old_labels) + notify_if_mentions_added(merge_request, old_mentioned_users) - if added_mentions.present? - notification_service.async.new_mentions_in_merge_request( - merge_request, - added_mentions, - current_user - ) + # Since #mark_as_unchecked triggers an update action through the MR's + # state machine, we want to push this as far down in the process so we + # avoid resetting #ActiveModel::Dirty + # + if merge_request.previous_changes.include?('target_branch') || + merge_request.previous_changes.include?('source_branch') + merge_request.mark_as_unchecked end end @@ -95,56 +78,128 @@ module MergeRequests MergeRequests::CloseService end - def before_update(issuable, skip_spam_check: false) - return unless issuable.changed? - - @issuable_changes = issuable.changes - end - def after_update(issuable) issuable.cache_merge_request_closes_issues!(current_user) + end - return unless @issuable_changes + private - %w(title description).each do |action| - next unless @issuable_changes.key?(action) + attr_reader :target_branch_was_deleted + + def track_title_and_desc_edits(changed_fields) + tracked_fields = %w(title description) + + return unless changed_fields.any? { |field| tracked_fields.include?(field) } + + tracked_fields.each do |action| + next unless changed_fields.include?(action) - # Track edits to title or description - # merge_request_activity_counter .public_send("track_#{action}_edit_action".to_sym, user: current_user) # rubocop:disable GitlabSecurity/PublicSend + end + end - # Track changes to Draft/WIP status - # - if action == "title" - old_title, new_title = @issuable_changes["title"] - old_title_wip = MergeRequest.work_in_progress?(old_title) - new_title_wip = MergeRequest.work_in_progress?(new_title) - - if !old_title_wip && new_title_wip - # Marked as Draft/WIP - # - merge_request_activity_counter - .track_marked_as_draft_action(user: current_user) - elsif old_title_wip && !new_title_wip - # Unmarked as Draft/WIP - # - merge_request_activity_counter - .track_unmarked_as_draft_action(user: current_user) - end - end + def track_discussion_lock_toggle(merge_request, changed_fields) + return unless changed_fields.include?('discussion_locked') + + if merge_request.discussion_locked + merge_request_activity_counter.track_discussion_locked_action(user: current_user) + else + merge_request_activity_counter.track_discussion_unlocked_action(user: current_user) end end - private + def track_time_estimate_and_spend_edits(merge_request, old_timelogs, changed_fields) + merge_request_activity_counter.track_time_estimate_changed_action(user: current_user) if changed_fields.include?('time_estimate') + merge_request_activity_counter.track_time_spent_changed_action(user: current_user) if old_timelogs != merge_request.timelogs + end - attr_reader :target_branch_was_deleted + def track_labels_change(merge_request, old_labels) + return if Set.new(merge_request.labels) == Set.new(old_labels) + + merge_request_activity_counter.track_labels_changed_action(user: current_user) + end + + def notify_if_labels_added(merge_request, old_labels) + added_labels = merge_request.labels - old_labels + + return unless added_labels.present? + + notification_service.async.relabeled_merge_request( + merge_request, + added_labels, + current_user + ) + end + + def notify_if_mentions_added(merge_request, old_mentioned_users) + added_mentions = merge_request.mentioned_users(current_user) - old_mentioned_users + + return unless added_mentions.present? + + notification_service.async.new_mentions_in_merge_request( + merge_request, + added_mentions, + current_user + ) + end + + def resolve_todos(merge_request, old_labels, old_assignees, old_reviewers) + return unless has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees, old_reviewers: old_reviewers) + + todo_service.resolve_todos_for_target(merge_request, current_user) + end + + def handle_target_branch_change(merge_request) + return unless merge_request.previous_changes.include?('target_branch') + + create_branch_change_note( + merge_request, + 'target', + target_branch_was_deleted ? 'delete' : 'update', + merge_request.previous_changes['target_branch'].first, + merge_request.target_branch + ) + + abort_auto_merge(merge_request, 'target branch was changed') + end + + def handle_draft_status_change(merge_request, changed_fields) + return unless changed_fields.include?("title") + + old_title, new_title = merge_request.previous_changes["title"] + old_title_wip = MergeRequest.work_in_progress?(old_title) + new_title_wip = MergeRequest.work_in_progress?(new_title) + + if !old_title_wip && new_title_wip + # Marked as Draft/WIP + # + merge_request_activity_counter + .track_marked_as_draft_action(user: current_user) + elsif old_title_wip && !new_title_wip + # Unmarked as Draft/WIP + # + notify_draft_status_changed(merge_request) + + merge_request_activity_counter + .track_unmarked_as_draft_action(user: current_user) + end + end + + def notify_draft_status_changed(merge_request) + notification_service.async.change_in_merge_request_draft_status( + merge_request, + current_user + ) + end def handle_milestone_change(merge_request) return if skip_milestone_email return unless merge_request.previous_changes.include?('milestone_id') + merge_request_activity_counter.track_milestone_changed_action(user: current_user) + if merge_request.milestone.nil? notification_service.async.removed_milestone_merge_request(merge_request, current_user) else @@ -159,6 +214,7 @@ module MergeRequests new_assignees = merge_request.assignees - old_assignees merge_request_activity_counter.track_users_assigned_to_mr(users: new_assignees) + merge_request_activity_counter.track_assignees_changed_action(user: current_user) end def handle_reviewers_change(merge_request, old_reviewers) @@ -170,6 +226,7 @@ module MergeRequests new_reviewers = merge_request.reviewers - old_reviewers merge_request_activity_counter.track_users_review_requested(users: new_reviewers) + merge_request_activity_counter.track_reviewers_changed_action(user: current_user) end def create_branch_change_note(issuable, branch_type, event_type, old_branch, new_branch) |