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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a41f62720b6a1d95aac60bc4275d5711b4ab82e3
|
4
|
+
data.tar.gz: 88ca498a5fef9fbec2d48bb12ea0c973123cf15f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d6d4dc8b130952e6c002af7d5f524f35464f2359e88b5c7b01cdae49f8fc63cb11a8c5e97b681c4be509ca9851a50d0040ff60129843c163e01ea1ee115b7ab
|
7
|
+
data.tar.gz: d6f2cf9bcd93e7cf2a169b138a3fadc56b9494702d4bd36a347e9fe9d2b6404022d05e92eb58d987ec53f84484e14f0b6cc11d900f60ab33e98b7a1012ae7492
|
data/Gemfile.lock
CHANGED
@@ -4,6 +4,7 @@ PATH
|
|
4
4
|
flash_flow (1.3.2.1)
|
5
5
|
hipchat (~> 1.5)
|
6
6
|
octokit (~> 4.1)
|
7
|
+
percy-client
|
7
8
|
pivotal-tracker (~> 0.5)
|
8
9
|
ruby-graphviz (> 0)
|
9
10
|
|
@@ -20,7 +21,7 @@ GEM
|
|
20
21
|
crack (0.4.3)
|
21
22
|
safe_yaml (~> 1.0.0)
|
22
23
|
debugger-linecache (1.2.0)
|
23
|
-
domain_name (0.5.
|
24
|
+
domain_name (0.5.20160615)
|
24
25
|
unf (>= 0.0.5, < 1.0.0)
|
25
26
|
faraday (0.9.2)
|
26
27
|
multipart-post (>= 1.2, < 3)
|
@@ -29,11 +30,12 @@ GEM
|
|
29
30
|
mimemagic
|
30
31
|
http-cookie (1.0.2)
|
31
32
|
domain_name (~> 0.5)
|
32
|
-
httparty (0.
|
33
|
-
json (~> 1.8)
|
33
|
+
httparty (0.14.0)
|
34
34
|
multi_xml (>= 0.5.2)
|
35
|
-
|
36
|
-
mime-types (
|
35
|
+
httpclient (2.8.0)
|
36
|
+
mime-types (3.1)
|
37
|
+
mime-types-data (~> 3.2015)
|
38
|
+
mime-types-data (3.2016.0521)
|
37
39
|
mimemagic (0.3.1)
|
38
40
|
mini_portile2 (2.1.0)
|
39
41
|
minitest (5.3.5)
|
@@ -48,6 +50,9 @@ GEM
|
|
48
50
|
nokogiri (~> 1.5)
|
49
51
|
octokit (4.3.0)
|
50
52
|
sawyer (~> 0.7.0, >= 0.5.3)
|
53
|
+
percy-client (1.6.0)
|
54
|
+
faraday (>= 0.9)
|
55
|
+
httpclient (>= 2.6)
|
51
56
|
pivotal-tracker (0.5.13)
|
52
57
|
builder
|
53
58
|
crack
|
@@ -56,10 +61,10 @@ GEM
|
|
56
61
|
rest-client (>= 1.8.0)
|
57
62
|
pkg-config (1.1.7)
|
58
63
|
rake (10.4.2)
|
59
|
-
rest-client (
|
64
|
+
rest-client (2.0.0)
|
60
65
|
http-cookie (>= 1.0.2, < 2.0)
|
61
|
-
mime-types (>= 1.16, <
|
62
|
-
netrc (~> 0.
|
66
|
+
mime-types (>= 1.16, < 4.0)
|
67
|
+
netrc (~> 0.8)
|
63
68
|
ruby-graphviz (1.2.2)
|
64
69
|
safe_yaml (1.0.4)
|
65
70
|
sawyer (0.7.0)
|
data/bin/flash_flow
CHANGED
@@ -25,12 +25,12 @@ case
|
|
25
25
|
when options[:resolve_manual]
|
26
26
|
FlashFlow::Resolve.new(FlashFlow::Config.configuration.git, FlashFlow::Config.configuration.branch_info_file, logger: FlashFlow::Config.configuration.logger).manual_instructions
|
27
27
|
when options[:merge_status]
|
28
|
-
FlashFlow::
|
28
|
+
FlashFlow::Merge::Status.new(FlashFlow::Config.configuration.issue_tracker, FlashFlow::Config.configuration.branches, FlashFlow::Config.configuration.branch_info_file, FlashFlow::Config.configuration.git, logger: FlashFlow::Config.configuration.logger).status
|
29
29
|
when options[:merge_status_html]
|
30
|
-
FlashFlow::
|
30
|
+
FlashFlow::Merge::Status.new(FlashFlow::Config.configuration.issue_tracker, FlashFlow::Config.configuration.branches, FlashFlow::Config.configuration.branch_info_file, FlashFlow::Config.configuration.git, logger: FlashFlow::Config.configuration.logger).status_html
|
31
31
|
when options[:release_branches]
|
32
|
-
FlashFlow::
|
32
|
+
FlashFlow::Merge::Master.new(options).run
|
33
33
|
else
|
34
|
-
FlashFlow::
|
34
|
+
FlashFlow::Merge::Acceptance.new(options).run
|
35
35
|
FlashFlow::IssueTracker::Base.new(FlashFlow::Config.configuration.issue_tracker).stories_pushed
|
36
36
|
end
|
data/flash_flow.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_dependency 'hipchat', "~> 1.5"
|
22
22
|
spec.add_dependency 'pivotal-tracker', "~> 0.5"
|
23
23
|
spec.add_dependency 'ruby-graphviz', "> 0"
|
24
|
+
spec.add_dependency 'percy-client'
|
24
25
|
|
25
26
|
spec.add_development_dependency "bundler", "~> 1.6"
|
26
27
|
spec.add_development_dependency "rake", "> 0"
|
data/flash_flow.yml.erb.example
CHANGED
@@ -82,3 +82,10 @@ branch_info_file: 'your/random/file'
|
|
82
82
|
# unmergeable_label: unmergeable
|
83
83
|
# do_not_merge_label: 'do not merge'
|
84
84
|
# shippable_label: 'shippable'
|
85
|
+
|
86
|
+
#release:
|
87
|
+
# class:
|
88
|
+
# name: 'FlashFlow::Release::Percy'
|
89
|
+
# token: <%= ENV['PERCY_TOKEN'] %>
|
90
|
+
# repo: # Your github repo. For example, the flash_flow repo is 'flashfunders/flash_flow'
|
91
|
+
# api_url: 'https://percy.io/api/v1/'
|
data/lib/flash_flow.rb
CHANGED
@@ -3,7 +3,7 @@ module FlashFlow; end
|
|
3
3
|
require 'flash_flow/options'
|
4
4
|
require 'flash_flow/install'
|
5
5
|
require 'flash_flow/config'
|
6
|
-
require 'flash_flow/deploy'
|
7
6
|
require 'flash_flow/issue_tracker'
|
8
7
|
require 'flash_flow/resolve'
|
9
|
-
require 'flash_flow/
|
8
|
+
require 'flash_flow/merge'
|
9
|
+
require 'flash_flow/release'
|
data/lib/flash_flow/config.rb
CHANGED
@@ -16,7 +16,7 @@ module FlashFlow
|
|
16
16
|
end
|
17
17
|
|
18
18
|
ATTRIBUTES = [
|
19
|
-
:git, :branch_info_file, :log_file, :notifier, :issue_tracker, :lock, :branches
|
19
|
+
:git, :branch_info_file, :log_file, :notifier, :issue_tracker, :lock, :branches, :release
|
20
20
|
]
|
21
21
|
|
22
22
|
attr_reader *ATTRIBUTES
|
@@ -55,6 +55,7 @@ module FlashFlow
|
|
55
55
|
issue_tracker: nil,
|
56
56
|
lock: nil,
|
57
57
|
branches: nil,
|
58
|
+
release: nil
|
58
59
|
}
|
59
60
|
end
|
60
61
|
|
data/lib/flash_flow/data/base.rb
CHANGED
@@ -13,6 +13,8 @@ module FlashFlow
|
|
13
13
|
:remove_from_merge, :add_to_merge, :failures, :successes, :removals, :set_resolutions,
|
14
14
|
:to_a, :code_reviewed?, :branch_link
|
15
15
|
|
16
|
+
attr_reader :collection
|
17
|
+
|
16
18
|
def initialize(branch_config, filename, git, opts={})
|
17
19
|
@git = git
|
18
20
|
@store = Store.new(filename, git, opts)
|
@@ -20,14 +22,23 @@ module FlashFlow
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def initialize_collection(branch_config, remotes)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
stored_collection = Collection.from_hash(remotes, stored_branches)
|
26
|
+
|
27
|
+
if ! branch_config.empty?
|
28
|
+
collection = Collection.fetch(remotes, branch_config)
|
29
|
+
# Order matters. We are marking the PRs as current, not the branches stored in the json
|
30
|
+
collection.mark_all_as_current
|
31
|
+
collection.reverse_merge(stored_collection)
|
32
|
+
|
33
|
+
else
|
34
|
+
collection = stored_collection
|
35
|
+
collection.mark_all_as_current
|
36
|
+
collection
|
37
|
+
end
|
27
38
|
end
|
28
39
|
|
29
40
|
def version
|
30
|
-
|
41
|
+
stored_data['version']
|
31
42
|
end
|
32
43
|
|
33
44
|
def save!
|
@@ -37,24 +48,29 @@ module FlashFlow
|
|
37
48
|
def to_hash
|
38
49
|
{
|
39
50
|
'version' => FlashFlow::VERSION,
|
40
|
-
'branches' =>
|
51
|
+
'branches' => @collection.to_hash,
|
52
|
+
'releases' => releases
|
41
53
|
}
|
42
54
|
end
|
43
55
|
|
44
|
-
def
|
45
|
-
@
|
56
|
+
def stored_branches
|
57
|
+
@stored_branches ||= stored_data['branches'] || {}
|
46
58
|
end
|
47
59
|
|
48
|
-
def
|
49
|
-
@
|
50
|
-
|
60
|
+
def releases
|
61
|
+
@releases ||= stored_data['releases'] || []
|
62
|
+
end
|
51
63
|
|
52
|
-
|
53
|
-
|
64
|
+
def merged_branches
|
65
|
+
@collection.reverse_merge(Collection.from_hash({}, stored_branches))
|
66
|
+
end
|
67
|
+
|
68
|
+
def stored_data
|
69
|
+
@stored_data ||= @store.get
|
54
70
|
end
|
55
71
|
|
56
72
|
def saved_branches
|
57
|
-
Collection.from_hash(@git.remotes,
|
73
|
+
Collection.from_hash(@git.remotes, stored_branches).to_a
|
58
74
|
end
|
59
75
|
end
|
60
76
|
end
|
data/lib/flash_flow/git.rb
CHANGED
@@ -63,9 +63,13 @@ module FlashFlow
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
def
|
66
|
+
def branch_contains?(branch, ref)
|
67
67
|
run("branch --contains #{ref}", log: CmdRunner::LOG_CMD)
|
68
|
-
last_stdout.split("\n").detect { |str| str[2..-1] ==
|
68
|
+
last_stdout.split("\n").detect { |str| str[2..-1] == branch }
|
69
|
+
end
|
70
|
+
|
71
|
+
def master_branch_contains?(ref)
|
72
|
+
branch_contains?(master_branch, ref)
|
69
73
|
end
|
70
74
|
|
71
75
|
def in_original_merge_branch
|
@@ -197,7 +201,7 @@ module FlashFlow
|
|
197
201
|
run("push #{'-f' if force} #{merge_remote} #{branch}")
|
198
202
|
end
|
199
203
|
|
200
|
-
def
|
204
|
+
def copy_temp_to_branch(branch, squash_message = nil)
|
201
205
|
run("checkout #{temp_merge_branch}")
|
202
206
|
run("merge --strategy=ours --no-edit #{branch}")
|
203
207
|
run("checkout #{branch}")
|
@@ -232,6 +236,20 @@ module FlashFlow
|
|
232
236
|
end
|
233
237
|
end
|
234
238
|
|
239
|
+
def temp_merge_branch
|
240
|
+
"flash_flow/#{merge_branch}"
|
241
|
+
end
|
242
|
+
|
243
|
+
def get_sha(branch)
|
244
|
+
run("rev-parse #{branch}")
|
245
|
+
last_stdout.strip if last_success?
|
246
|
+
end
|
247
|
+
|
248
|
+
def branch_exists?(branch)
|
249
|
+
run("rev-parse --verify #{branch}")
|
250
|
+
last_success?
|
251
|
+
end
|
252
|
+
|
235
253
|
private
|
236
254
|
|
237
255
|
def squash_commits(branch, commit_message)
|
@@ -249,14 +267,5 @@ module FlashFlow
|
|
249
267
|
run("commit -m '#{commit_message}'")
|
250
268
|
end
|
251
269
|
|
252
|
-
def branch_exists?(branch)
|
253
|
-
run("rev-parse --verify #{branch}")
|
254
|
-
last_success?
|
255
|
-
end
|
256
|
-
|
257
|
-
def temp_merge_branch
|
258
|
-
"flash_flow/#{merge_branch}"
|
259
|
-
end
|
260
|
-
|
261
270
|
end
|
262
271
|
end
|
@@ -59,7 +59,7 @@ module FlashFlow
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def get_branches
|
62
|
-
branch_info_store = Data::Base.new(
|
62
|
+
branch_info_store = Data::Base.new({}, Config.configuration.branch_info_file, git, logger: Config.configuration.logger)
|
63
63
|
|
64
64
|
branch_info_store.saved_branches
|
65
65
|
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'flash_flow/merge/base'
|
2
|
+
|
3
|
+
module FlashFlow
|
4
|
+
module Merge
|
5
|
+
class Acceptance < Base
|
6
|
+
|
7
|
+
def initialize(opts={})
|
8
|
+
super(opts)
|
9
|
+
|
10
|
+
@data = Data::Base.new(Config.configuration.branches, Config.configuration.branch_info_file, @git, logger: logger)
|
11
|
+
|
12
|
+
@do_not_merge = opts[:do_not_merge]
|
13
|
+
@force = opts[:force]
|
14
|
+
@rerere_forget = opts[:rerere_forget]
|
15
|
+
@stories = [opts[:stories]].flatten.compact
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
check_version
|
20
|
+
check_repo
|
21
|
+
puts "Building #{@local_git.merge_branch}... Log can be found in #{FlashFlow::Config.configuration.log_file}"
|
22
|
+
logger.info "\n\n### Beginning #{@local_git.merge_branch} merge ###\n\n"
|
23
|
+
|
24
|
+
begin
|
25
|
+
open_pull_request
|
26
|
+
|
27
|
+
@lock.with_lock do
|
28
|
+
@git.fetch(@git.merge_remote)
|
29
|
+
@git.in_original_merge_branch do
|
30
|
+
@git.initialize_rerere
|
31
|
+
end
|
32
|
+
|
33
|
+
@git.reset_temp_merge_branch
|
34
|
+
@git.in_temp_merge_branch do
|
35
|
+
merge_branches(@data.mergeable) do |branch, merger|
|
36
|
+
process_result(branch, merger)
|
37
|
+
end
|
38
|
+
commit_branch_info
|
39
|
+
commit_rerere
|
40
|
+
end
|
41
|
+
|
42
|
+
@git.copy_temp_to_branch(@git.merge_branch, commit_message)
|
43
|
+
@git.delete_temp_merge_branch
|
44
|
+
@git.push(@git.merge_branch, true)
|
45
|
+
end
|
46
|
+
|
47
|
+
print_errors
|
48
|
+
logger.info "### Finished #{@local_git.merge_branch} merge ###"
|
49
|
+
rescue Lock::Error, OutOfSyncWithRemote => e
|
50
|
+
puts 'Failure!'
|
51
|
+
puts e.message
|
52
|
+
ensure
|
53
|
+
@local_git.run("checkout #{@local_git.working_branch}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def commit_branch_info
|
58
|
+
@stories.each do |story_id|
|
59
|
+
@data.add_story(@git.merge_remote, @git.working_branch, story_id)
|
60
|
+
end
|
61
|
+
@data.save!
|
62
|
+
end
|
63
|
+
|
64
|
+
def commit_rerere
|
65
|
+
current_branches = @data.to_a.select { |branch| !@git.master_branch_contains?(branch.sha) && (Time.now - branch.updated_at < two_weeks) }
|
66
|
+
current_rereres = current_branches.map { |branch| branch.resolutions.to_h.values }.flatten
|
67
|
+
|
68
|
+
@git.commit_rerere(current_rereres)
|
69
|
+
end
|
70
|
+
|
71
|
+
def two_weeks
|
72
|
+
60 * 60 * 24 * 14
|
73
|
+
end
|
74
|
+
|
75
|
+
def process_result(branch, merger)
|
76
|
+
case merger.result
|
77
|
+
when :deleted
|
78
|
+
@data.mark_deleted(branch)
|
79
|
+
@notifier.deleted_branch(branch) unless is_working_branch(branch)
|
80
|
+
|
81
|
+
when :success
|
82
|
+
branch.sha = merger.sha
|
83
|
+
@data.mark_success(branch)
|
84
|
+
@data.set_resolutions(branch, merger.resolutions)
|
85
|
+
|
86
|
+
when :conflict
|
87
|
+
if is_working_branch(branch)
|
88
|
+
@data.mark_failure(branch, merger.conflict_sha)
|
89
|
+
else
|
90
|
+
@data.mark_failure(branch, nil)
|
91
|
+
@notifier.merge_conflict(branch)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def is_working_branch(branch)
|
97
|
+
branch.ref == @git.working_branch
|
98
|
+
end
|
99
|
+
|
100
|
+
def open_pull_request
|
101
|
+
return false if [@local_git.master_branch, @local_git.merge_branch].include?(@local_git.working_branch)
|
102
|
+
|
103
|
+
# TODO - This should use the actual remote for the branch we're on
|
104
|
+
@local_git.push(@local_git.working_branch, @force)
|
105
|
+
raise OutOfSyncWithRemote.new("Your branch is out of sync with the remote. If you want to force push, run 'flash_flow -f'") unless @local_git.last_success?
|
106
|
+
|
107
|
+
# TODO - This should use the actual remote for the branch we're on
|
108
|
+
if @do_not_merge
|
109
|
+
@data.remove_from_merge(@local_git.merge_remote, @local_git.working_branch)
|
110
|
+
else
|
111
|
+
@data.add_to_merge(@local_git.merge_remote, @local_git.working_branch)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def print_errors
|
116
|
+
puts format_errors
|
117
|
+
end
|
118
|
+
|
119
|
+
def format_errors
|
120
|
+
errors = []
|
121
|
+
branch_not_merged = nil
|
122
|
+
@data.failures.each do |branch|
|
123
|
+
if branch.ref == @local_git.working_branch
|
124
|
+
branch_not_merged = "ERROR: Your branch did not merge to #{@local_git.merge_branch}. Run 'flash_flow --resolve', fix the merge conflict(s) and then re-run this script\n"
|
125
|
+
else
|
126
|
+
errors << "WARNING: Unable to merge branch #{branch.remote}/#{branch.ref} to #{@local_git.merge_branch} due to conflicts."
|
127
|
+
end
|
128
|
+
end
|
129
|
+
errors << branch_not_merged if branch_not_merged
|
130
|
+
|
131
|
+
if errors.empty?
|
132
|
+
"Success!"
|
133
|
+
else
|
134
|
+
errors.join("\n")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def commit_message
|
139
|
+
message =<<-EOS
|
140
|
+
Flash Flow run from branch: #{@local_git.working_branch}
|
141
|
+
|
142
|
+
Merged branches:
|
143
|
+
#{@data.successes.empty? ? 'None' : @data.successes.sort_by(&:merge_order).map(&:ref).join("\n")}
|
144
|
+
|
145
|
+
Failed branches:
|
146
|
+
#{@data.failures.empty? ? 'None' : @data.failures.map(&:ref).join("\n")}
|
147
|
+
|
148
|
+
Removed branches:
|
149
|
+
#{@data.removals.empty? ? 'None' : @data.removals.map(&:ref).join("\n")}
|
150
|
+
EOS
|
151
|
+
message.gsub(/'/, '')
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|