flash_flow 1.4.9 → 1.4.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +40 -2
- data/bin/flash_flow +2 -0
- data/flash_flow.gemspec +1 -0
- data/flash_flow.yml.erb.example +20 -7
- data/lib/flash_flow/google_drive.rb +43 -0
- data/lib/flash_flow/options.rb +1 -0
- data/lib/flash_flow/release.rb +4 -0
- data/lib/flash_flow/release/percy_client.rb +67 -6
- data/lib/flash_flow/version.rb +1 -1
- data/test/lib/release/test_percy_client.rb +2 -2
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 952e4f7a486fdb5f394ff02c131bf51fac271d54
|
4
|
+
data.tar.gz: 4c7c524879fcf1902f899609b2e5fd2c53cb208c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9303c67f43148c4bbaddf614a16d36bfe14f1f5ed7bad729c9f3916af849fa9a427ffc5159ba3927bdbc9d842530d310ca4e4349c5d3922f70b8a804cf4fa6d7
|
7
|
+
data.tar.gz: efa60f954abd042a8f714d4d3ee50f1cb5b3f50c401c16bcde11a62f34d9be79904567f9be9772e8c5165e067cedcd1501ea929603dc757c1bf96a1261dbaf2d
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
flash_flow (1.4.
|
4
|
+
flash_flow (1.4.10)
|
5
|
+
google-api-client
|
5
6
|
hipchat (~> 1.5)
|
6
7
|
mail
|
7
8
|
octokit (~> 4.1)
|
@@ -27,6 +28,24 @@ GEM
|
|
27
28
|
unf (>= 0.0.5, < 1.0.0)
|
28
29
|
faraday (0.9.2)
|
29
30
|
multipart-post (>= 1.2, < 3)
|
31
|
+
google-api-client (0.9.12)
|
32
|
+
addressable (~> 2.3)
|
33
|
+
googleauth (~> 0.5)
|
34
|
+
httpclient (~> 2.7)
|
35
|
+
hurley (~> 0.1)
|
36
|
+
memoist (~> 0.11)
|
37
|
+
mime-types (>= 1.6)
|
38
|
+
representable (~> 2.3.0)
|
39
|
+
retriable (~> 2.0)
|
40
|
+
thor (~> 0.19)
|
41
|
+
googleauth (0.5.1)
|
42
|
+
faraday (~> 0.9)
|
43
|
+
jwt (~> 1.4)
|
44
|
+
logging (~> 2.0)
|
45
|
+
memoist (~> 0.12)
|
46
|
+
multi_json (~> 1.11)
|
47
|
+
os (~> 0.9)
|
48
|
+
signet (~> 0.7)
|
30
49
|
hipchat (1.5.3)
|
31
50
|
httparty
|
32
51
|
mimemagic
|
@@ -34,9 +53,16 @@ GEM
|
|
34
53
|
domain_name (~> 0.5)
|
35
54
|
httparty (0.14.0)
|
36
55
|
multi_xml (>= 0.5.2)
|
37
|
-
httpclient (2.8.2)
|
56
|
+
httpclient (2.8.2.2)
|
57
|
+
hurley (0.2)
|
58
|
+
jwt (1.5.4)
|
59
|
+
little-plugger (1.1.4)
|
60
|
+
logging (2.1.0)
|
61
|
+
little-plugger (~> 1.1)
|
62
|
+
multi_json (~> 1.10)
|
38
63
|
mail (2.6.4)
|
39
64
|
mime-types (>= 1.16, < 4)
|
65
|
+
memoist (0.14.0)
|
40
66
|
mime-types (3.1)
|
41
67
|
mime-types-data (~> 3.2015)
|
42
68
|
mime-types-data (3.2016.0521)
|
@@ -44,6 +70,7 @@ GEM
|
|
44
70
|
mini_portile2 (2.1.0)
|
45
71
|
minitest (5.3.5)
|
46
72
|
minitest-stub_any_instance (1.0.1)
|
73
|
+
multi_json (1.12.1)
|
47
74
|
multi_xml (0.5.5)
|
48
75
|
multipart-post (2.0.0)
|
49
76
|
netrc (0.11.0)
|
@@ -54,6 +81,7 @@ GEM
|
|
54
81
|
nokogiri (~> 1.5)
|
55
82
|
octokit (4.3.0)
|
56
83
|
sawyer (~> 0.7.0, >= 0.5.3)
|
84
|
+
os (0.9.6)
|
57
85
|
pdf-core (0.6.1)
|
58
86
|
percy-client (1.6.0)
|
59
87
|
faraday (>= 0.9)
|
@@ -69,17 +97,27 @@ GEM
|
|
69
97
|
pdf-core (~> 0.6.1)
|
70
98
|
ttfunk (~> 1.4.0)
|
71
99
|
rake (10.4.2)
|
100
|
+
representable (2.3.0)
|
101
|
+
uber (~> 0.0.7)
|
72
102
|
rest-client (2.0.0)
|
73
103
|
http-cookie (>= 1.0.2, < 2.0)
|
74
104
|
mime-types (>= 1.16, < 4.0)
|
75
105
|
netrc (~> 0.8)
|
106
|
+
retriable (2.1.0)
|
76
107
|
ruby-graphviz (1.2.2)
|
77
108
|
safe_yaml (1.0.4)
|
78
109
|
sawyer (0.7.0)
|
79
110
|
addressable (>= 2.3.5, < 2.5)
|
80
111
|
faraday (~> 0.8, < 0.10)
|
112
|
+
signet (0.7.3)
|
113
|
+
addressable (~> 2.3)
|
114
|
+
faraday (~> 0.9)
|
115
|
+
jwt (~> 1.5)
|
116
|
+
multi_json (~> 1.10)
|
81
117
|
slop (3.6.0)
|
118
|
+
thor (0.19.1)
|
82
119
|
ttfunk (1.4.0)
|
120
|
+
uber (0.0.15)
|
83
121
|
unf (0.1.4)
|
84
122
|
unf_ext
|
85
123
|
unf_ext (0.0.7.2)
|
data/bin/flash_flow
CHANGED
@@ -36,6 +36,8 @@ case
|
|
36
36
|
FlashFlow::Release::Base.new(FlashFlow::Config.configuration.release).gen_pdf_diffs(*options[:gen_pdf_diffs])
|
37
37
|
when options[:merge_release]
|
38
38
|
FlashFlow::Merge::Master.new(options).run
|
39
|
+
when options[:notify_compliance]
|
40
|
+
FlashFlow::Release::Base.new(FlashFlow::Config.configuration.release).send_compliance_email
|
39
41
|
else
|
40
42
|
FlashFlow::Merge::Acceptance.new(options).run
|
41
43
|
FlashFlow::IssueTracker::Base.new(FlashFlow::Config.configuration.issue_tracker).stories_pushed
|
data/flash_flow.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_dependency 'percy-client'
|
25
25
|
spec.add_dependency 'mail'
|
26
26
|
spec.add_dependency 'prawn'
|
27
|
+
spec.add_dependency 'google-api-client'
|
27
28
|
|
28
29
|
spec.add_development_dependency "bundler", "~> 1.6"
|
29
30
|
spec.add_development_dependency "rake", "> 0"
|
data/flash_flow.yml.erb.example
CHANGED
@@ -89,8 +89,20 @@ branch_info_file: 'your/random/file'
|
|
89
89
|
# token: <%= ENV['PERCY_TOKEN'] %>
|
90
90
|
# repo: # Your github repo. For example, the flash_flow repo is 'flashfunders/flash_flow'
|
91
91
|
# api_url: 'https://percy.io/api/v1/'
|
92
|
-
#
|
93
|
-
#
|
92
|
+
# compliance:
|
93
|
+
# max_wait_time: minutes to wait
|
94
|
+
# delay: minutes between checks
|
95
|
+
# file_prefix: 'Release_Candidate_'
|
96
|
+
# permissions:
|
97
|
+
# group:
|
98
|
+
# reader: comma-delimited list of emails
|
99
|
+
# writer: comma-delimited list of emails
|
100
|
+
# user:
|
101
|
+
# reader: comma-delimited list of emails
|
102
|
+
# writer: comma-delimited list of emails
|
103
|
+
# notify: true
|
104
|
+
# message: 'string for the message body. %percy_url% will be replaced with the url to the percy build'
|
105
|
+
|
94
106
|
#smtp:
|
95
107
|
# settings:
|
96
108
|
# domain: 'yourdomain.com'
|
@@ -101,8 +113,9 @@ branch_info_file: 'your/random/file'
|
|
101
113
|
# authentication: 'plain'
|
102
114
|
# enable_starttls_auto: true
|
103
115
|
# emails:
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
116
|
+
# release_ready:
|
117
|
+
# from: 'sender@domain.com'
|
118
|
+
# to: 'receiver@domain.com'
|
119
|
+
# cc: 'cc@domain.com'
|
120
|
+
# subject: 'The engineering team has a new release candidate'
|
121
|
+
# body_file: 'path/to/email_template.erb'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'google/api_client/client_secrets'
|
2
|
+
require 'google/apis/drive_v3'
|
3
|
+
|
4
|
+
module FlashFlow
|
5
|
+
module Release
|
6
|
+
class GoogleDrive
|
7
|
+
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
DRIVE = Google::Apis::DriveV3
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
scopes = [DRIVE::AUTH_DRIVE]
|
14
|
+
@client = DRIVE::DriveService.new
|
15
|
+
@client.authorization = Google::Auth.get_application_default(scopes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def upload_file(local_file, config={})
|
19
|
+
metadata = DRIVE::File.new(name: File.basename(local_file), extension: 'pdf')
|
20
|
+
metadata = @client.create_file(metadata, upload_source: local_file, content_type: 'application/pdf')
|
21
|
+
set_file_permissions(metadata.id, config)
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_files(query)
|
25
|
+
response = @client.list_files(q: query)
|
26
|
+
response.files
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_file_permissions(file_id, config={})
|
30
|
+
@client.batch do
|
31
|
+
%w(group user).each do |type|
|
32
|
+
%w(reader writer).each do |role| # owner is currently not supported
|
33
|
+
config.dig('permissions', type, role).to_s.split(',').each do |email|
|
34
|
+
permission = DRIVE::Permission.new(role: role, type: type, email_address: email)
|
35
|
+
@client.create_permission(file_id, permission, email_message: config[:email_body], send_notification_email: config['notify'])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/flash_flow/options.rb
CHANGED
@@ -27,6 +27,7 @@ module FlashFlow
|
|
27
27
|
opts.on('--make-release branch1,branch2', 'Comma-delimited list of branches to merge to the release branch. Run "--merge-release ready" to merge all ready to ship branches') { |v| options[:release_branches] = v.split(',') }
|
28
28
|
opts.on('--gen-pdf-diffs output_file,build_id,threshold', 'Generate a pdf file with screenshot differences for the specified (latest) build. output_file is required. build_id defaults to the latest build. threshold defaults to 0') { |v| options[:gen_pdf_diffs] = v.split(',') }
|
29
29
|
opts.on('--merge-release', 'Merge the release branch into the master branch and push') { |v| options[:merge_release] = true }
|
30
|
+
opts.on('--notify-compliance', 'Send the compliance notification email if everything is ready') { |v| options[:notify_compliance] = true }
|
30
31
|
|
31
32
|
opts.on_tail('-h', '--help', 'Show this message') do
|
32
33
|
puts opts
|
data/lib/flash_flow/release.rb
CHANGED
@@ -17,6 +17,10 @@ module FlashFlow
|
|
17
17
|
@release.find_latest_by_sha(sha) if @release.respond_to?(:find_latest_by_sha)
|
18
18
|
end
|
19
19
|
|
20
|
+
def send_compliance_email
|
21
|
+
@release.send_compliance_email if @release.respond_to?(:send_compliance_email)
|
22
|
+
end
|
23
|
+
|
20
24
|
def send_release_email
|
21
25
|
@release.send_release_email if @release.respond_to?(:send_release_email)
|
22
26
|
end
|
@@ -2,6 +2,7 @@ require 'percy'
|
|
2
2
|
require 'flash_flow/git'
|
3
3
|
require 'flash_flow/mailer'
|
4
4
|
require 'flash_flow/release/pdf_diff_generator'
|
5
|
+
require 'flash_flow/google_drive'
|
5
6
|
|
6
7
|
module FlashFlow
|
7
8
|
module Release
|
@@ -10,6 +11,7 @@ module FlashFlow
|
|
10
11
|
def initialize(config={})
|
11
12
|
@client = initialize_connection!(config)
|
12
13
|
@git = ShadowGit.new(Config.configuration.git, Config.configuration.logger)
|
14
|
+
@compliance_config = config['compliance']
|
13
15
|
end
|
14
16
|
|
15
17
|
def find_latest_by_sha(sha)
|
@@ -18,10 +20,20 @@ module FlashFlow
|
|
18
20
|
find_build_by_commit_id(response, commit['id'])
|
19
21
|
end
|
20
22
|
|
23
|
+
def send_compliance_email
|
24
|
+
max_wait_time = @compliance_config['max_wait_time'] || 0
|
25
|
+
delay = @compliance_config['delay'] || 1
|
26
|
+
build = find_completed_build_by_sha(get_latest_sha, max_wait_time, delay)
|
27
|
+
|
28
|
+
unless build_approved?(build)
|
29
|
+
gen_compliance_pdf_file(build)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
def send_release_email
|
22
34
|
build = find_latest_by_sha(get_latest_sha)
|
23
35
|
|
24
|
-
|
36
|
+
unless build_approved?(build)
|
25
37
|
mailer.deliver!(:compliance, { percy_build_url: build['web-url'] })
|
26
38
|
end
|
27
39
|
end
|
@@ -39,8 +51,52 @@ module FlashFlow
|
|
39
51
|
|
40
52
|
private
|
41
53
|
|
54
|
+
def find_completed_build_by_sha(sha, max_wait_time=5, delay=1)
|
55
|
+
max_wait_time *= 60
|
56
|
+
delay *= 60
|
57
|
+
build = find_latest_by_sha(sha)
|
58
|
+
start_time = Time.now
|
59
|
+
|
60
|
+
until build_completed?(build) do
|
61
|
+
return nil if Time.now - start_time >= max_wait_time
|
62
|
+
putc '#'
|
63
|
+
sleep delay
|
64
|
+
build = find_latest_by_sha(sha)
|
65
|
+
end
|
66
|
+
build
|
67
|
+
end
|
68
|
+
|
69
|
+
def gen_compliance_pdf_file(build)
|
70
|
+
build_id = extract_build_id(build)
|
71
|
+
base_file_name = gen_compliance_file_name(build_id)
|
72
|
+
drive = GoogleDrive.new
|
73
|
+
existing_files = drive.find_files("name contains '#{File.basename(base_file_name)}' and mimeType = 'application/pdf'")
|
74
|
+
|
75
|
+
if existing_files.empty?
|
76
|
+
file_name = "#{base_file_name}_#{Time.now.strftime('%Y%m%dT%H%M')}.pdf"
|
77
|
+
gen_pdf_diffs(file_name, build_id)
|
78
|
+
|
79
|
+
puts "Uploading #{file_name} to Google Drive"
|
80
|
+
drive.upload_file(file_name, @compliance_config.merge({ email_body: compose_compliance_email_body(build) }))
|
81
|
+
else
|
82
|
+
puts "This build has already been processed: #{existing_files.first.name}."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def gen_compliance_file_name(build_id)
|
87
|
+
"/tmp/#{@compliance_config['file_prefix']}#{build_id}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def compose_compliance_email_body(build)
|
91
|
+
@compliance_config['message'].sub('%percy_url%', build['web-url'])
|
92
|
+
end
|
93
|
+
|
42
94
|
def get_build_id(sha=nil)
|
43
95
|
build = find_latest_by_sha(sha || get_latest_sha)
|
96
|
+
extract_build_id(build)
|
97
|
+
end
|
98
|
+
|
99
|
+
def extract_build_id(build)
|
44
100
|
build['web-url'].split('/').last
|
45
101
|
end
|
46
102
|
|
@@ -75,19 +131,24 @@ module FlashFlow
|
|
75
131
|
|
76
132
|
def builds_collection(response)
|
77
133
|
response.fetch('data', [])
|
78
|
-
.select do |h|
|
134
|
+
.select do |h|
|
135
|
+
h['type'] == 'builds' &&
|
79
136
|
h.dig('attributes', 'web-url') &&
|
80
137
|
h.dig('relationships', 'commit', 'data', 'type') == 'commits'
|
81
|
-
|
138
|
+
end
|
82
139
|
end
|
83
140
|
|
84
141
|
def commits_data(response)
|
85
|
-
response.fetch('included', {'id' => nil})
|
142
|
+
response.fetch('included', { 'id' => nil })
|
86
143
|
.select { |data| data['type'] == 'commits' }
|
87
144
|
end
|
88
145
|
|
89
|
-
def
|
90
|
-
build
|
146
|
+
def build_approved?(build)
|
147
|
+
!build.nil? && !build['approved-at'].nil?
|
148
|
+
end
|
149
|
+
|
150
|
+
def build_completed?(build)
|
151
|
+
build['state'] == 'finished';
|
91
152
|
end
|
92
153
|
|
93
154
|
def get_latest_sha
|
data/lib/flash_flow/version.rb
CHANGED
@@ -59,10 +59,10 @@ module FlashFlow
|
|
59
59
|
def test_has_unapproved_diffs?
|
60
60
|
@percy_client.stub(:get_builds, sample_response) do
|
61
61
|
build1 = @percy_client.find_latest_by_sha('bbbbb')
|
62
|
-
|
62
|
+
refute(@percy_client.send(:build_approved?, build1))
|
63
63
|
|
64
64
|
build2 = @percy_client.find_latest_by_sha('aaaaa')
|
65
|
-
|
65
|
+
assert(@percy_client.send(:build_approved?, build2))
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flash_flow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Flashfunders
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: octokit
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: google-api-client
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: bundler
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -208,6 +222,7 @@ files:
|
|
208
222
|
- lib/flash_flow/data/github.rb
|
209
223
|
- lib/flash_flow/data/store.rb
|
210
224
|
- lib/flash_flow/git.rb
|
225
|
+
- lib/flash_flow/google_drive.rb
|
211
226
|
- lib/flash_flow/install.rb
|
212
227
|
- lib/flash_flow/issue_tracker.rb
|
213
228
|
- lib/flash_flow/issue_tracker/pivotal.rb
|