dpl-code_deploy 1.9.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b6b1afca5c5e56e7d2f21490ed1ef98653cf698
4
+ data.tar.gz: b3b341b6703e21763e62b9e1121ee272cb0a4db0
5
+ SHA512:
6
+ metadata.gz: e72df0817c9af23e512d8d9360e312ab89d42a7f27bdb8aca07b9720ba7f487b17fd11b55aecb32f256f6740c52c01714be82c943d7185326ec6a9e5f949f9f8
7
+ data.tar.gz: 6f4e23a292948ff1ef835734756b2bd151fb98ca436f2ae615e49d688b513b6fd803bdfa36f73e51b27446453ae80e3e7b8a9e5167fd58139316efec84ce3ac1
@@ -0,0 +1,3 @@
1
+ require './gemspec_helper'
2
+
3
+ gemspec_for 'code_deploy', [['aws-sdk', '~> 2.0']]
@@ -0,0 +1,153 @@
1
+ require 'json'
2
+ require 'aws-sdk'
3
+
4
+ module DPL
5
+ class Provider
6
+ class CodeDeploy < Provider
7
+ def code_deploy
8
+ @code_deploy ||= Aws::CodeDeploy::Client.new(code_deploy_options)
9
+ end
10
+
11
+ def s3api
12
+ @s3api ||= Aws::S3::Client.new(code_deploy_options)
13
+ end
14
+
15
+ def code_deploy_options
16
+ code_deploy_options = {
17
+ region: options[:region] || 'us-east-1',
18
+ credentials: Aws::Credentials.new(access_key_id, secret_access_key)
19
+ }
20
+ code_deploy_options[:endpoint] = options[:endpoint] if options[:endpoint]
21
+ code_deploy_options
22
+ end
23
+
24
+ def access_key_id
25
+ options[:access_key_id] || context.env['AWS_ACCESS_KEY_ID'] || raise(Error, "missing access_key_id")
26
+ end
27
+
28
+ def secret_access_key
29
+ options[:secret_access_key] || context.env['AWS_SECRET_ACCESS_KEY'] || raise(Error, "missing secret_access_key")
30
+ end
31
+
32
+ def needs_key?
33
+ false
34
+ end
35
+
36
+ def revision
37
+ case options[:revision_type].to_s.downcase
38
+ when "s3" then s3_revision
39
+ when "github" then github_revision
40
+ when "" then options[:bucket] ? s3_revision : github_revision
41
+ else error("unknown revision type %p" % options[:revision_type])
42
+ end
43
+ end
44
+
45
+ def revision_version_info
46
+ s3api.head_object({
47
+ bucket: option(:bucket),
48
+ key: s3_key
49
+ })
50
+ rescue Aws::Errors::ServiceError
51
+ {}
52
+ end
53
+
54
+ def s3_revision
55
+ info = {
56
+ revision_type: 'S3',
57
+ s3_location: {
58
+ bucket: option(:bucket),
59
+ bundle_type: bundle_type,
60
+ key: s3_key,
61
+ }
62
+ }
63
+ unless revision_version_info.empty?
64
+ info[:s3_location][:version] = revision_version_info[:version_id]
65
+ info[:s3_location][:e_tag] = revision_version_info[:etag]
66
+ end
67
+
68
+ info
69
+ end
70
+
71
+ def github_revision
72
+ {
73
+ revision_type: 'GitHub',
74
+ git_hub_location: {
75
+ commit_id: options[:commit_id] || context.env['TRAVIS_COMMIT'] || `git rev-parse HEAD`.strip,
76
+ repository: options[:repository] || context.env['TRAVIS_REPO_SLUG'] || option(:repository)
77
+ }
78
+ }
79
+ end
80
+
81
+ def push_app
82
+ rev = revision()
83
+ rev_info = rev[:s3_location]
84
+
85
+ if rev_info && rev_info[:version]
86
+ log "Registering app revision with version=#{rev_info[:version]}, etag=#{rev_info[:e_tag]}"
87
+ code_deploy.register_application_revision({
88
+ revision: rev,
89
+ application_name: options[:application] || option(:application_name),
90
+ description: options[:description] || default_description
91
+ })
92
+ end
93
+
94
+ data = code_deploy.create_deployment({
95
+ revision: revision,
96
+ application_name: options[:application] || option(:application_name),
97
+ deployment_group_name: options[:deployment_group] || option(:deployment_group_name),
98
+ description: options[:description] || default_description
99
+ })
100
+ log "Triggered deployment #{data.deployment_id.inspect}."
101
+ return unless options[:wait_until_deployed]
102
+ print "Deploying "
103
+ deployment = wait_until_deployed(data[:deployment_id])
104
+ print "\n"
105
+ if deployment[:status] == 'Succeeded'
106
+ log "Deployment successful."
107
+ else
108
+ error "Deployment failed."
109
+ end
110
+ rescue Aws::CodeDeploy::Errors::DeploymentLimitExceededException => exception
111
+ error(exception.message)
112
+ end
113
+
114
+ def wait_until_deployed(deployment_id)
115
+ deployment = {}
116
+ loop do
117
+ result = code_deploy.get_deployment(deployment_id: deployment_id)
118
+ deployment = result[:deployment_info]
119
+ break if deployment[:status] == "Succeeded" || deployment[:status] == "Failed" || deployment[:status] == "Stopped"
120
+ print "."
121
+ sleep 5
122
+ end
123
+ deployment
124
+ end
125
+
126
+ def bundle_type
127
+ if s3_key =~ /\.(tar|tgz|zip)$/
128
+ options[:bundle_type] || $1
129
+ else
130
+ option(:bundle_type)
131
+ end
132
+ end
133
+
134
+ def s3_key
135
+ options[:key] || option(:s3_key)
136
+ end
137
+
138
+ def default_description
139
+ "Deploy build #{context.env['TRAVIS_BUILD_NUMBER']} via Travis CI"
140
+ end
141
+
142
+ def check_auth
143
+ log "Logging in with Access Key: #{access_key_id[-4..-1].rjust(20, '*')}"
144
+ end
145
+
146
+ def cleanup
147
+ end
148
+
149
+ def uncleanup
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,366 @@
1
+ require 'spec_helper'
2
+ require 'aws-sdk'
3
+ require 'dpl/error'
4
+ require 'dpl/provider'
5
+ require 'dpl/provider/code_deploy'
6
+
7
+ describe DPL::Provider::CodeDeploy do
8
+
9
+ subject :provider do
10
+ described_class.new(DummyContext.new, :access_key_id => 'qwertyuiopasdfghjklz', :secret_access_key => 'qwertyuiopasdfghjklzqwertyuiopasdfghjklz')
11
+ end
12
+
13
+ describe '#code_deploy_options' do
14
+ context 'without region' do
15
+ example do
16
+ options = provider.code_deploy_options
17
+ expect(options[:region]).to eq('us-east-1')
18
+ end
19
+ end
20
+
21
+ context 'with region' do
22
+ example do
23
+ region = 'us-west-1'
24
+ provider.options.update(:region => region)
25
+ options = provider.code_deploy_options
26
+ expect(options[:region]).to eq(region)
27
+ end
28
+ end
29
+
30
+ context 'without endpoint' do
31
+ example do
32
+ options = provider.code_deploy_options
33
+ expect(options[:endpoint]).to eq(nil)
34
+ end
35
+ end
36
+
37
+ context 'with endpoint' do
38
+ example do
39
+ endpoint = 's3test.com.s3-website-us-west-2.amazonaws.com'
40
+ provider.options.update(:endpoint => endpoint)
41
+ options = provider.code_deploy_options
42
+ expect(options[:endpoint]).to eq(endpoint)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ describe DPL::Provider::CodeDeploy do
49
+ access_key_id = 'someaccesskey'
50
+ secret_access_key = 'somesecretaccesskey'
51
+ application = 'app'
52
+ deployment_group = 'group'
53
+ description = 'description'
54
+ revision = '23jkljkl'
55
+ client_options = {
56
+ :stub_responses => true,
57
+ :region => 'us-east-1',
58
+ :credentials => ::Aws::Credentials.new(access_key_id, secret_access_key),
59
+ :endpoint => 'https://codedeploy.us-east-1.amazonaws.com'
60
+ }
61
+
62
+ subject :provider do
63
+ described_class.new(DummyContext.new, {
64
+ :access_key_id => access_key_id,
65
+ :secret_access_key => secret_access_key
66
+ })
67
+ end
68
+
69
+ before :each do
70
+ provider.stub(:code_deploy_options).and_return(client_options)
71
+ end
72
+
73
+ describe '#code_deploy' do
74
+ example do
75
+ expect(::Aws::CodeDeploy::Client).to receive(:new).with(client_options).once
76
+ provider.code_deploy
77
+ end
78
+ end
79
+
80
+ describe '#needs_key?' do
81
+ example do
82
+ expect(provider.needs_key?).to eq(false)
83
+ end
84
+ end
85
+
86
+ describe '#revision' do
87
+ expected_s3_revision = {
88
+ revision_type: 'S3',
89
+ s3_location: {
90
+ bucket: 'bucket',
91
+ bundle_type: 'tar',
92
+ key: 'key',
93
+ version: 'object_version_id',
94
+ e_tag: 'etag'
95
+ }
96
+ }
97
+
98
+ expected_github_revision = {
99
+ revision_type: 'GitHub',
100
+ git_hub_location: {
101
+ commit_id: '2lk3j4k2j3k4j23k4j',
102
+ repository: 'travis-ci/dpl'
103
+ }
104
+ }
105
+
106
+ before(:each) do
107
+ provider.stub(:s3_revision).and_return(expected_s3_revision)
108
+ provider.stub(:github_revision).and_return(expected_github_revision)
109
+ end
110
+
111
+ context 'when s3' do
112
+ before do
113
+ provider.options.update(:revision_type => :s3)
114
+ end
115
+
116
+ example do
117
+ expect(provider.revision).to eq(expected_s3_revision)
118
+ end
119
+ end
120
+
121
+ context 'when github' do
122
+ before do
123
+ provider.options.update(:revision_type => :github)
124
+ end
125
+
126
+ example do
127
+ expect(provider.revision).to eq(expected_github_revision)
128
+ end
129
+ end
130
+
131
+ context 'when not specified' do
132
+ before do
133
+ provider.options.update(:bucket => 'bucket')
134
+ end
135
+
136
+ example do
137
+ expect(provider.revision).to eq(expected_s3_revision)
138
+ end
139
+ end
140
+
141
+ context 'when revision and bucket are not specified' do
142
+ example do
143
+ expect(provider.revision).to eq(expected_github_revision)
144
+ end
145
+ end
146
+
147
+ context 'when not a known revision type' do
148
+ type = :bad
149
+
150
+ before do
151
+ provider.options.update(:revision_type => type)
152
+ end
153
+
154
+ example do
155
+ expect(provider).to receive(:error).with(/unknown revision type :#{type}/)
156
+ provider.revision
157
+ end
158
+ end
159
+ end
160
+
161
+ describe '#s3_revision' do
162
+ bucket = 'bucket'
163
+ bundle_type = 'tar'
164
+ key = "/some/key.#{bundle_type}"
165
+
166
+ before(:each) do
167
+ head_data = provider.s3api.stub(:head_object).and_return({
168
+ version_id: 'object_version_id',
169
+ etag: 'etag'
170
+ })
171
+ provider.s3api.stub_responses(:head_object, head_data)
172
+ expect(provider).to receive(:option).at_least(1).times.with(:bucket).and_return(bucket)
173
+ expect(provider).to receive(:bundle_type).and_return(bundle_type)
174
+ expect(provider).to receive(:s3_key).at_least(1).times.and_return(key)
175
+ end
176
+
177
+ example do
178
+ expect(provider.s3_revision[:s3_location]).to include(
179
+ bucket: bucket,
180
+ bundle_type: bundle_type,
181
+ key: key,
182
+ version: 'object_version_id',
183
+ e_tag: 'etag'
184
+ )
185
+ end
186
+ end
187
+
188
+ describe '#github_revision' do
189
+ commit_id = '432s35s3'
190
+ repository = 'git@github.com/org/repo.git'
191
+
192
+ context 'with options set' do
193
+ before(:each) do
194
+ expect(provider.options).to receive(:[]).with(:commit_id).and_return(commit_id)
195
+ expect(provider.options).to receive(:[]).with(:repository).and_return(repository)
196
+ end
197
+
198
+ example do
199
+ expect(provider.github_revision).to eq({
200
+ revision_type: 'GitHub',
201
+ git_hub_location: {
202
+ commit_id: commit_id,
203
+ repository: repository
204
+ }
205
+ })
206
+ end
207
+ end
208
+
209
+ context 'with environment variables' do
210
+ before(:each) do
211
+ expect(provider.options).to receive(:[]).with(:commit_id).and_return(nil)
212
+ expect(provider.options).to receive(:[]).with(:repository).and_return(nil)
213
+ expect(provider.context.env).to receive(:[]).with('TRAVIS_COMMIT').and_return(commit_id)
214
+ expect(provider.context.env).to receive(:[]).with('TRAVIS_REPO_SLUG').and_return(repository)
215
+ end
216
+
217
+ example do
218
+ expect(provider.github_revision).to eq({
219
+ revision_type: 'GitHub',
220
+ git_hub_location: {
221
+ commit_id: commit_id,
222
+ repository: repository
223
+ }
224
+ })
225
+ end
226
+ end
227
+
228
+ context 'without required options' do
229
+ before(:each) do
230
+ expect(provider.options).to receive(:[]).with(:commit_id).and_return(nil)
231
+ provider.options.stub(:[]).with(:repository) { nil }
232
+ expect(provider.context.env).to receive(:[]).with('TRAVIS_COMMIT').and_return(nil)
233
+ expect(provider.context.env).to receive(:[]).with('TRAVIS_REPO_SLUG').and_return(nil)
234
+ end
235
+
236
+ example do
237
+ expect{provider.github_revision}.to raise_error(DPL::Error)
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '#push_app' do
243
+ before(:each) do
244
+ old_options = provider.options
245
+ provider.stub(:options) {old_options.merge({
246
+ :application_name => application,
247
+ :deployment_group_name => deployment_group,
248
+ :description => description,
249
+ :repository => 'git@github.com:travis-ci/dpl.git'
250
+ })}
251
+ end
252
+
253
+ context 'without an error' do
254
+ deployment_id = 'some-deployment-id'
255
+
256
+ before do
257
+ provider.code_deploy.stub_responses(:create_deployment, :deployment_id => deployment_id)
258
+ end
259
+
260
+ example do
261
+ expect(provider).to receive(:log).with(/Triggered deployment \"#{deployment_id}\"\./)
262
+ provider.push_app
263
+ end
264
+
265
+ before do
266
+ allow(provider.code_deploy).to receive(:get_deployment).and_return(
267
+ {:deployment_info => {:status => "Created"}},
268
+ {:deployment_info => {:status => "Queued"}},
269
+ {:deployment_info => {:status => "InProgress"}},
270
+ {:deployment_info => {:status => "Succeeded"}})
271
+ end
272
+
273
+ example 'with :wait_until_deployed' do
274
+ old_options = provider.options
275
+ provider.stub(:options) {old_options.merge({
276
+ app_id: 'app-id',
277
+ wait_until_deployed: true})}
278
+ expect(provider).to receive(:log).with(/Triggered deployment \"#{deployment_id}\"\./)
279
+ expect(provider).to receive(:log).with(/Deployment successful./)
280
+ provider.push_app
281
+ end
282
+ end
283
+
284
+ context 'with an error' do
285
+ before do
286
+ provider.code_deploy.stub_responses(:create_deployment, 'DeploymentLimitExceededException')
287
+ end
288
+
289
+ example do
290
+ expect(provider).to receive(:error).once
291
+ provider.push_app
292
+ end
293
+ end
294
+ end
295
+
296
+ describe '#bundle_type' do
297
+ context 'with s3_key' do
298
+ format = 'zip'
299
+ s3_key = "/some/key/name.#{format}"
300
+
301
+ before(:each) do
302
+ expect(provider).to receive(:s3_key).and_return(s3_key)
303
+ end
304
+
305
+ example do
306
+ expect(provider.bundle_type).to eq(format)
307
+ end
308
+ end
309
+
310
+ context 'without s3_key' do
311
+ bundle_type = 'tar'
312
+
313
+ before do
314
+ expect(provider).to receive(:s3_key).and_return('')
315
+ expect(provider).to receive(:option).with(:bundle_type).and_return(bundle_type)
316
+ end
317
+
318
+ example do
319
+ expect(provider.bundle_type).to eq(bundle_type)
320
+ end
321
+ end
322
+ end
323
+
324
+ describe '#s3_key' do
325
+ key = '/some/key/name.zip'
326
+
327
+ context 'with key option' do
328
+ before do
329
+ expect(provider.options).to receive(:[]).with(:key).and_return(key)
330
+ end
331
+
332
+ example do
333
+ expect(provider.s3_key).to eq(key)
334
+ end
335
+ end
336
+
337
+ context 'with s3_key option' do
338
+ before do
339
+ expect(provider).to receive(:option).with(:s3_key).and_return(key)
340
+ end
341
+
342
+ example do
343
+ expect(provider.s3_key).to eq(key)
344
+ end
345
+ end
346
+ end
347
+
348
+ describe '#default_description' do
349
+ build_number = 2
350
+
351
+ before do
352
+ provider.context.env.stub(:[]).with('TRAVIS_BUILD_NUMBER').and_return(build_number)
353
+ end
354
+
355
+ example do
356
+ expect(provider.default_description).to eq("Deploy build #{build_number} via Travis CI")
357
+ end
358
+ end
359
+
360
+ describe '#check_auth' do
361
+ example do
362
+ expect(provider).to receive(:log).with("Logging in with Access Key: #{access_key_id[-4..-1].rjust(20, '*')}")
363
+ provider.check_auth
364
+ end
365
+ end
366
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dpl-code_deploy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Konstantin Haase
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dpl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.9.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-its
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: json_pure
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: tins
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: coveralls
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: highline
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: deploy tool abstraction for clients
140
+ email: konstantin.mailinglists@googlemail.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - dpl-code_deploy.gemspec
146
+ - lib/dpl/provider/code_deploy.rb
147
+ - spec/provider/code_deploy_spec.rb
148
+ homepage: https://github.com/travis-ci/dpl
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '2.2'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubyforge_project:
168
+ rubygems_version: 2.6.13
169
+ signing_key:
170
+ specification_version: 4
171
+ summary: deploy tool
172
+ test_files:
173
+ - spec/provider/code_deploy_spec.rb