Ensure issuable state changes only fire webhooks once

* Webhooks for close and reopen events now fired in respective services only
* Prevents generic 'update' webhooks firing too
This commit is contained in:
Mark Fletcher 2016-12-14 20:45:39 +00:00
parent 2f736c6d41
commit 9f97fa4d9f
5 changed files with 37 additions and 1 deletions

View file

@ -184,7 +184,8 @@ class IssuableBaseService < BaseService
old_labels = issuable.labels.to_a
old_mentioned_users = issuable.mentioned_users.to_a
params[:label_ids] = process_label_ids(params, existing_label_ids: issuable.label_ids)
label_ids = process_label_ids(params, existing_label_ids: issuable.label_ids)
params[:label_ids] = label_ids if labels_changing?(issuable.label_ids, label_ids)
if params.present? && update_issuable(issuable, params)
# We do not touch as it will affect a update on updated_at field
@ -201,6 +202,10 @@ class IssuableBaseService < BaseService
issuable
end
def labels_changing?(old_label_ids, new_label_ids)
old_label_ids.sort != new_label_ids.sort
end
def change_state(issuable)
case params.delete(:state_event)
when 'reopen'

View file

@ -0,0 +1,4 @@
---
title: Ensure issuable state changes only fire webhooks once
merge_request:
author:

View file

@ -376,5 +376,10 @@ describe Issues::UpdateService, services: true do
let(:mentionable) { issue }
include_examples 'updating mentions', Issues::UpdateService
end
include_examples 'issuable update service' do
let(:open_issuable) { issue }
let(:closed_issuable) { create(:closed_issue, project: project) }
end
end
end

View file

@ -320,5 +320,10 @@ describe MergeRequests::UpdateService, services: true do
expect(issue_ids).to be_empty
end
end
include_examples 'issuable update service' do
let(:open_issuable) { merge_request }
let(:closed_issuable) { create(:closed_merge_request, source_project: project) }
end
end
end

View file

@ -0,0 +1,17 @@
shared_examples 'issuable update service' do
context 'changing state' do
before { expect(project).to receive(:execute_hooks).once }
context 'to reopened' do
it 'executes hooks only once' do
described_class.new(project, user, state_event: 'reopen').execute(closed_issuable)
end
end
context 'to closed' do
it 'executes hooks only once' do
described_class.new(project, user, state_event: 'close').execute(open_issuable)
end
end
end
end