flash_flow 1.4.9 → 1.4.10
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 +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
|