dpl-code_deploy 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
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