Unverified Commit 6d353c1d authored by Robert Speicher's avatar Robert Speicher Committed by John Skarbek

Adapt CherryPick::Service to use generic targets

Previously, this service was limited to picking into a preparation merge
request. Now it can work with any object that responds to specific
messages we require.
parent d2d881fd
......@@ -4,13 +4,11 @@ module ReleaseTools
module CherryPick
class CommentNotifier
attr_reader :version
attr_reader :prep_mr
attr_reader :branch_name
attr_reader :target
def initialize(version, prep_mr: nil, branch_name: nil)
def initialize(version, target:)
@version = version
@prep_mr = prep_mr
@branch_name = branch_name
@target = target
end
def comment(pick_result)
......@@ -28,7 +26,6 @@ module ReleaseTools
# unpicked - Array of failure Results
def summary(picked, unpicked)
return if picked.empty? && unpicked.empty?
return unless prep_mr
message = []
......@@ -48,26 +45,22 @@ module ReleaseTools
MSG
end
create_merge_request_comment(prep_mr, message.join("\n"))
create_merge_request_comment(target, message.join("\n"))
end
def blog_post_summary(picked)
return if version.rc?
return if version.rc? || version.monthly?
return if picked.empty?
notify_object = prep_mr&.url || branch_name
message = <<~MSG
The following merge requests were picked into #{notify_object}:
The following merge requests were picked into #{target.url}:
```
#{markdown_list(picked.collect(&:to_markdown))}
```
MSG
return message unless prep_mr
create_issue_comment(prep_mr.release_issue, message)
create_issue_comment(target.release_issue, message)
end
private
......@@ -77,17 +70,13 @@ module ReleaseTools
end
def successful_comment(pick_result)
notify_object = prep_mr&.url || branch_name
comment = <<~MSG
Automatically picked into #{notify_object}, will merge into
Automatically picked into #{target.pick_destination}, will merge into
`#{version.stable_branch}` ready for `#{version}`.
/unlabel #{PickIntoLabel.reference(version)}
MSG
return unless prep_mr
create_merge_request_comment(pick_result.merge_request, comment)
end
......@@ -119,6 +108,9 @@ module ReleaseTools
end
def create_merge_request_comment(merge_request, comment)
return unless merge_request.respond_to?(:project_id) &&
merge_request.respond_to?(:iid)
client.create_merge_request_comment(
merge_request.project_id,
merge_request.iid,
......
......@@ -2,41 +2,33 @@
module ReleaseTools
module CherryPick
# Performs automated cherry picking to a preparation branch for the specified
# Performs automated cherry picking to a target branch for the specified
# version.
#
# For the given project, this service will look for merged merge requests on
# that project labeled `Pick into X.Y` and attempt to cherry-pick their merge
# commits into the preparation merge request for the specified version.
# commits into the target merge request for the specified version.
#
# It will post a comment to each merge request with the status of the pick,
# and then a final summary message to the preparation merge request with the
# list of picked and unpicked merge requests for the release managers to
# perform any further manual actions.
# and a final summary message with the list of picked and unpicked merge
# requests for the release managers to perform any further manual actions.
class Service
# TODO (rspeicher): Support `SharedStatus.security_release?`
REMOTE = :gitlab
attr_reader :project
attr_reader :version
attr_reader :pick_branch
attr_reader :target
def initialize(project, version, pick_branch = nil)
def initialize(project, version, target)
@project = project
@version = version
@pick_branch = pick_branch
@target = target
assert_version!
assert_target!
if pick_branch.nil?
@prep_mr = PreparationMergeRequest.new(version: version)
assert_prep_mr!
@prep_branch = @prep_mr.preparation_branch_name
else
@prep_branch = pick_branch
end
@target_branch = @target.branch_name
@results = []
end
......@@ -66,17 +58,15 @@ module ReleaseTools
raise "Invalid version provided: `#{version}`" unless version.valid?
end
def assert_prep_mr!
unless @prep_mr.exists?
raise "Preparation merge request not found for `#{version}`"
end
def assert_target!
raise 'Invalid cherry-pick target provided' unless target.exists?
end
def notifier
if SharedStatus.dry_run?
@notifier ||= ConsoleNotifier.new(version, prep_mr: @prep_mr, branch_name: pick_branch)
@notifier ||= ConsoleNotifier.new(version, target: target)
else
@notifier ||= CommentNotifier.new(version, prep_mr: @prep_mr, branch_name: pick_branch)
@notifier ||= CommentNotifier.new(version, target: target)
end
end
......@@ -87,7 +77,7 @@ module ReleaseTools
GitlabClient.cherry_pick(
project,
ref: merge_request.merge_commit_sha,
target: @prep_branch
target: @target_branch
)
end
......
......@@ -11,7 +11,7 @@ module ReleaseTools
end
def source_branch
preparation_branch_name
branch_name
end
def target_branch
......@@ -38,7 +38,7 @@ module ReleaseTools
end
end
def preparation_branch_name
def branch_name
if version.rc?
"#{version.stable_branch}-prepare-rc#{version.rc}"
else
......@@ -46,6 +46,10 @@ module ReleaseTools
end
end
def pick_destination
url
end
def ee?
version.ee?
end
......
......@@ -18,9 +18,10 @@ namespace :release do
# CE
version = get_version(args).to_ce
target = ReleaseTools::PreparationMergeRequest.new(version: version)
$stdout.puts "--> Picking for #{version}..."
results = ReleaseTools::CherryPick::Service
.new(ReleaseTools::Project::GitlabCe, version)
.new(ReleaseTools::Project::GitlabCe, version, target)
.execute
results.each do |result|
......@@ -31,7 +32,7 @@ namespace :release do
version = version.to_ee
$stdout.puts "--> Picking for #{version}..."
results = ReleaseTools::CherryPick::Service
.new(ReleaseTools::Project::GitlabEe, version)
.new(ReleaseTools::Project::GitlabEe, version, target)
.execute
results.each do |result|
......
......@@ -4,14 +4,15 @@ require 'spec_helper'
describe ReleaseTools::CherryPick::CommentNotifier do
let(:client) { spy('GitlabClient') }
let(:version) { ReleaseTools::Version.new('11.4.0') }
let(:version) { ReleaseTools::Version.new('11.4.1') }
let(:prep_mr) do
double(
iid: 1,
project_id: 2,
url: 'https://example.com',
release_issue: double(project: spy, iid: 4)
release_issue: double(project: spy, iid: 4),
pick_destination: 'https://example.com'
)
end
......@@ -34,7 +35,7 @@ describe ReleaseTools::CherryPick::CommentNotifier do
end
subject do
described_class.new(version, prep_mr: prep_mr)
described_class.new(version, target: prep_mr)
end
before do
......
......@@ -4,20 +4,25 @@ require 'spec_helper'
describe ReleaseTools::CherryPick::Service do
let(:version) { ReleaseTools::Version.new('11.4.0-rc8') }
let(:target) { double(branch_name: 'branch-name', exists?: true) }
subject { described_class.new(ReleaseTools::Project::GitlabCe, version) }
subject do
described_class.new(ReleaseTools::Project::GitlabCe, version, target)
end
describe 'initialize' do
it 'validates version argument' do
expect { described_class.new(double, double(valid?: false)) }
version = double(valid?: false)
expect { described_class.new(double, version, target) }
.to raise_error(RuntimeError, /Invalid version provided/)
end
it 'validates preparation MR' do
stub_const('ReleaseTools::PreparationMergeRequest', spy(exists?: false))
it 'validates target exists' do
target = double(exists?: false)
expect { described_class.new(double, version) }
.to raise_error(RuntimeError, /Preparation merge request not found/)
expect { described_class.new(double, version, target) }
.to raise_error(RuntimeError, /Invalid cherry-pick target provided/)
end
end
......@@ -43,7 +48,6 @@ describe ReleaseTools::CherryPick::Service do
end
end
let(:target) { '11-4-stable-prepare-rc8' }
let(:notifier) { spy }
let(:picks) do
Gitlab::PaginatedResponse.new(
......
......@@ -30,22 +30,22 @@ describe ReleaseTools::PreparationMergeRequest do
expect(merge_request.milestone).to eq '9.4'
end
describe '#preparation_branch_name' do
describe '#branch_name' do
it 'appends the stable branch with patch number' do
expect(merge_request.preparation_branch_name).to eq '9-4-stable-patch-1'
expect(ee_merge_request.preparation_branch_name).to eq '9-4-stable-ee-patch-1'
expect(merge_request.branch_name).to eq '9-4-stable-patch-1'
expect(ee_merge_request.branch_name).to eq '9-4-stable-ee-patch-1'
end
context 'release candidate' do
it 'appends the stable branch with rc number' do
expect(rc_merge_request.preparation_branch_name).to eq '9-4-stable-prepare-rc2'
expect(ee_rc_merge_request.preparation_branch_name).to eq '9-4-stable-ee-prepare-rc2'
expect(rc_merge_request.branch_name).to eq '9-4-stable-prepare-rc2'
expect(ee_rc_merge_request.branch_name).to eq '9-4-stable-ee-prepare-rc2'
end
end
end
it 'sets source_branch to the new branch' do
expect(merge_request.source_branch).to eq merge_request.preparation_branch_name
expect(merge_request.source_branch).to eq merge_request.branch_name
end
it 'sets target_branch to the stable branch' do
......
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