diff options
author | Michael Kozono <mkozono@gmail.com> | 2019-08-19 22:23:41 +0300 |
---|---|---|
committer | Zeger-Jan van de Weg <git@zjvandeweg.nl> | 2019-08-20 12:36:27 +0300 |
commit | dd4ff43781d78d76605aed697dcebad87fd93765 (patch) | |
tree | a6acd9de060ebaf61401717930847261ed2f8d84 | |
parent | 33d24d121550f19ab755303a14dba780389a0071 (diff) |
Add back ability to handle deprecated response message keys
- broadcast_message
- merge_request_urls
- redirected_message
- project_created_message
- warnings
Also refactor GitlabPostReceive, introduce Message class, and
improve tests.
-rw-r--r-- | ruby/gitlab-shell/lib/gitlab_post_receive.rb | 115 | ||||
-rw-r--r-- | ruby/gitlab-shell/lib/message.rb | 88 | ||||
-rw-r--r-- | ruby/gitlab-shell/spec/gitlab_post_receive_spec.rb | 346 |
3 files changed, 343 insertions, 206 deletions
diff --git a/ruby/gitlab-shell/lib/gitlab_post_receive.rb b/ruby/gitlab-shell/lib/gitlab_post_receive.rb index e0107350d..338354146 100644 --- a/ruby/gitlab-shell/lib/gitlab_post_receive.rb +++ b/ruby/gitlab-shell/lib/gitlab_post_receive.rb @@ -1,27 +1,15 @@ require_relative 'gitlab_init' require_relative 'gitlab_net' require_relative 'gitlab_metrics' +require_relative 'message' require 'json' require 'base64' require 'securerandom' class GitlabPostReceive - # A standard terminal window is (at least) 80 characters wide. - TERMINAL_WIDTH = 80 - GIT_REMOTE_MESSAGE_PREFIX_LENGTH = "remote: ".length - TERMINAL_MESSAGE_PADDING = 2 + attr_reader :config, :gl_repository, :repo_path, :changes, :jid, :output_stream - # Git prefixes remote messages with "remote: ", so this width is subtracted - # from the width available to us. - MAX_MESSAGE_WIDTH = TERMINAL_WIDTH - GIT_REMOTE_MESSAGE_PREFIX_LENGTH - - # Our centered text shouldn't start or end right at the edge of the window, - # so we add some horizontal padding: 2 chars on either side. - MAX_MESSAGE_TEXT_WIDTH = MAX_MESSAGE_WIDTH - 2 * TERMINAL_MESSAGE_PADDING - - attr_reader :config, :gl_repository, :repo_path, :changes, :jid - - def initialize(gl_repository, repo_path, actor, changes, push_options) + def initialize(gl_repository, repo_path, actor, changes, push_options, output_stream = $stdout) @config = GitlabConfig.new @gl_repository = gl_repository @repo_path = repo_path.strip @@ -29,6 +17,7 @@ class GitlabPostReceive @changes = changes @push_options = push_options @jid = SecureRandom.hex(12) + @output_stream = output_stream end def exec @@ -38,6 +27,9 @@ class GitlabPostReceive return false unless response + # Deprecated message format for backwards-compatibility + print_gitlab_12_2_messages(response) + print_messages(response['messages']) response['reference_counter_decreased'] @@ -51,73 +43,70 @@ class GitlabPostReceive @api ||= GitlabNet.new end - def print_messages(response_messages) - return if response_messages.nil? || response_messages.none? + # Deprecated message format for backwards-compatibility + def print_gitlab_12_2_messages(response) + if response['broadcast_message'] + puts + print_alert(response['broadcast_message']) + end - puts + print_merge_request_links(response['merge_request_urls']) if response['merge_request_urls'] + puts response['redirected_message'] if response['redirected_message'] + puts response['project_created_message'] if response['project_created_message'] - response_messages.each do |message| - print_message(message) + if response['warnings'] puts + print_warnings(response['warnings']) end end - def print_message(message) - case message['type'] - when 'alert' - print_alert(message['message']) - when 'basic' - print_basic(message['message']) - end + # Deprecated message format for backwards-compatibility + def print_merge_request_links(merge_request_urls) + return if merge_request_urls.empty? + puts + merge_request_urls.each { |mr| print_merge_request_link(mr) } end - def print_basic(str) - puts str + # Deprecated message format for backwards-compatibility + def print_merge_request_link(merge_request) + message = + if merge_request["new_merge_request"] + "To create a merge request for #{merge_request['branch_name']}, visit:" + else + "View merge request for #{merge_request['branch_name']}:" + end + + puts message + puts((" " * 2) + merge_request["url"]) + puts + end + + # Deprecated message format for backwards-compatibility + def print_warnings(warnings) + message = "WARNINGS:\n#{warnings}" + print_alert(message) + puts end def print_alert(message) - # Automatically wrap message at MAX_MESSAGE_TEXT_WIDTH (= 68) characters: - # Splits the message up into the longest possible chunks matching - # "<between 0 and MAX_MESSAGE_TEXT_WIDTH characters><space or end-of-line>". - - msg_start_idx = 0 - lines = [] - while msg_start_idx < message.length - parsed_line = parse_alert_message(message[msg_start_idx..-1], MAX_MESSAGE_TEXT_WIDTH) - msg_start_idx += parsed_line.length - lines.push(parsed_line.strip) - end + Message.new('alert', message).print(output_stream) + end + + def print_messages(response_messages) + return if response_messages.nil? || response_messages.none? - puts "=" * MAX_MESSAGE_WIDTH puts - lines.each do |line| - line.strip! + response_messages.each do |response_message| + Message.new(response_message['type'], response_message['message']).print(output_stream) - # Center the line by calculating the left padding measured in characters. - line_padding = [(MAX_MESSAGE_WIDTH - line.length) / 2, 0].max - puts((" " * line_padding) + line) + puts end - - puts - puts "=" * MAX_MESSAGE_WIDTH end private - def parse_alert_message(msg, text_length) - msg ||= "" - # just return msg if shorter than or equal to text length - return msg if msg.length <= text_length - - # search for word break shorter than text length - truncate_to_space = msg.match(/\A(.{,#{text_length}})(?=\s|$)(\s*)/).to_s - - if truncate_to_space.empty? - # search for word break longer than text length - truncate_to_space = msg.match(/\A\S+/).to_s - end - - truncate_to_space + def puts(*args) + output_stream.puts(*args) end end diff --git a/ruby/gitlab-shell/lib/message.rb b/ruby/gitlab-shell/lib/message.rb new file mode 100644 index 000000000..47d489566 --- /dev/null +++ b/ruby/gitlab-shell/lib/message.rb @@ -0,0 +1,88 @@ +class Message + # A standard terminal window is (at least) 80 characters wide. + TERMINAL_WIDTH = 80 + GIT_REMOTE_MESSAGE_PREFIX_LENGTH = "remote: ".length + TERMINAL_MESSAGE_PADDING = 2 + + # Git prefixes remote messages with "remote: ", so this width is subtracted + # from the width available to us. + MAX_MESSAGE_WIDTH = TERMINAL_WIDTH - GIT_REMOTE_MESSAGE_PREFIX_LENGTH + + # Our centered text shouldn't start or end right at the edge of the window, + # so we add some horizontal padding: 2 chars on either side. + MAX_MESSAGE_TEXT_WIDTH = MAX_MESSAGE_WIDTH - 2 * TERMINAL_MESSAGE_PADDING + + def initialize(type, message) + @type = type + @message = message + end + + def print(output_stream = $stdout) + @output_stream = output_stream + + case @type + when 'alert' + print_alert + when 'basic' + print_basic + else + raise "Unknown message type #{@type}" + end + end + + private + + def print_basic + puts @message + end + + def print_alert + # Automatically wrap message at MAX_MESSAGE_TEXT_WIDTH (= 68) characters: + # Splits the message up into the longest possible chunks matching + # "<between 0 and MAX_MESSAGE_TEXT_WIDTH characters><space or end-of-line>". + + msg_start_idx = 0 + lines = [] + while msg_start_idx < @message.length + parsed_line = parse_alert_message(@message[msg_start_idx..-1], MAX_MESSAGE_TEXT_WIDTH) + msg_start_idx += parsed_line.length + lines.push(parsed_line.strip) + end + + puts "=" * MAX_MESSAGE_WIDTH + puts + + lines.each do |line| + line.strip! + + # Center the line by calculating the left padding measured in characters. + line_padding = [(MAX_MESSAGE_WIDTH - line.length) / 2, 0].max + puts((" " * line_padding) + line) + end + + puts + puts "=" * MAX_MESSAGE_WIDTH + end + + private + + def parse_alert_message(msg, text_length) + msg ||= "" + # just return msg if shorter than or equal to text length + return msg if msg.length <= text_length + + # search for word break shorter than text length + truncate_to_space = msg.match(/\A(.{,#{text_length}})(?=\s|$)(\s*)/).to_s + + if truncate_to_space.empty? + # search for word break longer than text length + truncate_to_space = msg.match(/\A\S+/).to_s + end + + truncate_to_space + end + + def puts(*args) + @output_stream.puts(*args) + end +end diff --git a/ruby/gitlab-shell/spec/gitlab_post_receive_spec.rb b/ruby/gitlab-shell/spec/gitlab_post_receive_spec.rb index b1fd3e3ab..b9a86f486 100644 --- a/ruby/gitlab-shell/spec/gitlab_post_receive_spec.rb +++ b/ruby/gitlab-shell/spec/gitlab_post_receive_spec.rb @@ -12,7 +12,8 @@ describe GitlabPostReceive do let(:repo_path) { File.join(repository_path, repo_name) + ".git" } let(:gl_repository) { "project-1" } let(:push_options) { [] } - let(:gitlab_post_receive) { GitlabPostReceive.new(gl_repository, repo_path, actor, wrongly_encoded_changes, push_options) } + let(:output_stream) { double('output_stream') } + let(:gitlab_post_receive) { GitlabPostReceive.new(gl_repository, repo_path, actor, wrongly_encoded_changes, push_options, output_stream) } let(:broadcast_message) { "test " * 10 + "message " * 10 } let(:enqueued_at) { Time.new(2016, 6, 23, 6, 59) } let(:new_merge_request_message) do @@ -25,18 +26,19 @@ describe GitlabPostReceive do before do $logger = double('logger').as_null_object # Global vars are bad allow_any_instance_of(GitlabConfig).to receive(:repos_path).and_return(repository_path) + expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) end describe "#exec" do let(:response) { { 'reference_counter_decreased' => true } } - it 'calls the api to notify the execution of the hook' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) + subject { gitlab_post_receive.exec } - expect(gitlab_post_receive.exec).to eq(true) + it 'calls the api to notify the execution of the hook' do + expect(subject).to eq(true) end - context 'merge request urls and broadcast messages' do + context 'messages' do let(:response) do { 'reference_counter_decreased' => true, @@ -48,24 +50,20 @@ describe GitlabPostReceive do end it 'prints the merge request message and broadcast message' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) - assert_first_newline(gitlab_post_receive) - assert_broadcast_message_printed(gitlab_post_receive) - assert_basic_message(gitlab_post_receive, new_merge_request_message) + assert_broadcast_message_printed + assert_basic_message(new_merge_request_message) - expect(gitlab_post_receive.exec).to eq(true) + expect(subject).to eq(true) end context 'when contains long url string at end' do let(:broadcast_message) { "test " * 10 + "message " * 10 + "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" } it 'doesnt truncate url' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) - assert_first_newline(gitlab_post_receive) - assert_broadcast_message_printed_keep_long_url_end(gitlab_post_receive) - assert_basic_message(gitlab_post_receive, new_merge_request_message) + assert_broadcast_message_printed_keep_long_url_end + assert_basic_message(new_merge_request_message) - expect(gitlab_post_receive.exec).to eq(true) + expect(subject).to eq(true) end end @@ -73,12 +71,10 @@ describe GitlabPostReceive do let(:broadcast_message) { "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url " + "test " * 10 + "message " * 11} it 'doesnt truncate url' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) - assert_first_newline(gitlab_post_receive) - assert_broadcast_message_printed_keep_long_url_start(gitlab_post_receive) - assert_basic_message(gitlab_post_receive, new_merge_request_message) + assert_broadcast_message_printed_keep_long_url_start + assert_basic_message(new_merge_request_message) - expect(gitlab_post_receive.exec).to eq(true) + expect(subject).to eq(true) end end @@ -86,12 +82,10 @@ describe GitlabPostReceive do let(:broadcast_message) { "test " * 11 + "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url " + "message " * 11} it 'doesnt truncate url' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) - assert_first_newline(gitlab_post_receive) - assert_broadcast_message_printed_keep_long_url_middle(gitlab_post_receive) - assert_basic_message(gitlab_post_receive, new_merge_request_message) + assert_broadcast_message_printed_keep_long_url_middle + assert_basic_message(new_merge_request_message) - expect(gitlab_post_receive.exec).to eq(true) + expect(subject).to eq(true) end end end @@ -105,11 +99,11 @@ describe GitlabPostReceive do ] } end + let(:output_stream) { $stdout } it 'treats the warning as a broadcast message' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) - expect(gitlab_post_receive).to receive(:print_alert).with("WARNINGS:\nMy warning message") - expect(gitlab_post_receive.exec).to eq(true) + assert_warning_looks_like_broadcast_message + expect(subject).to eq(true) end end @@ -124,10 +118,9 @@ describe GitlabPostReceive do end it 'prints redirected message' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) - assert_first_newline(gitlab_post_receive) - assert_basic_message(gitlab_post_receive, "This is a redirected message") - expect(gitlab_post_receive.exec).to eq(true) + assert_first_newline + assert_basic_message("This is a redirected message") + expect(subject).to eq(true) end end @@ -142,12 +135,10 @@ describe GitlabPostReceive do end it 'prints project created message' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) - - assert_first_newline(gitlab_post_receive) - assert_basic_message(gitlab_post_receive, "This is a created project message") + assert_first_newline + assert_basic_message("This is a created project message") - expect(gitlab_post_receive.exec).to be true + expect(subject).to be true end end @@ -160,11 +151,9 @@ describe GitlabPostReceive do end it 'does not print anything' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) + expect(output_stream).to_not receive(:puts) - expect(gitlab_post_receive).to_not receive(:puts) - - expect(gitlab_post_receive.exec).to be true + expect(subject).to be true end end @@ -176,11 +165,117 @@ describe GitlabPostReceive do end it 'does not print anything' do - expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response) + expect(output_stream).to_not receive(:puts) - expect(gitlab_post_receive).to_not receive(:puts) + expect(subject).to be true + end + end - expect(gitlab_post_receive.exec).to be true + # Deprecated message format for backwards-compatibility + context 'deprecated message format' do + let(:new_merge_request_urls) do + [{ + 'branch_name' => 'new_branch', + 'url' => 'http://localhost/dzaporozhets/gitlab-ci/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch', + 'new_merge_request' => true + }] + end + + let(:response) do + { + 'merge_request_urls' => new_merge_request_urls, + 'broadcast_message' => broadcast_message + } + end + + def assert_new_mr_printed + expect_puts "To create a merge request for new_branch, visit:" + expect_puts " http://localhost/dzaporozhets/gitlab-ci/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch" + expect_puts + end + + it 'prints the merge request urls and broadcast message' do + assert_broadcast_message_printed + assert_new_mr_printed + + subject + end + + context 'when contains long url string at end' do + let(:broadcast_message) { "test " * 10 + "message " * 10 + "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" } + + it 'doesnt truncate url' do + assert_broadcast_message_printed_keep_long_url_end + assert_new_mr_printed + + subject + end + end + + context 'when contains long url string at start' do + let(:broadcast_message) { "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url " + "test " * 10 + "message " * 11} + + it 'doesnt truncate url' do + assert_broadcast_message_printed_keep_long_url_start + assert_new_mr_printed + + subject + end + end + + context 'when contains long url string in middle' do + let(:broadcast_message) { "test " * 11 + "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url " + "message " * 11} + + it 'doesnt truncate url' do + assert_broadcast_message_printed_keep_long_url_middle + assert_new_mr_printed + + subject + end + end + end + + context 'when warnings are present' do + let(:response) do + { + 'warnings' => 'My warning message' + } + end + + it 'treats the warning as a broadcast message' do + assert_warning_looks_like_broadcast_message + + subject + end + end + + context 'when redirected message available' do + let(:message) { "This is a redirected message" } + let(:response) do + { + 'redirected_message' => message + } + end + + it 'prints redirected message' do + expect_puts "This is a redirected message" + + subject + end + + context 'when project created message is available' do + let(:message) { "This is a created project message" } + let(:response) do + { + 'project_created_message' => message + } + end + + it 'prints project created message' do + expect_puts "This is a created project message" + + subject + end end end end @@ -193,114 +288,79 @@ describe GitlabPostReceive do # # Failure/Error: puts message # #<GitlabPostReceive:0x00007f97e0843008 ...<snip>... received :puts out of order - def assert_broadcast_message_printed(gitlab_post_receive) - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " test test test test test test test test test test message message" - ).ordered - expect(gitlab_post_receive).to receive(:puts).with( - " message message message message message message message message" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).ordered - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered + def assert_broadcast_message_printed + expect_puts + expect_puts "========================================================================" + expect_puts + expect_puts " test test test test test test test test test test message message" + expect_puts " message message message message message message message message" + expect_puts + expect_puts "========================================================================" + expect_puts end - def assert_broadcast_message_printed_keep_long_url_end(gitlab_post_receive) - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " test test test test test test test test test test message message" - ).ordered - expect(gitlab_post_receive).to receive(:puts).with( - " message message message message message message message message" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).ordered - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered + def assert_broadcast_message_printed_keep_long_url_end + expect_puts + expect_puts "========================================================================" + expect_puts + expect_puts " test test test test test test test test test test message message" + expect_puts " message message message message message message message message" + expect_puts "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" + expect_puts + expect_puts "========================================================================" + expect_puts end - def assert_broadcast_message_printed_keep_long_url_start(gitlab_post_receive) - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " test test test test test test test test test test message message" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " message message message message message message message message" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " message" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).ordered - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered + def assert_broadcast_message_printed_keep_long_url_start + expect_puts + expect_puts "========================================================================" + expect_puts + expect_puts "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" + expect_puts " test test test test test test test test test test message message" + expect_puts " message message message message message message message message" + expect_puts " message" + expect_puts + expect_puts "========================================================================" + expect_puts end - def assert_broadcast_message_printed_keep_long_url_middle(gitlab_post_receive) - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " test test test test test test test test test test test" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " message message message message message message message message" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).with( - " message message message" - ).ordered - - expect(gitlab_post_receive).to receive(:puts).ordered - expect(gitlab_post_receive).to receive(:puts).with( - "========================================================================" - ).ordered - expect(gitlab_post_receive).to receive(:puts).ordered + def assert_broadcast_message_printed_keep_long_url_middle + expect_puts + expect_puts "========================================================================" + expect_puts + expect_puts " test test test test test test test test test test test" + expect_puts "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" + expect_puts " message message message message message message message message" + expect_puts " message message message" + expect_puts + expect_puts "========================================================================" + expect_puts end - def assert_basic_message(gitlab_post_receive, message) - expect(gitlab_post_receive).to receive(:puts).with(message).ordered - expect(gitlab_post_receive).to receive(:puts).ordered + def assert_warning_looks_like_broadcast_message + expect_puts + expect_puts "========================================================================" + expect_puts + expect_puts " WARNINGS:\nMy warning message" + expect_puts + expect_puts "========================================================================" + expect_puts end - def assert_first_newline(gitlab_post_receive) - expect(gitlab_post_receive).to receive(:puts).ordered + def assert_basic_message(message) + expect_puts message + expect_puts + end + + def assert_first_newline + expect_puts + end + + def expect_puts(*args) + if (args).none? + expect(output_stream).to receive(:puts).ordered + else + expect(output_stream).to receive(:puts).with(*args).ordered + end end end |