dpl-connect 1.8.43

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.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +8 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +36 -0
  6. data/Gemfile +100 -0
  7. data/LICENSE +22 -0
  8. data/README.md +934 -0
  9. data/Rakefile +1 -0
  10. data/TESTING.md +29 -0
  11. data/bin/dpl +5 -0
  12. data/dpl.gemspec +32 -0
  13. data/lib/dpl/cli.rb +66 -0
  14. data/lib/dpl/error.rb +3 -0
  15. data/lib/dpl/provider.rb +264 -0
  16. data/lib/dpl/provider/anynines.rb +13 -0
  17. data/lib/dpl/provider/appfog.rb +21 -0
  18. data/lib/dpl/provider/atlas.rb +108 -0
  19. data/lib/dpl/provider/azure_webapps.rb +48 -0
  20. data/lib/dpl/provider/bintray.rb +509 -0
  21. data/lib/dpl/provider/bitballoon.rb +22 -0
  22. data/lib/dpl/provider/bluemix_cloud_foundry.rb +23 -0
  23. data/lib/dpl/provider/boxfuse.rb +57 -0
  24. data/lib/dpl/provider/catalyze.rb +49 -0
  25. data/lib/dpl/provider/chef_supermarket.rb +85 -0
  26. data/lib/dpl/provider/cloud66.rb +38 -0
  27. data/lib/dpl/provider/cloud_files.rb +38 -0
  28. data/lib/dpl/provider/cloud_foundry.rb +43 -0
  29. data/lib/dpl/provider/code_deploy.rb +123 -0
  30. data/lib/dpl/provider/deis.rb +119 -0
  31. data/lib/dpl/provider/divshot.rb +23 -0
  32. data/lib/dpl/provider/elastic_beanstalk.rb +195 -0
  33. data/lib/dpl/provider/engine_yard.rb +90 -0
  34. data/lib/dpl/provider/firebase.rb +27 -0
  35. data/lib/dpl/provider/gae.rb +97 -0
  36. data/lib/dpl/provider/gcs.rb +59 -0
  37. data/lib/dpl/provider/hackage.rb +29 -0
  38. data/lib/dpl/provider/heroku.rb +18 -0
  39. data/lib/dpl/provider/heroku/api.rb +98 -0
  40. data/lib/dpl/provider/heroku/generic.rb +94 -0
  41. data/lib/dpl/provider/heroku/git.rb +28 -0
  42. data/lib/dpl/provider/lambda.rb +236 -0
  43. data/lib/dpl/provider/launchpad.rb +48 -0
  44. data/lib/dpl/provider/modulus.rb +23 -0
  45. data/lib/dpl/provider/npm.rb +64 -0
  46. data/lib/dpl/provider/openshift.rb +59 -0
  47. data/lib/dpl/provider/ops_works.rb +132 -0
  48. data/lib/dpl/provider/packagecloud.rb +144 -0
  49. data/lib/dpl/provider/pages.rb +79 -0
  50. data/lib/dpl/provider/puppet_forge.rb +43 -0
  51. data/lib/dpl/provider/pypi.rb +111 -0
  52. data/lib/dpl/provider/releases.rb +139 -0
  53. data/lib/dpl/provider/rubygems.rb +51 -0
  54. data/lib/dpl/provider/s3.rb +123 -0
  55. data/lib/dpl/provider/scalingo.rb +97 -0
  56. data/lib/dpl/provider/script.rb +29 -0
  57. data/lib/dpl/provider/surge.rb +33 -0
  58. data/lib/dpl/provider/testfairy.rb +190 -0
  59. data/lib/dpl/provider/transifex.rb +45 -0
  60. data/lib/dpl/version.rb +3 -0
  61. data/notes/engine_yard.md +1 -0
  62. data/notes/heroku.md +3 -0
  63. data/spec/cli_spec.rb +36 -0
  64. data/spec/provider/anynines_spec.rb +20 -0
  65. data/spec/provider/appfog_spec.rb +35 -0
  66. data/spec/provider/atlas_spec.rb +99 -0
  67. data/spec/provider/azure_webapps_spec.rb +95 -0
  68. data/spec/provider/bintray_spec.rb +259 -0
  69. data/spec/provider/bitballoon_spec.rb +32 -0
  70. data/spec/provider/bluemixcloudfoundry_spec.rb +23 -0
  71. data/spec/provider/boxfuse_spec.rb +16 -0
  72. data/spec/provider/catalyze_spec.rb +39 -0
  73. data/spec/provider/chef_supermarket_spec.rb +51 -0
  74. data/spec/provider/cloud66_spec.rb +44 -0
  75. data/spec/provider/cloud_files_spec.rb +88 -0
  76. data/spec/provider/cloudfoundry_spec.rb +71 -0
  77. data/spec/provider/code_deploy_spec.rb +360 -0
  78. data/spec/provider/deis_spec.rb +116 -0
  79. data/spec/provider/divshot_spec.rb +28 -0
  80. data/spec/provider/elastic_beanstalk_spec.rb +209 -0
  81. data/spec/provider/firebase_spec.rb +40 -0
  82. data/spec/provider/gae_spec.rb +26 -0
  83. data/spec/provider/gcs_spec.rb +115 -0
  84. data/spec/provider/hackage_spec.rb +47 -0
  85. data/spec/provider/heroku_spec.rb +357 -0
  86. data/spec/provider/lambda_spec.rb +432 -0
  87. data/spec/provider/launchpad_spec.rb +33 -0
  88. data/spec/provider/modulus_spec.rb +29 -0
  89. data/spec/provider/npm_spec.rb +95 -0
  90. data/spec/provider/openshift_spec.rb +91 -0
  91. data/spec/provider/ops_works_spec.rb +127 -0
  92. data/spec/provider/packagecloud_spec.rb +56 -0
  93. data/spec/provider/puppet_forge_spec.rb +60 -0
  94. data/spec/provider/pypi_spec.rb +103 -0
  95. data/spec/provider/releases_spec.rb +303 -0
  96. data/spec/provider/rubygems_spec.rb +106 -0
  97. data/spec/provider/s3_spec.rb +174 -0
  98. data/spec/provider/scalingo_spec.rb +64 -0
  99. data/spec/provider/script_spec.rb +26 -0
  100. data/spec/provider/surge_spec.rb +15 -0
  101. data/spec/provider/testfairy_spec.rb +86 -0
  102. data/spec/provider/transifex_spec.rb +110 -0
  103. data/spec/provider_spec.rb +210 -0
  104. data/spec/spec_helper.rb +20 -0
  105. metadata +279 -0
@@ -0,0 +1,48 @@
1
+ module DPL
2
+ class Provider
3
+ class AzureWebApps < Provider
4
+ def config
5
+ {
6
+ "username" => options[:username] || context.env['AZURE_WA_USERNAME'],
7
+ "password" => options[:password] || context.env['AZURE_WA_PASSWORD'],
8
+ "site" => options[:site] || context.env['AZURE_WA_SITE'],
9
+ "slot" => options[:slot] || context.env['AZURE_WA_SLOT']
10
+ }
11
+ end
12
+
13
+ def git_target
14
+ "https://#{config['username']}:#{config['password']}@#{config['slot'] || config['site']}.scm.azurewebsites.net:443/#{config['site']}.git"
15
+ end
16
+
17
+ def needs_key?
18
+ false
19
+ end
20
+
21
+ def check_app
22
+ end
23
+
24
+ def check_auth
25
+ error "missing Azure Git Deployment username" unless config['username']
26
+ error "missing Azure Git Deployment password" unless config['password']
27
+ error "missing Azure Web App name" unless config['site']
28
+ end
29
+
30
+ def push_app
31
+ log "Deploying to Azure Web App '#{config['slot'] || config['site']}'"
32
+
33
+ if !!options[:skip_cleanup]
34
+ log "Skipping Cleanup"
35
+ context.shell "git checkout HEAD"
36
+ context.shell "git add . --all --force"
37
+ context.shell "git commit -m \"Skip Cleanup Commit\""
38
+ end
39
+
40
+ if !!options[:verbose]
41
+ context.shell "git push --force --quiet #{git_target} HEAD:refs/heads/master"
42
+ else
43
+ context.shell "git push --force --quiet #{git_target} HEAD:refs/heads/master > /dev/null 2>&1"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,509 @@
1
+ require 'json'
2
+ require 'net/http'
3
+ require "uri"
4
+ require 'find'
5
+
6
+ module DPL
7
+ class Provider
8
+ class Bintray < Provider
9
+ def check_auth
10
+ end
11
+
12
+ def needs_key?
13
+ false
14
+ end
15
+
16
+ attr_accessor :test_mode
17
+ attr_reader :user
18
+ attr_reader :key
19
+ attr_reader :file
20
+ attr_reader :passphrase
21
+ attr_reader :url
22
+ attr_reader :dry_run
23
+ attr_reader :descriptor
24
+
25
+ def initialize(*args)
26
+ super(*args)
27
+ @test_mode = false
28
+ @user = options[:user]
29
+ @key = options[:key]
30
+ @url = options[:url]
31
+ @file = options[:file]
32
+ @passphrase = options[:passphrase]
33
+ @dry_run = options[:dry_run]
34
+
35
+ if @user.nil?
36
+ abort("The 'user' argument is required")
37
+ end
38
+ if @key.nil?
39
+ abort("The 'key' argument is required")
40
+ end
41
+ if @file.nil?
42
+ abort("The 'file' argument is required")
43
+ end
44
+ if @url.nil?
45
+ @url = 'https://api.bintray.com'
46
+ end
47
+ if @dry_run.nil?
48
+ @dry_run = false
49
+ end
50
+ end
51
+
52
+ def read_descriptor
53
+ log "Reading descriptor file: #{file}"
54
+ @descriptor = JSON.parse(File.read(file))
55
+ end
56
+
57
+ def descriptor=(json)
58
+ @descriptor = JSON.parse(json)
59
+ end
60
+
61
+ def head_request(path)
62
+ url = URI.parse(self.url)
63
+ req = Net::HTTP::Head.new(path)
64
+ req.basic_auth user, key
65
+
66
+ sock = Net::HTTP.new(url.host, url.port)
67
+ sock.use_ssl = true
68
+ res = sock.start {|http| http.request(req) }
69
+
70
+ return res
71
+ end
72
+
73
+ def post_request(path, body)
74
+ req = Net::HTTP::Post.new(path)
75
+ req.add_field('Content-Type', 'application/json')
76
+ req.basic_auth user, key
77
+ if !body.nil?
78
+ req.body = body.to_json
79
+ end
80
+
81
+ url = URI.parse(self.url)
82
+ sock = Net::HTTP.new(url.host, url.port)
83
+ sock.use_ssl = true
84
+ res = sock.start {|http| http.request(req) }
85
+ return res
86
+ end
87
+
88
+ def put_file_request(local_file_path, upload_path, matrix_params)
89
+ url = URI.parse(self.url)
90
+
91
+ file = File.open(local_file_path, 'rb')
92
+ data = file.read()
93
+ http = Net::HTTP.new(url.host, url.port)
94
+ http.use_ssl = true
95
+
96
+ params = ''
97
+ if !matrix_params.nil?
98
+ matrix_params.each do |key, val|
99
+ params << ";#{key}=#{val}"
100
+ end
101
+ upload_path << params
102
+ end
103
+
104
+ request = Net::HTTP::Put.new("#{upload_path}")
105
+ request.basic_auth user, key
106
+ request.body = data
107
+
108
+ return http.request(request)
109
+ end
110
+
111
+ def upload_file(artifact)
112
+ log "Uploading file '#{artifact.local_path}' to #{artifact.upload_path}"
113
+
114
+ if dry_run
115
+ return
116
+ end
117
+
118
+ package = descriptor["package"]
119
+ version = descriptor["version"]
120
+ package_name = package["name"]
121
+ subject = package["subject"]
122
+ repo = package["repo"]
123
+ version_name = version["name"]
124
+
125
+ path = "/content/#{subject}/#{repo}/#{package_name}/#{version_name}/#{artifact.upload_path}"
126
+ res = put_file_request(artifact.local_path, path, artifact.matrix_params)
127
+ log_bintray_response(res)
128
+ end
129
+
130
+ def package_exists_path
131
+ package = descriptor["package"]
132
+ subject = package["subject"]
133
+ name = package["name"]
134
+ repo = package["repo"]
135
+ return "/packages/#{subject}/#{repo}/#{name}"
136
+ end
137
+
138
+ def package_exists?
139
+ path = package_exists_path
140
+ if !dry_run
141
+ res = head_request(path)
142
+ code = res.code.to_i
143
+ else
144
+ code = 404
145
+ end
146
+
147
+ if code == 404
148
+ return false
149
+ end
150
+ if code == 201 || code == 200
151
+ return true
152
+ end
153
+ name = descriptor["package"]["name"]
154
+ abort("Unexpected HTTP response code #{code} returned from Bintray while checking if package '#{name}' exists. " +
155
+ "Response message: #{res.message}")
156
+ end
157
+
158
+ def version_exists_path
159
+ package = descriptor["package"]
160
+ version = descriptor["version"]
161
+ package_name = package["name"]
162
+ subject = package["subject"]
163
+ repo = package["repo"]
164
+ version_name = version["name"]
165
+
166
+ return "/packages/#{subject}/#{repo}/#{package_name}/versions/#{version_name}"
167
+ end
168
+
169
+ def version_exists?
170
+ path = version_exists_path
171
+ if !dry_run
172
+ res = head_request(path)
173
+ code = res.code.to_i
174
+ else
175
+ code = 404
176
+ end
177
+
178
+ if code == 404
179
+ return false
180
+ end
181
+ if code == 201 || code == 200
182
+ return true
183
+ end
184
+ version_name = descriptor["version"]["name"]
185
+ abort("Unexpected HTTP response code #{code} returned from Bintray while checking if version '#{version_name}' exists. " +
186
+ "Response message: #{res.message}")
187
+ end
188
+
189
+ def create_package
190
+ package = descriptor["package"]
191
+ repo = package["repo"]
192
+ body = {}
193
+
194
+ add_to_map(body, package, "name")
195
+ add_to_map(body, package, "desc")
196
+ add_to_map(body, package, "licenses")
197
+ add_to_map(body, package, "labels")
198
+ add_to_map(body, package, "vcs_url")
199
+ add_to_map(body, package, "website_url")
200
+ add_to_map(body, package, "issue_tracker_url")
201
+ add_to_map(body, package, "public_download_numbers")
202
+ add_to_map(body, package, "public_stats")
203
+
204
+ subject = package["subject"]
205
+ package_name = package["name"]
206
+ log "Creating package '#{package_name}'..."
207
+
208
+ path = "/packages/#{subject}/#{repo}"
209
+ if !dry_run
210
+ res = post_request(path, body)
211
+ log_bintray_response(res)
212
+ code = res.code.to_i
213
+ else
214
+ code = 200
215
+ end
216
+
217
+ if !test_mode
218
+ if code == 201 || code == 200
219
+ add_package_attributes
220
+ end
221
+ end
222
+ RequestDetails.new(path, body)
223
+ end
224
+
225
+ def add_package_attributes
226
+ package = descriptor["package"]
227
+ repo = package["repo"]
228
+ subject = package["subject"]
229
+ package_name = package["name"]
230
+ attributes = package["attributes"]
231
+ path = nil
232
+ if !attributes.nil?
233
+ log "Adding attributes for package '#{package_name}'..."
234
+ path = "/packages/#{subject}/#{repo}/#{package_name}/attributes"
235
+ if !dry_run
236
+ res = post_request(path, attributes)
237
+ log_bintray_response(res)
238
+ end
239
+ end
240
+ RequestDetails.new(path, attributes)
241
+ end
242
+
243
+ def create_version
244
+ package = descriptor["package"]
245
+ version = descriptor["version"]
246
+ repo = package["repo"]
247
+ body = {}
248
+
249
+ add_to_map(body, version, "name")
250
+ add_to_map(body, version, "desc")
251
+ add_to_map(body, version, "released")
252
+ add_to_map(body, version, "vcs_tag")
253
+ add_to_map(body, version, "github_release_notes_file")
254
+ add_to_map(body, version, "github_use_tag_release_notes")
255
+ add_to_map(body, version, "attributes")
256
+
257
+ package_name = package["name"]
258
+ subject = package["subject"]
259
+ version_name = version["name"]
260
+ log "Creating version '#{version_name}'..."
261
+
262
+ path = "/packages/#{subject}/#{repo}/#{package_name}/versions"
263
+ if !dry_run
264
+ res = post_request(path, body)
265
+ log_bintray_response(res)
266
+ code = res.code.to_i
267
+ else
268
+ code = 200
269
+ end
270
+
271
+ if !test_mode
272
+ if code == 201 || code == 200
273
+ add_version_attributes
274
+ end
275
+ end
276
+ RequestDetails.new(path, body)
277
+ end
278
+
279
+ def add_version_attributes
280
+ package = descriptor["package"]
281
+ package_name = package["name"]
282
+ subject = package["subject"]
283
+ version = descriptor["version"]
284
+ version_name = version["name"]
285
+ repo = package["repo"]
286
+ attributes = version["attributes"]
287
+ path = nil
288
+ if !attributes.nil?
289
+ log "Adding attributes for version '#{version_name}'..."
290
+ path = "/packages/#{subject}/#{repo}/#{package_name}/versions/#{version_name}/attributes"
291
+ if !dry_run
292
+ res = post_request(path, attributes)
293
+ log_bintray_response(res)
294
+ end
295
+ end
296
+ RequestDetails.new(path, attributes)
297
+ end
298
+
299
+ def check_and_create_package
300
+ if !package_exists?
301
+ create_package
302
+ end
303
+ end
304
+
305
+ def check_and_create_version
306
+ if !version_exists?
307
+ create_version
308
+ end
309
+ end
310
+
311
+ def upload_files
312
+ files = files_to_upload
313
+
314
+ files.each do |key, artifact|
315
+ upload_file(artifact)
316
+ end
317
+ end
318
+
319
+ def publish_version
320
+ publish = descriptor["publish"]
321
+ if publish
322
+ package = descriptor["package"]
323
+ version = descriptor["version"]
324
+ repo = package["repo"]
325
+ package_name = package["name"]
326
+ subject = package["subject"]
327
+ version_name = version["name"]
328
+
329
+ log "Publishing version '#{version_name}' of package '#{package_name}'..."
330
+ path = "/content/#{subject}/#{repo}/#{package_name}/#{version_name}/publish"
331
+ if !dry_run
332
+ res = post_request(path, nil)
333
+ log_bintray_response(res)
334
+ end
335
+ end
336
+ RequestDetails.new(path, nil)
337
+ end
338
+
339
+ def gpg_sign_version
340
+ version = descriptor["version"]
341
+ gpg_sign = version["gpgSign"]
342
+ if gpg_sign
343
+ package = descriptor["package"]
344
+ repo = package["repo"]
345
+ package_name = package["name"]
346
+ subject = package["subject"]
347
+ version_name = version["name"]
348
+
349
+ body = nil
350
+ if !passphrase.nil?
351
+ log "Signing version with no passphrase..."
352
+ body = {}
353
+ body["passphrase"] = passphrase
354
+ else
355
+ log "Signing version with passphrase..."
356
+ end
357
+
358
+ path = "/gpg/#{subject}/#{repo}/#{package_name}/versions/#{version_name}"
359
+ if !dry_run
360
+ res = post_request(path, body)
361
+ log_bintray_response(res)
362
+ end
363
+ RequestDetails.new(path, body)
364
+ end
365
+ end
366
+
367
+ # Get the root path from which to start collecting files to be
368
+ # uploaded to Bintray.
369
+ def root_path(str)
370
+ index = str.index('(')
371
+ path = nil
372
+ if index.nil? || str.start_with?('(')
373
+ path = str
374
+ else
375
+ path = str[0, index]
376
+ end
377
+
378
+ if !test_mode && !File.exist?(path)
379
+ log "Warning: Path: #{path} does not exist."
380
+ return nil
381
+ end
382
+ return path
383
+ end
384
+
385
+ # Fills a map with Artifact objects which match
386
+ # the include pattern and do not match the exclude pattern.
387
+ # The artifacts are files collected from the file system.
388
+ def fill_files_map(map, include_pattern, exclude_pattern, upload_pattern, matrix_params)
389
+ # Get the root path from which to start collecting the files.
390
+ root_path = root_path(include_pattern)
391
+ if root_path.nil?
392
+ return
393
+ end
394
+
395
+ # Start scanning the root path recursively.
396
+ Find.find(root_path) do |path|
397
+ add_if_matches(map, path, include_pattern, exclude_pattern, upload_pattern, matrix_params)
398
+ end
399
+ end
400
+
401
+ def add_if_matches(map, path, include_pattern, exclude_pattern, upload_pattern, matrix_params)
402
+ res = path.match(/#{include_pattern}/)
403
+
404
+ # If the file matches the include pattern and it is not a directory.
405
+ # In case test_mode is set, we do not check if the file exists.
406
+ if !res.nil? && (test_mode || File.file?(path))
407
+ # If the file does not match the exclude pattern.
408
+ if exclude_pattern.nil? || exclude_pattern.empty? || !path.match(/#{exclude_pattern}/)
409
+ # Using the capturing groups in the include pattern, replace the $1, $2, ...
410
+ # in the upload pattern.
411
+ groups = res.captures
412
+ replaced_upload_pattern = upload_pattern
413
+ for i in 0..groups.size-1
414
+ replaced_upload_pattern = replaced_upload_pattern.gsub("$#{i+1}", groups[i])
415
+ end
416
+ map[path] = Artifact.new(path, replaced_upload_pattern, matrix_params)
417
+ end
418
+ end
419
+ end
420
+
421
+ # Returns a map containing Artifact objects.
422
+ # The map contains the files to be uploaded to Bintray.
423
+ def files_to_upload
424
+ upload_files = Hash.new()
425
+ files = descriptor["files"]
426
+ if files.nil?
427
+ return upload_files
428
+ end
429
+
430
+ files.each { |patterns|
431
+ fill_files_map(
432
+ upload_files,
433
+ patterns["includePattern"],
434
+ patterns["excludePattern"],
435
+ patterns["uploadPattern"],
436
+ patterns["matrixParams"])
437
+ }
438
+
439
+ return upload_files
440
+ end
441
+
442
+ def deploy
443
+ read_descriptor
444
+ check_and_create_package
445
+ check_and_create_version
446
+ upload_files
447
+ gpg_sign_version
448
+ publish_version
449
+ end
450
+
451
+ # Copies a key from one map to another, if the key exists there.
452
+ def add_to_map(to_map, from_map, key)
453
+ if !from_map[key].nil?
454
+ to_map[key] = from_map[key]
455
+ end
456
+ end
457
+
458
+ def log_bintray_response(res)
459
+ msg = ''
460
+ if !res.body.nil?
461
+ begin
462
+ response = JSON.parse(res.body)
463
+ msg = response["message"]
464
+ rescue
465
+ end
466
+ end
467
+
468
+ log "Bintray response: #{res.code.to_i} #{res.message}. #{msg}"
469
+ end
470
+
471
+ def log(msg)
472
+ puts "[Bintray Upload] #{msg}"
473
+ end
474
+
475
+ # This class represents an artifact (file) to be uploaded to Bintray.
476
+ class Artifact
477
+ def initialize(local_path, upload_path, matrix_params)
478
+ @local_path = local_path
479
+ @upload_path = upload_path
480
+ @matrix_params = matrix_params
481
+ end
482
+
483
+ def hash
484
+ return @localPath.hash
485
+ end
486
+
487
+ def eql?(other)
488
+ @localPath == other.local_path
489
+ end
490
+
491
+ attr_reader :local_path
492
+ attr_reader :upload_path
493
+ attr_reader :matrix_params
494
+ end
495
+
496
+ # Used to return the path and body of REST requests sent to Bintray.
497
+ # Used for testing.
498
+ class RequestDetails
499
+ def initialize(path, body)
500
+ @path = path
501
+ @body = body
502
+ end
503
+
504
+ attr_reader :path
505
+ attr_reader :body
506
+ end
507
+ end
508
+ end
509
+ end