Commit 50342028 authored by Michael Kozono's avatar Michael Kozono

Simplify internal post receive messages

Instead of sending varied data to Gitaly, and making Gitaly construct
various messages, build the messages first and have Gitaly print
either basic messages or alert messages, in the order they come.

Depends on https://gitlab.com/gitlab-org/gitaly/merge_requests/1410
parent a82e14c1
...@@ -1705,6 +1705,18 @@ module API ...@@ -1705,6 +1705,18 @@ module API
class ClusterGroup < Cluster class ClusterGroup < Cluster
expose :group, using: Entities::BasicGroupDetails expose :group, using: Entities::BasicGroupDetails
end end
module InternalPostReceive
class Message < Grape::Entity
expose :message
expose :type
end
class Response < Grape::Entity
expose :messages, using: Message
expose :reference_counter_decreased
end
end
end end
end end
......
...@@ -44,8 +44,6 @@ module API ...@@ -44,8 +44,6 @@ module API
end end
def process_mr_push_options(push_options, project, user, changes) def process_mr_push_options(push_options, project, user, changes)
output = {}
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/61359') Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/61359')
service = ::MergeRequests::PushOptionsHandlerService.new( service = ::MergeRequests::PushOptionsHandlerService.new(
...@@ -56,15 +54,13 @@ module API ...@@ -56,15 +54,13 @@ module API
).execute ).execute
if service.errors.present? if service.errors.present?
output[:warnings] = push_options_warning(service.errors.join("\n\n")) push_options_warning(service.errors.join("\n\n"))
end end
output
end end
def push_options_warning(warning) def push_options_warning(warning)
options = Array.wrap(params[:push_options]).map { |p| "'#{p}'" }.join(' ') options = Array.wrap(params[:push_options]).map { |p| "'#{p}'" }.join(' ')
"Error encountered with push options #{options}: #{warning}" "WARNINGS:\nError encountered with push options #{options}: #{warning}"
end end
def redis_ping def redis_ping
......
...@@ -256,25 +256,26 @@ module API ...@@ -256,25 +256,26 @@ module API
post '/post_receive' do post '/post_receive' do
status 200 status 200
output = {} # Messages to gitlab-shell response = Gitlab::InternalPostReceive::Response.new
user = identify(params[:identifier]) user = identify(params[:identifier])
project = Gitlab::GlRepository.parse(params[:gl_repository]).first project = Gitlab::GlRepository.parse(params[:gl_repository]).first
push_options = Gitlab::PushOptions.new(params[:push_options]) push_options = Gitlab::PushOptions.new(params[:push_options])
response.reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
PostReceive.perform_async(params[:gl_repository], params[:identifier], PostReceive.perform_async(params[:gl_repository], params[:identifier],
params[:changes], push_options.as_json) params[:changes], push_options.as_json)
mr_options = push_options.get(:merge_request) mr_options = push_options.get(:merge_request)
output.merge!(process_mr_push_options(mr_options, project, user, params[:changes])) if mr_options.present? if mr_options.present?
message = process_mr_push_options(mr_options, project, user, params[:changes])
response.add_alert_message(message)
end
broadcast_message = BroadcastMessage.current&.last&.message broadcast_message = BroadcastMessage.current&.last&.message
reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease response.add_alert_message(broadcast_message)
output.merge!( response.add_merge_request_urls(merge_request_urls)
broadcast_message: broadcast_message,
reference_counter_decreased: reference_counter_decreased,
merge_request_urls: merge_request_urls
)
# A user is not guaranteed to be returned; an orphaned write deploy # A user is not guaranteed to be returned; an orphaned write deploy
# key could be used # key could be used
...@@ -282,11 +283,11 @@ module API ...@@ -282,11 +283,11 @@ module API
redirect_message = Gitlab::Checks::ProjectMoved.fetch_message(user.id, project.id) redirect_message = Gitlab::Checks::ProjectMoved.fetch_message(user.id, project.id)
project_created_message = Gitlab::Checks::ProjectCreated.fetch_message(user.id, project.id) project_created_message = Gitlab::Checks::ProjectCreated.fetch_message(user.id, project.id)
output[:redirected_message] = redirect_message if redirect_message response.add_basic_message(redirect_message)
output[:project_created_message] = project_created_message if project_created_message response.add_basic_message(project_created_message)
end end
output present response, with: Entities::InternalPostReceive::Response
end end
end end
end end
......
# frozen_string_literal: true
module Gitlab
module InternalPostReceive
class Response
attr_accessor :reference_counter_decreased
attr_reader :messages
Message = Struct.new(:message, :type) do
def self.basic(text)
new(text, :basic)
end
def self.alert(text)
new(text, :alert)
end
end
def initialize
@messages = []
@reference_counter_decreased = false
end
def add_merge_request_urls(urls_data)
urls_data.each do |url_data|
add_merge_request_url(url_data)
end
end
def add_merge_request_url(url_data)
message = if url_data[:new_merge_request]
"To create a merge request for #{url_data[:branch_name]}, visit:"
else
"View merge request for #{url_data[:branch_name]}:"
end
message += "\n #{url_data[:url]}"
add_basic_message(message)
end
def add_basic_message(text)
@messages << Message.basic(text) if text.present?
end
def add_alert_message(text)
@messages.unshift(Message.alert(text)) if text.present?
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::InternalPostReceive::Response do
subject { described_class.new }
describe '#add_merge_request_urls' do
context 'when there are urls_data' do
it 'adds a message for each merge request URL' do
urls_data = [
{ new_merge_request: false, branch_name: 'foo', url: 'http://example.com/foo/bar/merge_requests/1' },
{ new_merge_request: true, branch_name: 'bar', url: 'http://example.com/foo/bar/merge_requests/new?merge_request%5Bsource_branch%5D=bar' }
]
subject.add_merge_request_urls(urls_data)
expected = [a_kind_of(described_class::Message), a_kind_of(described_class::Message)]
expect(subject.messages).to match(expected)
end
end
end
describe '#add_merge_request_url' do
context 'when :new_merge_request is false' do
it 'adds a basic message to view the existing merge request' do
url_data = { new_merge_request: false, branch_name: 'foo', url: 'http://example.com/foo/bar/merge_requests/1' }
subject.add_merge_request_url(url_data)
message = <<~MESSAGE.strip
View merge request for foo:
http://example.com/foo/bar/merge_requests/1
MESSAGE
expect(subject.messages.first.message).to eq(message)
expect(subject.messages.first.type).to eq(:basic)
end
end
context 'when :new_merge_request is true' do
it 'adds a basic message to create a new merge request' do
url_data = { new_merge_request: true, branch_name: 'bar', url: 'http://example.com/foo/bar/merge_requests/new?merge_request%5Bsource_branch%5D=bar' }
subject.add_merge_request_url(url_data)
message = <<~MESSAGE.strip
To create a merge request for bar, visit:
http://example.com/foo/bar/merge_requests/new?merge_request%5Bsource_branch%5D=bar
MESSAGE
expect(subject.messages.first.message).to eq(message)
expect(subject.messages.first.type).to eq(:basic)
end
end
end
describe '#add_basic_message' do
context 'when text is present' do
it 'adds a basic message' do
subject.add_basic_message('hello')
expect(subject.messages.first.message).to eq('hello')
expect(subject.messages.first.type).to eq(:basic)
end
end
context 'when text is blank' do
it 'does not add a message' do
subject.add_basic_message(' ')
expect(subject.messages).to be_blank
end
end
end
describe '#add_alert_message' do
context 'when text is present' do
it 'adds a alert message' do
subject.add_alert_message('hello')
expect(subject.messages.first.message).to eq('hello')
expect(subject.messages.first.type).to eq(:alert)
end
end
context 'when text is blank' do
it 'does not add a message' do
subject.add_alert_message(' ')
expect(subject.messages).to be_blank
end
end
end
describe '#reference_counter_decreased' do
context 'initially' do
it 'reference_counter_decreased is set to false' do
expect(subject.reference_counter_decreased).to eq(false)
end
end
end
describe '#reference_counter_decreased=' do
context 'when the argument is truthy' do
it 'reference_counter_decreased is truthy' do
subject.reference_counter_decreased = true
expect(subject.reference_counter_decreased).to be_truthy
end
end
context 'when the argument is falsey' do
it 'reference_counter_decreased is falsey' do
subject.reference_counter_decreased = false
expect(subject.reference_counter_decreased).to be_falsey
end
end
end
end
...@@ -925,19 +925,20 @@ describe API::Internal do ...@@ -925,19 +925,20 @@ describe API::Internal do
it 'returns link to create new merge request' do it 'returns link to create new merge request' do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(json_response['merge_request_urls']).to match [{ message = <<~MESSAGE.strip
"branch_name" => branch_name, To create a merge request for #{branch_name}, visit:
"url" => "http://#{Gitlab.config.gitlab.host}/#{project.full_path}/merge_requests/new?merge_request%5Bsource_branch%5D=#{branch_name}", http://#{Gitlab.config.gitlab.host}/#{project.full_path}/merge_requests/new?merge_request%5Bsource_branch%5D=#{branch_name}
"new_merge_request" => true MESSAGE
}]
expect(json_response['messages']).to include(build_basic_message(message))
end end
it 'returns empty array if printing_merge_request_link_enabled is false' do it 'returns no merge request messages if printing_merge_request_link_enabled is false' do
project.update!(printing_merge_request_link_enabled: false) project.update!(printing_merge_request_link_enabled: false)
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(json_response['merge_request_urls']).to eq([]) expect(json_response['messages']).to be_blank
end end
it 'does not invoke MergeRequests::PushOptionsHandlerService' do it 'does not invoke MergeRequests::PushOptionsHandlerService' do
...@@ -968,11 +969,12 @@ describe API::Internal do ...@@ -968,11 +969,12 @@ describe API::Internal do
it 'links to the newly created merge request' do it 'links to the newly created merge request' do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(json_response['merge_request_urls']).to match [{ message = <<~MESSAGE.strip
'branch_name' => branch_name, View merge request for #{branch_name}:
'url' => "http://#{Gitlab.config.gitlab.host}/#{project.full_path}/merge_requests/1", http://#{Gitlab.config.gitlab.host}/#{project.full_path}/merge_requests/1
'new_merge_request' => false MESSAGE
}]
expect(json_response['messages']).to include(build_basic_message(message))
end end
it 'adds errors on the service instance to warnings' do it 'adds errors on the service instance to warnings' do
...@@ -982,7 +984,8 @@ describe API::Internal do ...@@ -982,7 +984,8 @@ describe API::Internal do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(json_response['warnings']).to eq('Error encountered with push options \'merge_request.create\': my error') message = "WARNINGS:\nError encountered with push options 'merge_request.create': my error"
expect(json_response['messages']).to include(build_alert_message(message))
end end
it 'adds ActiveRecord errors on invalid MergeRequest records to warnings' do it 'adds ActiveRecord errors on invalid MergeRequest records to warnings' do
...@@ -995,38 +998,39 @@ describe API::Internal do ...@@ -995,38 +998,39 @@ describe API::Internal do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(json_response['warnings']).to eq('Error encountered with push options \'merge_request.create\': my error') message = "WARNINGS:\nError encountered with push options 'merge_request.create': my error"
expect(json_response['messages']).to include(build_alert_message(message))
end end
end end
context 'broadcast message exists' do context 'broadcast message exists' do
let!(:broadcast_message) { create(:broadcast_message, starts_at: 1.day.ago, ends_at: 1.day.from_now ) } let!(:broadcast_message) { create(:broadcast_message, starts_at: 1.day.ago, ends_at: 1.day.from_now ) }
it 'returns one broadcast message' do it 'outputs a broadcast message' do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response['broadcast_message']).to eq(broadcast_message.message) expect(json_response['messages']).to include(build_alert_message(broadcast_message.message))
end end
end end
context 'broadcast message does not exist' do context 'broadcast message does not exist' do
it 'returns empty string' do it 'does not output a broadcast message' do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response['broadcast_message']).to eq(nil) expect(has_alert_messages?(json_response['messages'])).to be_falsey
end end
end end
context 'nil broadcast message' do context 'nil broadcast message' do
it 'returns empty string' do it 'does not output a broadcast message' do
allow(BroadcastMessage).to receive(:current).and_return(nil) allow(BroadcastMessage).to receive(:current).and_return(nil)
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response['broadcast_message']).to eq(nil) expect(has_alert_messages?(json_response['messages'])).to be_falsey
end end
end end
...@@ -1038,8 +1042,7 @@ describe API::Internal do ...@@ -1038,8 +1042,7 @@ describe API::Internal do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response["redirected_message"]).to be_present expect(json_response['messages']).to include(build_basic_message(project_moved.message))
expect(json_response["redirected_message"]).to eq(project_moved.message)
end end
end end
...@@ -1051,8 +1054,7 @@ describe API::Internal do ...@@ -1051,8 +1054,7 @@ describe API::Internal do
post api('/internal/post_receive'), params: valid_params post api('/internal/post_receive'), params: valid_params
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response["project_created_message"]).to be_present expect(json_response['messages']).to include(build_basic_message(project_created.message))
expect(json_response["project_created_message"]).to eq(project_created.message)
end end
end end
...@@ -1172,4 +1174,18 @@ describe API::Internal do ...@@ -1172,4 +1174,18 @@ describe API::Internal do
} }
) )
end end
def build_alert_message(message)
{ 'type' => 'alert', 'message' => message }
end
def build_basic_message(message)
{ 'type' => 'basic', 'message' => message }
end
def has_alert_messages?(messages)
messages.any? do |message|
message['type'] == 'alert'
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment