dpl 1.8.33.travis.2049.5 → 1.8.34.travis.2089.5

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: 6bc174c17fad30b36ac9b2e2367a6b535a46ebd8
4
- data.tar.gz: 058ee4f23d5412dc20611a0c91c6e813362c6ed0
3
+ metadata.gz: 344f328801c80df62034fbfcc73345c4f1777df5
4
+ data.tar.gz: 126e4bd8d202e46a3b2096fcd1a45b137742fb16
5
5
  SHA512:
6
- metadata.gz: 44cb5e03513e86c8ee0610c705a64f73cb59d0fb17db8ca1d863a06b1462d4650e77a3134042f636c7133c1d185783b3ddcab4e368379058142fd89250486e94
7
- data.tar.gz: 4c02d030e307fb7adb256276eff47fa700bc1baf23865c157306548f66b5f2112a4039a31ae31edb17efb8c3de9bb0de1f2733fe672202635710a008b40bcc8d
6
+ metadata.gz: a57556f2852be0c4df1a23656529984bc66225f84b4519690114b9387824828b11fafb3e2ba06c70823125621878822386e775e9dbc04aea523899e71328041d
7
+ data.tar.gz: c2890e7cc455e59bfeb074fc9779754a12d1c8e8c9887ad07e724175434f8c6ce6afe41886c03189be5cd878a001ffeb80af40b7d43393e213fad8bb632f675d
data/Gemfile CHANGED
@@ -15,6 +15,7 @@ group :heroku do
15
15
  gem 'heroku-api', '= 0.3.16'
16
16
  gem 'anvil-cli', '~> 0.16.1'
17
17
  gem 'netrc'
18
+ gem 'faraday'
18
19
  end
19
20
 
20
21
  group :openshift do
@@ -1,11 +1,67 @@
1
1
  require 'json'
2
2
  require 'shellwords'
3
+ require 'logger'
3
4
 
4
5
  module DPL
5
6
  class Provider
6
7
  module Heroku
7
8
  class API < Generic
8
9
  attr_reader :build_id
10
+ requires 'faraday'
11
+ requires 'rendezvous'
12
+
13
+ def check_auth
14
+ response = faraday.get('/account')
15
+
16
+ if response.success?
17
+ email = JSON.parse(response.body)["email"]
18
+ log "authenticated as #{email}"
19
+ else
20
+ handle_error_response(response)
21
+ end
22
+ end
23
+
24
+ def faraday
25
+ return @conn if @conn
26
+ headers = { "Accept" => "application/vnd.heroku+json; version=3" }
27
+
28
+ if options[:user] and options[:password]
29
+ # no-op
30
+ else
31
+ headers.merge!({ "Authorization" => "Bearer #{option(:api_key)}" })
32
+ end
33
+
34
+ @conn = Faraday.new( url: 'https://api.heroku.com', headers: headers ) do |faraday|
35
+ if options[:user] and options[:password]
36
+ faraday.basic_auth(options[:user], options[:password])
37
+ end
38
+ if log_level = options[:log_level]
39
+ logger = Logger.new($stderr)
40
+ logger.level = Logger.const_get(log_level.upcase)
41
+
42
+ faraday.response :logger, logger do | logger |
43
+ logger.filter(/(.*Authorization: ).*/,'\1[REDACTED]')
44
+ end
45
+ end
46
+ faraday.adapter Faraday.default_adapter
47
+ end
48
+ end
49
+
50
+ def check_app
51
+ log "checking for app #{option(:app)}"
52
+ response = faraday.get("/apps/#{option(:app)}")
53
+ if response.success?
54
+ name = JSON.parse(response.body)["name"]
55
+ log "found app #{name}"
56
+ else
57
+ handle_error_response(response)
58
+ end
59
+ end
60
+
61
+ def handle_error_response(response)
62
+ error_response = JSON.parse(response.body)
63
+ error "API request failed.\nMessage: #{error_response["message"]}\nReference: #{error_response["url"]}"
64
+ end
9
65
 
10
66
  def push_app
11
67
  pack_archive
@@ -30,16 +86,29 @@ module DPL
30
86
 
31
87
  def trigger_build
32
88
  log "triggering new deployment"
33
- response = post(:builds, source_blob: { url: get_url, version: version })
34
- @build_id = response.fetch('id')
35
- output_stream_url = response.fetch('output_stream_url')
36
- context.shell "curl #{Shellwords.escape(output_stream_url)}"
89
+ response = faraday.post("/apps/#{option(:app)}/builds") do |req|
90
+ req.headers['Content-Type'] = 'application/json'
91
+ req.body = {
92
+ "source_blob" => {
93
+ "url" => get_url,
94
+ "version" => version
95
+ }
96
+ }.to_json
97
+ end
98
+
99
+ if response.success?
100
+ @build_id = JSON.parse(response.body)['id']
101
+ output_stream_url = JSON.parse(response.body)['output_stream_url']
102
+ context.shell "curl #{Shellwords.escape(output_stream_url)}"
103
+ else
104
+ handle_error_response(response)
105
+ end
37
106
  end
38
107
 
39
108
  def verify_build
40
109
  loop do
41
- response = get("builds/#{build_id}/result")
42
- exit_code = response.fetch('exit_code')
110
+ response = faraday.get("/apps/#{option(:app)}/builds/#{build_id}/result")
111
+ exit_code = JSON.parse(response.body)['exit_code']
43
112
  if exit_code.nil?
44
113
  log "heroku build still pending"
45
114
  sleep 5
@@ -61,38 +130,41 @@ module DPL
61
130
  end
62
131
 
63
132
  def source_blob
64
- @source_blob ||= post(:sources).fetch("source_blob")
133
+ return @source_blob if @source_blob
134
+
135
+ response = faraday.post('/sources')
136
+
137
+ if response.success?
138
+ @source_blob = JSON.parse(response.body)["source_blob"]
139
+ else
140
+ handle_error_response(response)
141
+ end
65
142
  end
66
143
 
67
144
  def version
68
145
  @version ||= options[:version] || context.env['TRAVIS_COMMIT'] || `git rev-parse HEAD`.strip
69
146
  end
70
147
 
71
- def get(subpath, options = {})
72
- options = {
73
- method: :get,
74
- path: "/apps/#{option(:app)}/#{subpath}",
75
- headers: { "Accept" => "application/vnd.heroku+json; version=3" },
76
- expects: [200]
77
- }.merge(options)
78
-
79
- api.request(options).body
148
+ def restart
149
+ response = faraday.delete "/apps/#{option(:app)}/dynos" do |req|
150
+ req.headers['Content-Type'] = 'application/json'
151
+ end
152
+ unless response.success?
153
+ handle_error_response(response)
154
+ end
80
155
  end
81
156
 
82
- def post(subpath, body = nil, options = {})
83
- options = {
84
- method: :post,
85
- path: "/apps/#{option(:app)}/#{subpath}",
86
- headers: { "Accept" => "application/vnd.heroku+json; version=3" },
87
- expects: [200, 201]
88
- }.merge(options)
89
-
90
- if body
91
- options[:body] = JSON.dump(body)
92
- options[:headers]['Content-Type'] = 'application/json'
157
+ def run(command)
158
+ response = faraday.post "/apps/#{option(:app)}/dynos" do |req|
159
+ req.headers['Content-Type'] = 'application/json'
160
+ req.body = {"command" => command, "attach" => true}.to_json
161
+ end
162
+ if response.success?
163
+ rendezvous_url = JSON.parse(response.body)["attach_url"]
164
+ Rendezvous.start(url: rendezvous_url)
165
+ else
166
+ handle_error_response(response)
93
167
  end
94
-
95
- api.request(options).body
96
168
  end
97
169
  end
98
170
  end
data/lib/dpl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module DPL
2
- VERSION = '1.8.32'
2
+ VERSION = '1.8.33'
3
3
  end
@@ -1,16 +1,160 @@
1
1
  require 'spec_helper'
2
- require 'heroku-api'
3
2
  require 'dpl/provider/heroku'
3
+ require 'faraday'
4
4
 
5
5
  describe DPL::Provider::Heroku do
6
+ let(:api_key) { 'foo' }
7
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
8
+ let(:faraday) {
9
+ Faraday.new do |builder|
10
+ builder.adapter :test, stubs do |stub|
11
+ stub.get("/account") {|env| [200, response_headers, account_response_body]}
12
+ stub.post("/apps/example/builds") {|env| [201, response_headers, builds_response_body]}
13
+ stub.get("/apps/example/builds/01234567-89ab-cdef-0123-456789abcdef/result") {|env| [200, response_headers, build_result_response_body]}
14
+ stub.post("/sources") {|env| [201, response_headers, source_response_body] }
15
+ end
16
+ end
17
+ }
18
+
19
+ let(:response_headers) {
20
+ {'Content-Type' => 'application/json'}
21
+ }
22
+
23
+ let(:account_response_body) {
24
+ '{
25
+ "allow_tracking": true,
26
+ "beta": false,
27
+ "created_at": "2012-01-01T12:00:00Z",
28
+ "email": "username@example.com",
29
+ "federated": false,
30
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
31
+ "identity_provider": {
32
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
33
+ "organization": {
34
+ "name": "example"
35
+ }
36
+ },
37
+ "last_login": "2012-01-01T12:00:00Z",
38
+ "name": "Tina Edmonds",
39
+ "sms_number": "+1 ***-***-1234",
40
+ "suspended_at": "2012-01-01T12:00:00Z",
41
+ "delinquent_at": "2012-01-01T12:00:00Z",
42
+ "two_factor_authentication": false,
43
+ "updated_at": "2012-01-01T12:00:00Z",
44
+ "verified": false,
45
+ "default_organization": {
46
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
47
+ "name": "example"
48
+ }
49
+ }'
50
+ }
51
+
52
+ let(:builds_response_body) {
53
+ '{
54
+ "app": {
55
+ "id": "01234567-89ab-cdef-0123-456789abcdef"
56
+ },
57
+ "buildpacks": [
58
+ {
59
+ "url": "https://github.com/heroku/heroku-buildpack-ruby"
60
+ }
61
+ ],
62
+ "created_at": "2012-01-01T12:00:00Z",
63
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
64
+ "output_stream_url": "https://build-output.heroku.com/streams/01234567-89ab-cdef-0123-456789abcdef",
65
+ "source_blob": {
66
+ "checksum": "SHA256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
67
+ "url": "https://example.com/source.tgz?token=xyz",
68
+ "version": "v1.3.0"
69
+ },
70
+ "release": {
71
+ "id": "01234567-89ab-cdef-0123-456789abcdef"
72
+ },
73
+ "slug": {
74
+ "id": "01234567-89ab-cdef-0123-456789abcdef"
75
+ },
76
+ "status": "succeeded",
77
+ "updated_at": "2012-01-01T12:00:00Z",
78
+ "user": {
79
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
80
+ "email": "username@example.com"
81
+ }
82
+ }'
83
+ }
84
+
85
+ let(:source_response_body) {
86
+ '{
87
+ "source_blob": {
88
+ "get_url": "https://api.heroku.com/sources/1234.tgz",
89
+ "put_url": "https://api.heroku.com/sources/1234.tgz"
90
+ }
91
+ }'
92
+ }
93
+
94
+ let(:build_result_response_body) {
95
+ '{
96
+ "build": {
97
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
98
+ "status": "succeeded",
99
+ "output_stream_url": "https://build-output.heroku.com/streams/01234567-89ab-cdef-0123-456789abcdef"
100
+ },
101
+ "exit_code": 0,
102
+ "lines": [
103
+ {
104
+ "line": "-----> Ruby app detected\n",
105
+ "stream": "STDOUT"
106
+ }
107
+ ]
108
+ }'
109
+ }
110
+
111
+ let(:build_result_response_body_failure) {
112
+ '{
113
+ "build": {
114
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
115
+ "status": "failed",
116
+ "output_stream_url": "https://build-output.heroku.com/streams/01234567-89ab-cdef-0123-456789abcdef"
117
+ },
118
+ "exit_code": 1,
119
+ "lines": [
120
+ {
121
+ "line": "-----> Ruby app detected\n",
122
+ "stream": "STDOUT"
123
+ }
124
+ ]
125
+ }'
126
+ }
127
+
128
+ let(:build_result_response_body_in_progress) {
129
+ '{
130
+ "build": {
131
+ "id": "01234567-89ab-cdef-0123-456789abcdef",
132
+ "status": "failed",
133
+ "output_stream_url": "https://build-output.heroku.com/streams/01234567-89ab-cdef-0123-456789abcdef"
134
+ },
135
+ "lines": [
136
+ {
137
+ "line": "-----> Ruby app detected\n",
138
+ "stream": "STDOUT"
139
+ }
140
+ ]
141
+ }'
142
+ }
143
+
6
144
  subject(:provider) do
7
- described_class.new(DummyContext.new, :app => 'example', :key_name => 'key', :api_key => "foo", :strategy => "api")
145
+ described_class.new(DummyContext.new, provider_options.merge({ :api_key => api_key}))
8
146
  end
9
147
 
148
+ let(:provider_options) {
149
+ {:app => 'example', :key_name => 'key', :strategy => "api"}
150
+ }
151
+
10
152
  let(:expected_headers) do
11
- { "User-Agent" => "dpl/#{DPL::VERSION} heroku-rb/#{Heroku::API::VERSION}", "Accept" => "application/vnd.heroku+json; version=3" }
153
+ { "Authorization" => "Bearer #{api_key}", "Accept" => "application/vnd.heroku+json; version=3" }
12
154
  end
13
155
 
156
+ let(:api_url) { 'https://api.heroku.com' }
157
+
14
158
  describe "#ssh" do
15
159
  it "doesn't require an ssh key" do
16
160
  expect(provider.needs_key?).to eq(false)
@@ -19,74 +163,61 @@ describe DPL::Provider::Heroku do
19
163
 
20
164
  describe "#api" do
21
165
  it 'accepts an api key' do
22
- api = double(:api)
23
- expect(::Heroku::API).to receive(:new).with(:api_key => "foo", :headers => expected_headers).and_return(api)
24
- expect(provider.api).to eq(api)
166
+ expect(provider).to receive(:faraday).at_least(:once).and_return(faraday)
167
+ provider.check_auth
25
168
  end
26
169
 
27
- it 'accepts a user and a password' do
28
- api = double(:api)
29
- provider.options.update(:user => "foo", :password => "bar")
30
- expect(::Heroku::API).to receive(:new).with(:user => "foo", :password => "bar", :headers => expected_headers).and_return(api)
31
- expect(provider.api).to eq(api)
170
+ context "when api_key is not given" do
171
+ let(:provider) { described_class.new(DummyContext.new, provider_options) }
172
+ it 'raises DPL::Error' do
173
+ provider.options.update(:user => "foo", :password => "bar")
174
+ expect(::Heroku::API).not_to receive(:new)
175
+ expect { provider.check_auth }.to raise_error(DPL::Error)
176
+ end
32
177
  end
33
178
  end
34
179
 
35
180
  describe "#trigger_build" do
36
- let(:response_body) { {
37
- "created_at" => "2012-01-01T12:00:00Z",
38
- "id" => "abc",
39
- "status" => "pending",
40
- "output_stream_url" => "http://example.com/stream",
41
- "updated_at" => "2012-01-01T12:00:00Z",
42
- "user" => { "id" => "01234567-89ab-cdef-0123-456789abcdef", "email" => "username@example.com" }
43
- } }
181
+ it "does not initiate legacy API object" do
182
+ expect(provider).to receive(:faraday).at_least(:once).and_return(faraday)
183
+ expect(::Heroku::API).not_to receive(:new)
184
+ provider.trigger_build
185
+ end
186
+
44
187
  example do
45
188
  expect(provider).to receive(:log).with('triggering new deployment')
189
+ expect(provider).to receive(:faraday).at_least(:once).and_return(faraday)
46
190
  expect(provider).to receive(:get_url).and_return 'http://example.com/source.tgz'
47
- expect(provider).to receive(:version).and_return 'sha'
48
- expect(provider).to receive(:post).with(
49
- :builds, source_blob: {url: 'http://example.com/source.tgz', version: 'sha'}
50
- ).and_return(response_body)
51
- expect(provider.context).to receive(:shell).with('curl http://example.com/stream')
191
+ expect(provider).to receive(:version).and_return 'v1.3.0'
192
+ expect(provider.context).to receive(:shell).with('curl https://build-output.heroku.com/streams/01234567-89ab-cdef-0123-456789abcdef')
52
193
  provider.trigger_build
53
- expect(provider.build_id).to eq('abc')
194
+ expect(provider.build_id).to eq('01234567-89ab-cdef-0123-456789abcdef')
54
195
  end
55
196
  end
56
197
 
57
198
  describe "#verify_build" do
58
- def response_body(status, exit_code)
59
- {
60
- "build" => {
61
- "id" => "01234567-89ab-cdef-0123-456789abcdef",
62
- "status" => status
63
- },
64
- "exit_code" => exit_code
65
- }
66
- end
67
-
68
- before do
69
- allow(provider).to receive(:build_id).and_return('abc')
70
- end
71
-
72
199
  context 'when build succeeds' do
73
200
  example do
74
- expect(provider).to receive(:get).with('builds/abc/result').and_return(response_body('succeeded', 0))
201
+ expect(provider).to receive(:faraday).at_least(:once).and_return(faraday)
202
+ expect(provider).to receive(:build_id).at_least(:once).and_return('01234567-89ab-cdef-0123-456789abcdef')
75
203
  expect{ provider.verify_build }.not_to raise_error
76
204
  end
77
205
  end
78
206
 
79
207
  context 'when build fails' do
80
208
  example do
81
- expect(provider).to receive(:get).with('builds/abc/result').and_return(response_body('failed', 1))
209
+ expect(provider).to receive(:faraday).at_least(:once).and_return(faraday)
210
+ expect(provider).to receive(:build_id).at_least(:once).and_return('01234567-89ab-cdef-0123-456789abcdef')
211
+ stubs.get("/apps/example/builds/01234567-89ab-cdef-0123-456789abcdef/result") {|env| [200, response_headers, build_result_response_body_failure]}
82
212
  expect{ provider.verify_build }.to raise_error("deploy failed, build exited with code 1")
83
213
  end
84
214
  end
85
215
 
86
216
  context 'when build is pending, then succeeds' do
87
217
  example do
88
- expect(provider).to receive(:get).with('builds/abc/result').and_return(response_body('pending', nil), response_body('succeeded', 0))
89
- expect(provider).to receive(:log).with('heroku build still pending')
218
+ expect(provider).to receive(:faraday).at_least(:once).and_return(faraday)
219
+ expect(provider).to receive(:build_id).at_least(:once).and_return('01234567-89ab-cdef-0123-456789abcdef')
220
+ stubs.get("/apps/example/builds/01234567-89ab-cdef-0123-456789abcdef/result") {|env| [200, response_headers, build_result_response_body_in_progress]}
90
221
  expect(provider).to receive(:sleep).with(5) # stub sleep
91
222
  expect{ provider.verify_build }.not_to raise_error
92
223
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dpl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.33.travis.2049.5
4
+ version: 1.8.34.travis.2089.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Haase
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-30 00:00:00.000000000 Z
11
+ date: 2017-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec