flash_flow 1.3.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +13 -8
- data/bin/flash_flow +4 -4
- data/flash_flow.gemspec +1 -0
- data/flash_flow.yml.erb.example +7 -0
- data/lib/flash_flow.rb +2 -2
- data/lib/flash_flow/config.rb +2 -1
- data/lib/flash_flow/data/base.rb +30 -14
- data/lib/flash_flow/git.rb +21 -12
- data/lib/flash_flow/issue_tracker.rb +1 -1
- data/lib/flash_flow/merge.rb +8 -0
- data/lib/flash_flow/merge/acceptance.rb +156 -0
- data/lib/flash_flow/merge/base.rb +81 -0
- data/lib/flash_flow/merge/master.rb +126 -0
- data/lib/flash_flow/{merge_master → merge}/merge_status.html.erb +0 -0
- data/lib/flash_flow/{merge_master → merge}/release_graph.rb +1 -1
- data/lib/flash_flow/{merge_master → merge}/status.rb +3 -3
- data/lib/flash_flow/merge_order.rb +1 -2
- data/lib/flash_flow/notifier/hipchat.rb +5 -7
- data/lib/flash_flow/release.rb +20 -0
- data/lib/flash_flow/release/percy_client.rb +67 -0
- data/lib/flash_flow/shadow_repo.rb +1 -0
- data/lib/flash_flow/version.rb +1 -1
- data/test/lib/merge/test_acceptance.rb +191 -0
- data/test/lib/{merge_master → merge}/test_release_graph.rb +2 -2
- data/test/lib/{merge_master → merge}/test_status.rb +4 -4
- data/test/lib/release/test_percy_client.rb +92 -0
- data/test/lib/test_merge_order.rb +1 -3
- metadata +33 -13
- data/lib/flash_flow/deploy.rb +0 -295
- data/lib/flash_flow/merge_master.rb +0 -6
- data/test/lib/test_deploy.rb +0 -186
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'flash_flow/git'
|
4
|
+
require 'flash_flow/data'
|
5
|
+
require 'flash_flow/lock'
|
6
|
+
require 'flash_flow/notifier'
|
7
|
+
require 'flash_flow/branch_merger'
|
8
|
+
require 'flash_flow/merge_order'
|
9
|
+
require 'flash_flow/shadow_repo'
|
10
|
+
|
11
|
+
module FlashFlow
|
12
|
+
module Merge
|
13
|
+
class Base
|
14
|
+
|
15
|
+
class VersionError < RuntimeError; end
|
16
|
+
class OutOfSyncWithRemote < RuntimeError; end
|
17
|
+
class UnmergeableBranch < RuntimeError; end
|
18
|
+
|
19
|
+
def initialize(opts={})
|
20
|
+
@local_git = Git.new(Config.configuration.git, logger)
|
21
|
+
@git = ShadowGit.new(Config.configuration.git, logger)
|
22
|
+
@lock = Lock::Base.new(Config.configuration.lock)
|
23
|
+
@notifier = Notifier::Base.new(Config.configuration.notifier)
|
24
|
+
end
|
25
|
+
|
26
|
+
def logger
|
27
|
+
@logger ||= FlashFlow::Config.configuration.logger
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_repo
|
31
|
+
if @local_git.staged_and_working_dir_files.any?
|
32
|
+
raise RuntimeError.new('You have changes in your working directory. Please stash and try again')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_version
|
37
|
+
data_version = @data.version
|
38
|
+
return if data_version.nil?
|
39
|
+
|
40
|
+
written_version = data_version.split(".").map(&:to_i)
|
41
|
+
running_version = FlashFlow::VERSION.split(".").map(&:to_i)
|
42
|
+
|
43
|
+
unless written_version[0] < running_version[0] ||
|
44
|
+
(written_version[0] == running_version[0] && written_version[1] <= running_version[1]) # Ignore the point release number
|
45
|
+
raise RuntimeError.new("Your version of flash flow (#{FlashFlow::VERSION}) is behind the version that was last used (#{data_version}) by a member of your team. Please upgrade to at least #{written_version[0]}.#{written_version[1]}.0 and try again.")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def merge_branches(branches)
|
50
|
+
ordered_branches = MergeOrder.new(@git, branches).get_order
|
51
|
+
ordered_branches.each_with_index do |branch, index|
|
52
|
+
branch.merge_order = index + 1
|
53
|
+
|
54
|
+
remote = @git.fetch_remote_for_url(branch.remote_url)
|
55
|
+
if remote.nil?
|
56
|
+
raise RuntimeError.new("No remote found for #{branch.remote_url}. Please run 'git remote add *your_remote_name* #{branch.remote_url}' and try again.")
|
57
|
+
end
|
58
|
+
|
59
|
+
@git.fetch(branch.remote)
|
60
|
+
merger = git_merge(branch)
|
61
|
+
|
62
|
+
yield(branch, merger)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def git_merge(branch)
|
67
|
+
merger = BranchMerger.new(@git, branch)
|
68
|
+
forget_rerere = is_working_branch(branch) && @rerere_forget
|
69
|
+
|
70
|
+
merger.do_merge(forget_rerere)
|
71
|
+
|
72
|
+
merger
|
73
|
+
end
|
74
|
+
|
75
|
+
def is_working_branch(branch)
|
76
|
+
branch.ref == @git.working_branch
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'flash_flow/merge/base'
|
2
|
+
|
3
|
+
module FlashFlow
|
4
|
+
module Merge
|
5
|
+
class Master < Base
|
6
|
+
|
7
|
+
class PendingReleaseError < RuntimeError; end
|
8
|
+
class NothingToMergeError < RuntimeError; end
|
9
|
+
class GitPushFailure < RuntimeError; end
|
10
|
+
|
11
|
+
def initialize(opts={})
|
12
|
+
super(opts)
|
13
|
+
|
14
|
+
@release_branches = parse_branches(opts[:release_branches])
|
15
|
+
|
16
|
+
@data = Data::Base.new({}, Config.configuration.branch_info_file, @git, logger: logger)
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
begin
|
21
|
+
check_version
|
22
|
+
check_branches
|
23
|
+
puts "Merging these branches into #{@git.release_branch}:\n #{@release_branches.map(&:ref).join("\n ")}"
|
24
|
+
logger.info "\n\n### Beginning #{@local_git.merge_branch} merge ###\n\n"
|
25
|
+
|
26
|
+
mergers, errors = [], []
|
27
|
+
|
28
|
+
@lock.with_lock do
|
29
|
+
release = @data.releases.detect { |r| r['status'] == 'Pending' }
|
30
|
+
if release
|
31
|
+
raise PendingReleaseError.new("There is already a pending release: #{release}")
|
32
|
+
elsif @git.branch_exists?("#{@git.merge_remote}/#{@git.release_branch}") &&
|
33
|
+
!@git.branch_contains?(@git.master_branch, @git.get_sha("#{@git.merge_remote}/#{@git.release_branch}"))
|
34
|
+
raise PendingReleaseError.new("The release branch '#{@git.release_branch}' has commits that are not in master")
|
35
|
+
end
|
36
|
+
|
37
|
+
@git.fetch(@git.merge_remote)
|
38
|
+
@git.in_original_merge_branch do
|
39
|
+
@git.initialize_rerere
|
40
|
+
end
|
41
|
+
|
42
|
+
@git.reset_temp_merge_branch
|
43
|
+
@git.in_temp_merge_branch do
|
44
|
+
merge_branches(@release_branches) do |branch, merger|
|
45
|
+
mergers << [branch, merger]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
errors = mergers.select { |m| m.last.result != :success }
|
50
|
+
|
51
|
+
if errors.empty?
|
52
|
+
unless @git.push("#{@git.temp_merge_branch}:#{@git.release_branch}", true)
|
53
|
+
raise GitPushFailure.new("Unable to push to #{@git.release_branch}. See log for details.")
|
54
|
+
end
|
55
|
+
|
56
|
+
release_sha = @git.get_sha(@git.temp_merge_branch)
|
57
|
+
|
58
|
+
@data.releases.unshift({ created_at: Time.now, sha: release_sha, status: 'Pending' })
|
59
|
+
|
60
|
+
@git.in_temp_merge_branch do
|
61
|
+
@git.run("reset --hard #{@git.merge_remote}/#{@git.merge_branch}")
|
62
|
+
end
|
63
|
+
@git.in_merge_branch do
|
64
|
+
@git.run("reset --hard #{@git.merge_remote}/#{@git.merge_branch}")
|
65
|
+
end
|
66
|
+
|
67
|
+
@data.save!
|
68
|
+
|
69
|
+
@git.copy_temp_to_branch(@git.merge_branch, 'Release data updated [ci skip]')
|
70
|
+
@git.delete_temp_merge_branch
|
71
|
+
@git.push(@git.merge_branch, false)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
if errors.empty?
|
76
|
+
puts 'Success!'
|
77
|
+
else
|
78
|
+
raise UnmergeableBranch.new("The following branches didn't merge successfully:\n #{errors.map { |e| e.first.ref }.join("\n ")}")
|
79
|
+
end
|
80
|
+
|
81
|
+
logger.info "### Finished #{@git.release_branch} merge ###"
|
82
|
+
rescue Lock::Error, OutOfSyncWithRemote, UnmergeableBranch, GitPushFailure, NothingToMergeError, VersionError, PendingReleaseError => e
|
83
|
+
puts 'Failure!'
|
84
|
+
puts e.message
|
85
|
+
ensure
|
86
|
+
@local_git.run("checkout #{@local_git.working_branch}")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def branch_data
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_branches(user_branches)
|
95
|
+
branch_list = user_branches == ['ready'] ? shippable_branch_names : [user_branches].flatten.compact
|
96
|
+
|
97
|
+
branch_list.map { |b| Data::Branch.new('origin', @git.remotes_hash['origin'], b) }
|
98
|
+
end
|
99
|
+
|
100
|
+
def check_branches
|
101
|
+
raise NothingToMergeError.new("Nothing to merge") if @release_branches.empty?
|
102
|
+
|
103
|
+
requested_not_ready_branches = (@release_branches.map(&:ref) - shippable_branch_names)
|
104
|
+
raise RuntimeError.new("The following branches are not ready to ship:\n#{requested_not_ready_branches.join("\n")}") unless requested_not_ready_branches.empty?
|
105
|
+
end
|
106
|
+
|
107
|
+
def shippable_branch_names
|
108
|
+
@shippable_branch_names ||= begin
|
109
|
+
status = Merge::Status.new(Config.configuration.issue_tracker, Config.configuration.branches, Config.configuration.branch_info_file, Config.configuration.git, logger: logger)
|
110
|
+
|
111
|
+
all_branches = status.branches
|
112
|
+
all_branches.values.select { |b| b[:shippable?] }.map { |b| b[:name] }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def commit_message
|
117
|
+
message =<<-EOS
|
118
|
+
Flash Flow merged these branches:
|
119
|
+
#{@release_branches.map(&:ref).join("\n")}
|
120
|
+
EOS
|
121
|
+
message.gsub(/'/, '')
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
File without changes
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require 'flash_flow/
|
1
|
+
require 'flash_flow/merge/release_graph'
|
2
2
|
|
3
3
|
module FlashFlow
|
4
|
-
module
|
4
|
+
module Merge
|
5
5
|
class Status
|
6
6
|
attr_reader :issue_tracker, :collection, :stories, :releases
|
7
7
|
|
8
8
|
def initialize(issue_tracker_config, branches_config, branch_info_file, git_config, opts={})
|
9
9
|
@issue_tracker = IssueTracker::Base.new(issue_tracker_config)
|
10
|
-
@collection = Data::Base.new(branches_config, branch_info_file, ShadowGit.new(git_config)).
|
10
|
+
@collection = Data::Base.new(branches_config, branch_info_file, ShadowGit.new(git_config)).collection
|
11
11
|
end
|
12
12
|
|
13
13
|
def status
|
@@ -14,14 +14,12 @@ module FlashFlow
|
|
14
14
|
user_name = branch.metadata['user_url'].split('/').last
|
15
15
|
user_url_link = %{<a href="#{branch.metadata['user_url']}">#{user_name}</a>}
|
16
16
|
ref_link = %{<a href="#{branch.metadata['repo_url']}/tree/#{branch.ref}">#{branch.ref}</a>}
|
17
|
-
rescue => e
|
18
|
-
puts "An error occurred in the hipchat notifier: #{e.message}."
|
19
|
-
user_url_link = 'Unknown'
|
20
|
-
ref_link = branch.ref
|
21
|
-
end
|
22
17
|
|
23
|
-
|
24
|
-
|
18
|
+
message = %{#{user_url_link}'s branch (#{ref_link}) did not merge successfully}
|
19
|
+
@client[@room].send("FlashFlow", message)
|
20
|
+
rescue HipChat::UnknownResponseCode => e
|
21
|
+
puts e.message
|
22
|
+
end
|
25
23
|
end
|
26
24
|
|
27
25
|
private
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'flash_flow/release/percy_client'
|
2
|
+
|
3
|
+
module FlashFlow
|
4
|
+
module Release
|
5
|
+
class Base
|
6
|
+
def initialize(config=nil)
|
7
|
+
release_class_name = config && config['class'] && config['class']['name']
|
8
|
+
return unless release_class_name
|
9
|
+
|
10
|
+
@release_class = Object.const_get(release_class_name)
|
11
|
+
@release = @release_class.new(config['class'])
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_latest_by_sha(sha)
|
15
|
+
@release.find_latest_by_sha(sha) if @release.respond_to?(:find_latest_by_sha)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'percy'
|
2
|
+
|
3
|
+
module FlashFlow
|
4
|
+
module Release
|
5
|
+
class PercyClient
|
6
|
+
|
7
|
+
def initialize(config={})
|
8
|
+
@client = initialize_connection!(config['token'])
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_latest_by_sha(sha)
|
12
|
+
response = get_builds
|
13
|
+
commit = find_commit_by_sha(response, sha)
|
14
|
+
build = find_build_by_commit_id(response, commit['id'])
|
15
|
+
|
16
|
+
{ url: build['web-url'], approved: !build['approved-at'].nil? }
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def initialize_connection!(token)
|
22
|
+
if token.nil?
|
23
|
+
raise RuntimeError.new("Percy token must be set in your flash flow config.")
|
24
|
+
end
|
25
|
+
|
26
|
+
Percy.client.config.access_token = token
|
27
|
+
percy_client
|
28
|
+
end
|
29
|
+
|
30
|
+
def percy_client
|
31
|
+
Percy.client
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_builds
|
35
|
+
@client.get("#{Percy.config.api_url}/repos/#{Percy.config.repo}/builds/")
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_commit_by_sha(response, sha)
|
39
|
+
commits_data(response).detect { |h| h.dig('attributes', 'sha') == sha }
|
40
|
+
end
|
41
|
+
|
42
|
+
def find_build_by_commit_id(response, commit_id)
|
43
|
+
builds = builds_collection(response)
|
44
|
+
return if builds.nil?
|
45
|
+
|
46
|
+
latest_build = builds
|
47
|
+
.select { |b| b.dig('relationships', 'commit', 'data', 'id') == commit_id }
|
48
|
+
.sort_by { |b| DateTime.parse(b.dig('attributes', 'created-at')) }.last
|
49
|
+
|
50
|
+
latest_build['attributes']
|
51
|
+
end
|
52
|
+
|
53
|
+
def builds_collection(response)
|
54
|
+
response['data'].select do |h|
|
55
|
+
h['type'] == 'builds' &&
|
56
|
+
h.dig('attributes', 'web-url') &&
|
57
|
+
h.dig('relationships', 'commit', 'data', 'type') == 'commits'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def commits_data(response)
|
62
|
+
response['included'].select { |data| data['type'] == 'commits' }
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/flash_flow/version.rb
CHANGED
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
require 'minitest/stub_any_instance'
|
3
|
+
|
4
|
+
module FlashFlow
|
5
|
+
module Merge
|
6
|
+
class TestAcceptance < Minitest::Test
|
7
|
+
|
8
|
+
def setup
|
9
|
+
reset_config!
|
10
|
+
config!(git:
|
11
|
+
{
|
12
|
+
'merge_branch' => 'test_acceptance',
|
13
|
+
'merge_remote' => 'test_remote',
|
14
|
+
'master_branch' => 'test_master',
|
15
|
+
'remotes' => ['fake_origin'],
|
16
|
+
'use_rerere' => true
|
17
|
+
},
|
18
|
+
branches: {}
|
19
|
+
)
|
20
|
+
|
21
|
+
@branch = Data::Branch.from_hash({'ref' => 'pushing_branch', 'remote' => 'origin', 'status' => 'fail', 'stories' => []})
|
22
|
+
@deploy = Acceptance.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_version_is_nil
|
26
|
+
with_versions('1.1.1', nil) do
|
27
|
+
assert_nil(@deploy.check_version)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_check_version_greater
|
32
|
+
with_versions('2.0.0', '1.1.1') do
|
33
|
+
assert_nil(@deploy.check_version)
|
34
|
+
end
|
35
|
+
|
36
|
+
with_versions('1.2.0', '1.1.1') do
|
37
|
+
assert_nil(@deploy.check_version)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_check_version_less_raises
|
42
|
+
with_versions('1.1.1', '2.1.0') do
|
43
|
+
assert_raises(RuntimeError) { @deploy.check_version }
|
44
|
+
end
|
45
|
+
|
46
|
+
with_versions('1.2.0', '2.1.0') do
|
47
|
+
assert_raises(RuntimeError) { @deploy.check_version }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_check_version_equal
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_print_errors_with_no_errors
|
56
|
+
data.expect(:failures, [])
|
57
|
+
assert_equal(@deploy.format_errors, 'Success!')
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_print_errors_when_current_branch_cant_merge
|
61
|
+
data.expect(:failures, [@branch])
|
62
|
+
@branch.fail!('some_random_sha')
|
63
|
+
|
64
|
+
current_branch_error = "ERROR: Your branch did not merge to test_acceptance. Run 'flash_flow --resolve', fix the merge conflict(s) and then re-run this script\n"
|
65
|
+
|
66
|
+
@deploy.instance_variable_get('@local_git'.to_sym).stub(:working_branch, 'pushing_branch') do
|
67
|
+
assert_equal(current_branch_error, @deploy.format_errors)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_print_errors_when_another_branch_cant_merge
|
72
|
+
data.expect(:failures, [@branch])
|
73
|
+
|
74
|
+
other_branch_error = "WARNING: Unable to merge branch origin/pushing_branch to test_acceptance due to conflicts."
|
75
|
+
|
76
|
+
assert_equal(@deploy.format_errors, other_branch_error)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_check_out_to_working_branch
|
80
|
+
@deploy.stub(:check_repo, true) do
|
81
|
+
@deploy.stub(:check_version, true) do
|
82
|
+
Lock::Base.stub_any_instance(:with_lock, -> { raise Lock::Error }) do
|
83
|
+
assert_output(/Failure!/) { @deploy.run }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_deleted_branch
|
90
|
+
data.expect(:mark_deleted, true, [@branch])
|
91
|
+
|
92
|
+
notifier.expect(:deleted_branch, true, [@branch])
|
93
|
+
|
94
|
+
merger.expect(:result, :deleted)
|
95
|
+
|
96
|
+
@deploy.process_result(@branch, merger)
|
97
|
+
|
98
|
+
notifier.verify
|
99
|
+
data.verify
|
100
|
+
merger.verify
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_merge_conflict
|
104
|
+
data.expect(:mark_failure, true, [@branch, nil])
|
105
|
+
|
106
|
+
notifier.expect(:merge_conflict, true, [@branch])
|
107
|
+
|
108
|
+
merger.expect(:result, :conflict)
|
109
|
+
|
110
|
+
@deploy.process_result(@branch, merger)
|
111
|
+
|
112
|
+
notifier.verify
|
113
|
+
data.verify
|
114
|
+
merger.verify
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_successful_merge
|
118
|
+
data.expect(:mark_success, true, [@branch])
|
119
|
+
data.expect(:set_resolutions, true, [@branch, {'filename' => ["resolution_sha"]}])
|
120
|
+
|
121
|
+
merger.
|
122
|
+
expect(:result, :success).
|
123
|
+
expect(:sha, 'sha').
|
124
|
+
expect(:resolutions, {'filename' => ["resolution_sha"]})
|
125
|
+
|
126
|
+
@deploy.process_result(@branch, merger)
|
127
|
+
|
128
|
+
data.verify
|
129
|
+
merger.verify
|
130
|
+
assert_equal(@branch.sha, 'sha')
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_ignore_pushing_master_or_acceptance
|
134
|
+
['test_master', 'test_acceptance'].each do |branch|
|
135
|
+
@deploy.instance_variable_get('@local_git'.to_sym).stub(:working_branch, branch) do
|
136
|
+
refute(@deploy.open_pull_request)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_commit_message_ordering
|
142
|
+
data
|
143
|
+
.expect(:successes, ['data_successes'])
|
144
|
+
.expect(:successes, sample_branches)
|
145
|
+
.expect(:failures, [])
|
146
|
+
.expect(:removals, [])
|
147
|
+
|
148
|
+
expected_message = sample_branches.sort_by(&:merge_order).map(&:ref).join("\n")
|
149
|
+
assert_output(/#{expected_message}/) { print @deploy.commit_message }
|
150
|
+
data.verify
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def with_versions(current, written)
|
156
|
+
original_version = FlashFlow::VERSION
|
157
|
+
FlashFlow.send(:remove_const, :VERSION)
|
158
|
+
FlashFlow.const_set(:VERSION, current)
|
159
|
+
data.expect(:version, written)
|
160
|
+
yield
|
161
|
+
data.verify
|
162
|
+
FlashFlow.send(:remove_const, :VERSION)
|
163
|
+
FlashFlow.const_set(:VERSION, original_version)
|
164
|
+
end
|
165
|
+
|
166
|
+
def merger
|
167
|
+
@merger ||= Minitest::Mock.new
|
168
|
+
end
|
169
|
+
|
170
|
+
def notifier
|
171
|
+
return @notifier if @notifier
|
172
|
+
|
173
|
+
@notifier = Minitest::Mock.new
|
174
|
+
@deploy.instance_variable_set('@notifier'.to_sym, @notifier)
|
175
|
+
end
|
176
|
+
|
177
|
+
def data
|
178
|
+
return @data if @data
|
179
|
+
|
180
|
+
@data = Minitest::Mock.new
|
181
|
+
@deploy.instance_variable_set('@data'.to_sym, @data)
|
182
|
+
end
|
183
|
+
|
184
|
+
def sample_branches
|
185
|
+
@sample_branches ||= [Data::Branch.from_hash({'ref' => 'branch3', 'merge_order' => 2}),
|
186
|
+
Data::Branch.from_hash({'ref' => 'branch1', 'merge_order' => 3}),
|
187
|
+
Data::Branch.from_hash({'ref' => 'branch2', 'merge_order' => 1})]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|