flash_flow 1.4.5 → 1.4.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4aff3163ea68205769ff9157ffcc3186797b571c
4
- data.tar.gz: d917594c16e2f836b6572922a227df7f696bbd39
3
+ metadata.gz: 4b4faf52faa0345d39f5a6b125d897a33ef97dc6
4
+ data.tar.gz: 96e3e0f1160587d5bbd972a4357f82c92807704d
5
5
  SHA512:
6
- metadata.gz: 39d51941b834bc218524412c37e7fd02309a3e947e39aad06ff5b45ff0815fa65c79bb6939accff3c98072c0c119e3e82753f195c1f9901101ae27b5694c4238
7
- data.tar.gz: 75ba31076eaa53acb0f84a81088f7dcd4e21e892e03bd9903be25ba38df81f4c87c3fd747f49bead11ce399bf6857b6643d16a14fe0f60c412b56df2917d585f
6
+ metadata.gz: d513f6f38ac8bd6e8e44e2e380975f7fafd9c1f28c60999b1d91d33312daff171fd97e855a3d9fdcfa5f1190dad7ae4f3caab9b5336d7531d1dd96b13a0b372d
7
+ data.tar.gz: 5767d8b4b74060742e2a50b50aaa7b782c7858fec8badbfc4d6c2e05402052b3f285c0ca13029a4f6920b28a82b1ac194571e93f7d4c924f0bd67bdaab52bbb4
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flash_flow (1.4.5)
4
+ flash_flow (1.4.6)
5
5
  hipchat (~> 1.5)
6
+ mail
6
7
  octokit (~> 4.1)
7
8
  percy-client
8
9
  pivotal-tracker (~> 0.5)
@@ -33,9 +34,9 @@ GEM
33
34
  httparty (0.14.0)
34
35
  multi_xml (>= 0.5.2)
35
36
  httpclient (2.8.0)
36
- mime-types (3.1)
37
- mime-types-data (~> 3.2015)
38
- mime-types-data (3.2016.0521)
37
+ mail (2.6.3)
38
+ mime-types (>= 1.16, < 3)
39
+ mime-types (2.99.2)
39
40
  mimemagic (0.3.1)
40
41
  mini_portile2 (2.1.0)
41
42
  minitest (5.3.5)
data/bin/flash_flow CHANGED
@@ -20,6 +20,8 @@ case
20
20
  FlashFlow::IssueTracker::Base.new(FlashFlow::Config.configuration.issue_tracker).stories_delivered
21
21
  when options[:release_notes]
22
22
  FlashFlow::IssueTracker::Base.new(FlashFlow::Config.configuration.issue_tracker).release_notes(options[:release_notes])
23
+ when options[:release_email]
24
+ FlashFlow::Release::Base.new(FlashFlow::Config.configuration.release).send_release_email
23
25
  when options[:resolve]
24
26
  FlashFlow::Resolve.new(FlashFlow::Config.configuration.git, FlashFlow::Config.configuration.branch_info_file, logger: FlashFlow::Config.configuration.logger).start
25
27
  when options[:resolve_manual]
data/flash_flow.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency 'pivotal-tracker', "~> 0.5"
23
23
  spec.add_dependency 'ruby-graphviz', "> 0"
24
24
  spec.add_dependency 'percy-client'
25
+ spec.add_dependency 'mail'
25
26
 
26
27
  spec.add_development_dependency "bundler", "~> 1.6"
27
28
  spec.add_development_dependency "rake", "> 0"
@@ -85,7 +85,24 @@ branch_info_file: 'your/random/file'
85
85
 
86
86
  #release:
87
87
  # class:
88
- # name: 'FlashFlow::Release::Percy'
88
+ # name: 'FlashFlow::Release::PercyClient'
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
+ # email: 'foo@bar.com'
93
+ # cc_email: 'bar@foo.com'
94
+ #smtp:
95
+ # settings:
96
+ # domain: 'yourdomain.com'
97
+ # address: <%= ENV['SMTP_ADDRESS'] %>
98
+ # user_name: <%= ENV['SMTP_USERNAME'] %>
99
+ # password: <%= ENV['SMTP_PASSWORD'] %>
100
+ # port: 587
101
+ # authentication: 'plain'
102
+ # enable_starttls_auto: true
103
+ # emails:
104
+ # from: 'sender@domain.com'
105
+ # to: 'receiver@domain.com'
106
+ # cc: 'cc@domain.com'
107
+ # subject: 'The engineering team has a new release candidate'
108
+ # body_file: 'path/to/email_template.erb'
data/lib/flash_flow.rb CHANGED
@@ -7,3 +7,4 @@ require 'flash_flow/issue_tracker'
7
7
  require 'flash_flow/resolve'
8
8
  require 'flash_flow/merge'
9
9
  require 'flash_flow/release'
10
+ require 'flash_flow/mailer'
@@ -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, :release
19
+ :git, :branch_info_file, :log_file, :notifier, :issue_tracker, :lock, :branches, :release, :smtp
20
20
  ]
21
21
 
22
22
  attr_reader *ATTRIBUTES
@@ -55,7 +55,8 @@ module FlashFlow
55
55
  issue_tracker: nil,
56
56
  lock: nil,
57
57
  branches: nil,
58
- release: nil
58
+ release: nil,
59
+ smtp: nil
59
60
  }
60
61
  end
61
62
 
@@ -4,6 +4,7 @@ require 'shellwords'
4
4
  module FlashFlow
5
5
  class Git
6
6
  ATTRIBUTES = [:remote, :merge_branch, :master_branch, :release_branch, :use_rerere]
7
+
7
8
  attr_reader *ATTRIBUTES
8
9
  attr_reader :working_branch
9
10
 
@@ -0,0 +1,45 @@
1
+ require 'mail'
2
+
3
+ module FlashFlow
4
+ module Mailer
5
+ class Base
6
+
7
+ def initialize(config)
8
+ unless config&.fetch('settings', false)
9
+ raise RuntimeError.new("smtp settings must be set in your flash flow config.")
10
+ end
11
+
12
+ configure!(config['settings'])
13
+ end
14
+
15
+ def deliver!(data={})
16
+ delivery_info = Config.configuration.smtp["emails"]
17
+
18
+ if delivery_info
19
+ delivery_info["body_html"] = body_html(data, delivery_info["body_file"])
20
+
21
+ Mail.deliver do
22
+ from delivery_info["from"]
23
+ to delivery_info["to"]
24
+ cc delivery_info["cc"]
25
+ subject delivery_info["subject"]
26
+ body delivery_info["body_html"]
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def configure!(config)
34
+ Mail.defaults { delivery_method :smtp, config.symbolize_keys }
35
+ end
36
+
37
+ def body_html(data, template)
38
+ @data = data
39
+ erb_template = ERB.new File.read(template)
40
+ erb_template.result(binding)
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -13,6 +13,7 @@ module FlashFlow
13
13
  opts.on('--prod-deploy', 'Run IssueTracker#deploy_production and exit') { |v| options[:prod_deploy] = true }
14
14
  opts.on('--review-deploy', 'Run IssueTracker#deploy_review and exit') { |v| options[:review_deploy] = true }
15
15
  opts.on('--release-notes hours', 'Run IssueTracker#release_notes and exit') { |v| options[:release_notes] = v }
16
+ opts.on('--release-email', 'Send an email with a latest build info and exit') { |v| options[:release_email] = v }
16
17
  opts.on('-n', '--no-merge', 'Run flash flow, but do not merge this branch') { |v| options[:do_not_merge] = true }
17
18
  opts.on('--rerere-forget', 'Delete the saved patch for this branch and let the merge fail if there is a conflict') { |v| options[:rerere_forget] = true }
18
19
  opts.on('--story id1', 'story id for this branch') { |v| options[:stories] = [v] }
@@ -24,7 +25,6 @@ module FlashFlow
24
25
  opts.on('--merge-status', 'Show status of all branches and their stories and exit') { |v| options[:merge_status] = true }
25
26
  opts.on('--merge-status-html', 'Show status of all branches and their stories in html format and exit') { |v| options[:merge_status_html] = true }
26
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(',') }
27
- opts.on('--merge-release', 'Merge the release branch into the master branch and push') { |v| options[:merge_release] = v.split(',') }
28
28
 
29
29
  opts.on_tail("-h", "--help", "Show this message") do
30
30
  puts opts
@@ -15,6 +15,10 @@ module FlashFlow
15
15
  @release.find_latest_by_sha(sha) if @release.respond_to?(:find_latest_by_sha)
16
16
  end
17
17
 
18
+ def send_release_email
19
+ @release.send_release_email if @release.respond_to?(:send_release_email)
20
+ end
21
+
18
22
  end
19
23
  end
20
24
  end
@@ -1,4 +1,6 @@
1
1
  require 'percy'
2
+ require 'flash_flow/git'
3
+ require 'flash_flow/mailer'
2
4
 
3
5
  module FlashFlow
4
6
  module Release
@@ -6,14 +8,21 @@ module FlashFlow
6
8
 
7
9
  def initialize(config={})
8
10
  @client = initialize_connection!(config['token'])
11
+ @git = ShadowGit.new(Config.configuration.git, Config.configuration.logger)
9
12
  end
10
13
 
11
14
  def find_latest_by_sha(sha)
12
15
  response = get_builds
13
16
  commit = find_commit_by_sha(response, sha)
14
- build = find_build_by_commit_id(response, commit['id'])
17
+ find_build_by_commit_id(response, commit['id'])
18
+ end
19
+
20
+ def send_release_email
21
+ build = find_latest_by_sha(get_latest_sha)
15
22
 
16
- { url: build['web-url'], approved: !build['approved-at'].nil? }
23
+ if has_unapproved_diffs?(build)
24
+ mailer.deliver!(percy_build_url: build['web-url'])
25
+ end
17
26
  end
18
27
 
19
28
  private
@@ -24,10 +33,6 @@ module FlashFlow
24
33
  end
25
34
 
26
35
  Percy.client.config.access_token = token
27
- percy_client
28
- end
29
-
30
- def percy_client
31
36
  Percy.client
32
37
  end
33
38
 
@@ -40,26 +45,35 @@ module FlashFlow
40
45
  end
41
46
 
42
47
  def find_build_by_commit_id(response, commit_id)
43
- builds = builds_collection(response)
44
- return if builds.nil?
45
-
46
- latest_build = builds
48
+ builds_collection(response)
47
49
  .select { |b| b.dig('relationships', 'commit', 'data', 'id') == commit_id }
48
50
  .sort_by { |b| DateTime.parse(b.dig('attributes', 'created-at')) }.last
49
-
50
- latest_build['attributes']
51
+ &.fetch('attributes', {}) || {}
51
52
  end
52
53
 
53
54
  def builds_collection(response)
54
- response['data'].select do |h|
55
- h['type'] == 'builds' &&
55
+ response.fetch('data', [])
56
+ .select do |h| h['type'] == 'builds' &&
56
57
  h.dig('attributes', 'web-url') &&
57
58
  h.dig('relationships', 'commit', 'data', 'type') == 'commits'
58
- end
59
+ end
59
60
  end
60
61
 
61
62
  def commits_data(response)
62
- response['included'].select { |data| data['type'] == 'commits' }
63
+ response.fetch('included', {'id' => nil})
64
+ .select { |data| data['type'] == 'commits' }
65
+ end
66
+
67
+ def has_unapproved_diffs?(build)
68
+ build['total-comparisons-diff'] > 0 && build['approved-at'].nil?
69
+ end
70
+
71
+ def get_latest_sha
72
+ @git.get_sha(@git.release_branch)
73
+ end
74
+
75
+ def mailer
76
+ @mailer ||= FlashFlow::Mailer::Base.new(Config.configuration.smtp)
63
77
  end
64
78
 
65
79
  end
@@ -1,3 +1,3 @@
1
1
  module FlashFlow
2
- VERSION = "1.4.5"
2
+ VERSION = "1.4.6"
3
3
  end
@@ -6,15 +6,41 @@ module FlashFlow
6
6
  class TestPercyClient < Minitest::Test
7
7
 
8
8
  def setup
9
+ configuration = {}
10
+ .merge(git_config)
11
+ .merge(smtp_config)
12
+ reset_config!
13
+ config!(configuration)
14
+
9
15
  @percy_client = Release::PercyClient.new({'token' => ''})
10
16
  end
11
17
 
12
18
  def test_find_latest_by_sha
13
19
  @percy_client.stub(:get_builds, sample_response) do
14
- results = @percy_client.send(:find_latest_by_sha, 'aaaaa')
15
- assert_equal(results[:url], 'https://percy.io/repo/builds/2222')
16
- assert_equal(results[:approved], true)
20
+ results = @percy_client.find_latest_by_sha('aaaaa')
21
+ assert(results.has_key?('web-url'))
22
+ assert(results.has_key?('approved-at'))
23
+ assert(results.has_key?('total-comparisons-diff'))
24
+ end
25
+ end
26
+
27
+ def test_send_release_email
28
+ @git = Minitest::Mock.new
29
+ .expect(:release_branch, 'release')
30
+ .expect(:get_sha, 'bbbbb', ['release'])
31
+
32
+ @mailer = Minitest::Mock.new
33
+ @mailer.expect(:deliver!, true, [{percy_build_url: 'https://percy.io/repo/builds/1111'}])
34
+
35
+ @percy_client.instance_variable_set('@git'.to_sym, @git)
36
+ @percy_client.instance_variable_set('@mailer'.to_sym, @mailer)
37
+
38
+ @percy_client.stub(:get_builds, sample_response) do
39
+ @percy_client.send_release_email
17
40
  end
41
+
42
+ @git.verify
43
+ @mailer.verify
18
44
  end
19
45
 
20
46
  def test_find_commit_by_sha
@@ -30,6 +56,16 @@ module FlashFlow
30
56
  assert(!build['approved-at'].nil?)
31
57
  end
32
58
 
59
+ def test_has_unapproved_diffs?
60
+ @percy_client.stub(:get_builds, sample_response) do
61
+ build1 = @percy_client.find_latest_by_sha('bbbbb')
62
+ assert(@percy_client.send(:has_unapproved_diffs?, build1))
63
+
64
+ build2 = @percy_client.find_latest_by_sha('aaaaa')
65
+ refute(@percy_client.send(:has_unapproved_diffs?, build2))
66
+ end
67
+ end
68
+
33
69
  private
34
70
 
35
71
  def sample_response
@@ -39,6 +75,7 @@ module FlashFlow
39
75
  "type": "builds",
40
76
  "attributes": {
41
77
  "web-url": "https://percy.io/repo/builds/1111",
78
+ "total-comparisons-diff": 1,
42
79
  "approved-at": null,
43
80
  "created-at": "2016-08-01T00:00:00.000Z"
44
81
  },
@@ -46,7 +83,7 @@ module FlashFlow
46
83
  "commit": {
47
84
  "data": {
48
85
  "type": "commits",
49
- "id": "9999"
86
+ "id": "8888"
50
87
  }
51
88
  }
52
89
  }
@@ -55,6 +92,7 @@ module FlashFlow
55
92
  "type": "builds",
56
93
  "attributes": {
57
94
  "web-url": "https://percy.io/repo/builds/2222",
95
+ "total-comparisons-diff": 0,
58
96
  "approved-at": "2016-08-01T22:41:58.000Z",
59
97
  "created-at": "2016-08-01T11:11:11.111Z"
60
98
  },
@@ -87,6 +125,24 @@ module FlashFlow
87
125
  }')
88
126
  end
89
127
 
128
+ def git_config
129
+ {
130
+ git: {
131
+ 'merge_branch' => 'test_acceptance',
132
+ 'merge_remote' => 'test_remote',
133
+ 'master_branch' => 'test_master',
134
+ 'remotes' => ['fake_origin'],
135
+ 'use_rerere' => true
136
+ }
137
+ }
138
+ end
139
+
140
+ def smtp_config
141
+ {
142
+ smtp: {}
143
+ }
144
+ end
145
+
90
146
  end
91
147
  end
92
148
  end
@@ -30,7 +30,8 @@ module FlashFlow
30
30
  'class' => {
31
31
  'name' => 'BranchClass'
32
32
  }
33
- }
33
+ },
34
+ 'smtp' => {}
34
35
  }
35
36
 
36
37
  reset_config!
@@ -72,9 +73,9 @@ module FlashFlow
72
73
  assert_nil(config.lock)
73
74
  end
74
75
  end
75
-
76
+
76
77
  private
77
-
78
+
78
79
  def config
79
80
  Config.configuration
80
81
  end
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.5
4
+ version: 1.4.6
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-13 00:00:00.000000000 Z
11
+ date: 2016-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: octokit
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mail
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -185,6 +199,7 @@ files:
185
199
  - lib/flash_flow/issue_tracker/pivotal.rb
186
200
  - lib/flash_flow/lock.rb
187
201
  - lib/flash_flow/lock/github.rb
202
+ - lib/flash_flow/mailer.rb
188
203
  - lib/flash_flow/merge.rb
189
204
  - lib/flash_flow/merge/acceptance.rb
190
205
  - lib/flash_flow/merge/base.rb