dpl 1.10.17.travis.6637.6 → 2.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +74 -0
  3. data/CONTRIBUTING.md +392 -0
  4. data/Gemfile +17 -3
  5. data/Gemfile.lock +373 -0
  6. data/LICENSE +16 -19
  7. data/NOTES.md +275 -0
  8. data/README.md +1977 -707
  9. data/Rakefile +2 -2
  10. data/bin/dpl +7 -3
  11. data/lib/dpl.rb +20 -0
  12. data/lib/dpl/assets/atlas/install +19 -0
  13. data/lib/dpl/assets/dpl/README.erb.md +133 -0
  14. data/lib/dpl/assets/dpl/git_ssh +2 -0
  15. data/lib/dpl/assets/git/detect_private_key +8 -0
  16. data/lib/dpl/assets/hephy/filter_log +3 -0
  17. data/lib/dpl/assets/pypi/install +4 -0
  18. data/lib/dpl/assets/scalingo/install +6 -0
  19. data/lib/dpl/cli.rb +36 -48
  20. data/lib/dpl/ctx.rb +2 -0
  21. data/lib/dpl/ctx/bash.rb +543 -0
  22. data/lib/dpl/ctx/test.rb +242 -0
  23. data/lib/dpl/helper/assets.rb +36 -0
  24. data/lib/dpl/helper/cmd.rb +167 -0
  25. data/lib/dpl/helper/config_file.rb +47 -0
  26. data/lib/dpl/helper/env.rb +39 -0
  27. data/lib/dpl/helper/interpolate.rb +126 -0
  28. data/lib/dpl/helper/memoize.rb +20 -0
  29. data/lib/dpl/helper/squiggle.rb +22 -0
  30. data/lib/dpl/helper/zip.rb +69 -0
  31. data/lib/dpl/provider.rb +562 -234
  32. data/lib/dpl/provider/dsl.rb +369 -0
  33. data/lib/dpl/provider/examples.rb +128 -0
  34. data/lib/dpl/provider/status.rb +59 -0
  35. data/lib/dpl/providers.rb +40 -0
  36. data/lib/dpl/providers/anynines.rb +65 -0
  37. data/lib/dpl/providers/atlas.rb +49 -0
  38. data/lib/dpl/providers/azure_web_apps.rb +59 -0
  39. data/lib/dpl/providers/bintray.rb +313 -0
  40. data/lib/dpl/providers/bluemixcloudfoundry.rb +92 -0
  41. data/lib/dpl/providers/boxfuse.rb +48 -0
  42. data/lib/dpl/providers/cargo.rb +19 -0
  43. data/lib/dpl/providers/chef_supermarket.rb +128 -0
  44. data/lib/dpl/providers/cloud66.rb +40 -0
  45. data/lib/dpl/providers/cloudfiles.rb +56 -0
  46. data/lib/dpl/providers/cloudfoundry.rb +81 -0
  47. data/lib/dpl/providers/codedeploy.rb +179 -0
  48. data/lib/dpl/providers/datica.rb +60 -0
  49. data/lib/dpl/providers/elasticbeanstalk.rb +195 -0
  50. data/lib/dpl/providers/engineyard.rb +107 -0
  51. data/lib/dpl/providers/firebase.rb +41 -0
  52. data/lib/dpl/providers/gae.rb +74 -0
  53. data/lib/dpl/providers/gcs.rb +105 -0
  54. data/lib/dpl/providers/hackage.rb +47 -0
  55. data/lib/dpl/providers/hephy.rb +101 -0
  56. data/lib/dpl/providers/heroku.rb +111 -0
  57. data/lib/dpl/providers/heroku/api.rb +119 -0
  58. data/lib/dpl/providers/heroku/git.rb +50 -0
  59. data/lib/dpl/providers/lambda.rb +202 -0
  60. data/lib/dpl/providers/launchpad.rb +74 -0
  61. data/lib/dpl/providers/netlify.rb +30 -0
  62. data/lib/dpl/providers/npm.rb +88 -0
  63. data/lib/dpl/providers/openshift.rb +46 -0
  64. data/lib/dpl/providers/opsworks.rb +142 -0
  65. data/lib/dpl/providers/packagecloud.rb +190 -0
  66. data/lib/dpl/providers/pages.rb +17 -0
  67. data/lib/dpl/providers/pages/api.rb +102 -0
  68. data/lib/dpl/providers/pages/git.rb +251 -0
  69. data/lib/dpl/providers/puppetforge.rb +44 -0
  70. data/lib/dpl/providers/pypi.rb +120 -0
  71. data/lib/dpl/providers/releases.rb +214 -0
  72. data/lib/dpl/providers/rubygems.rb +89 -0
  73. data/lib/dpl/providers/s3.rb +243 -0
  74. data/lib/dpl/providers/scalingo.rb +63 -0
  75. data/lib/dpl/providers/script.rb +28 -0
  76. data/lib/dpl/providers/snap.rb +59 -0
  77. data/lib/dpl/providers/surge.rb +55 -0
  78. data/lib/dpl/providers/testfairy.rb +93 -0
  79. data/lib/dpl/providers/transifex.rb +66 -0
  80. data/lib/dpl/support/aws_sdk_patch.rb +23 -0
  81. data/lib/dpl/support/gems.rb +69 -0
  82. data/lib/dpl/support/gstore_patch.rb +6 -0
  83. data/lib/dpl/support/version.rb +83 -0
  84. data/lib/dpl/version.rb +2 -2
  85. metadata +98 -169
  86. data/.coveralls.yml +0 -1
  87. data/.github/CONTRIBUTING.md +0 -173
  88. data/.github/stale.yml +0 -53
  89. data/.gitignore +0 -13
  90. data/.rspec +0 -2
  91. data/.travis.yml +0 -56
  92. data/dpl-anynines.gemspec +0 -3
  93. data/dpl-atlas.gemspec +0 -3
  94. data/dpl-azure_webapps.gemspec +0 -3
  95. data/dpl-bintray.gemspec +0 -3
  96. data/dpl-bitballoon.gemspec +0 -3
  97. data/dpl-bluemix_cloud_foundry.gemspec +0 -3
  98. data/dpl-boxfuse.gemspec +0 -3
  99. data/dpl-cargo.gemspec +0 -3
  100. data/dpl-catalyze.gemspec +0 -3
  101. data/dpl-chef_supermarket.gemspec +0 -20
  102. data/dpl-cloud66.gemspec +0 -3
  103. data/dpl-cloud_files.gemspec +0 -3
  104. data/dpl-cloud_foundry.gemspec +0 -3
  105. data/dpl-code_deploy.gemspec +0 -3
  106. data/dpl-deis.gemspec +0 -3
  107. data/dpl-elastic_beanstalk.gemspec +0 -3
  108. data/dpl-engine_yard.gemspec +0 -3
  109. data/dpl-firebase.gemspec +0 -3
  110. data/dpl-gae.gemspec +0 -3
  111. data/dpl-gcs.gemspec +0 -3
  112. data/dpl-hackage.gemspec +0 -3
  113. data/dpl-hephy.gemspec +0 -3
  114. data/dpl-heroku.gemspec +0 -3
  115. data/dpl-lambda.gemspec +0 -3
  116. data/dpl-launchpad.gemspec +0 -3
  117. data/dpl-npm.gemspec +0 -3
  118. data/dpl-openshift.gemspec +0 -3
  119. data/dpl-ops_works.gemspec +0 -3
  120. data/dpl-packagecloud.gemspec +0 -3
  121. data/dpl-pages.gemspec +0 -3
  122. data/dpl-puppet_forge.gemspec +0 -3
  123. data/dpl-pypi.gemspec +0 -3
  124. data/dpl-releases.gemspec +0 -8
  125. data/dpl-rubygems.gemspec +0 -3
  126. data/dpl-s3.gemspec +0 -3
  127. data/dpl-scalingo.gemspec +0 -3
  128. data/dpl-script.gemspec +0 -3
  129. data/dpl-snap.gemspec +0 -3
  130. data/dpl-surge.gemspec +0 -3
  131. data/dpl-testfairy.gemspec +0 -3
  132. data/dpl-transifex.gemspec +0 -3
  133. data/dpl.gemspec +0 -3
  134. data/gemspec_helper.rb +0 -51
  135. data/lib/dpl/error.rb +0 -3
  136. data/notes/engine_yard.md +0 -1
  137. data/notes/heroku.md +0 -3
  138. data/spec/cli_spec.rb +0 -36
  139. data/spec/provider_spec.rb +0 -191
  140. data/spec/spec_helper.rb +0 -20
@@ -0,0 +1,63 @@
1
+ module Dpl
2
+ module Providers
3
+ class Scalingo < Provider
4
+ status :alpha
5
+
6
+ description sq(<<-str)
7
+ tbd
8
+ str
9
+
10
+ required :api_token, [:username, :password]
11
+
12
+ opt '--app APP', default: :repo_name
13
+ opt '--api_token TOKEN', 'Scalingo API token', alias: :api_key, deprecated: :api_key
14
+ opt '--username NAME', 'Scalingo username'
15
+ opt '--password PASS', 'Scalingo password', secret: true
16
+ opt '--region REGION', 'Scalingo region', default: 'agora-fr1', enum: %w(agora-fr1 osc-fr1)
17
+ opt '--remote REMOTE', 'Git remote name', default: 'scalingo-dpl'
18
+ opt '--branch BRANCH', 'Git branch', default: 'master'
19
+ opt '--timeout SEC', 'Timeout for Scalingo CLI commands', default: 60, type: :integer
20
+
21
+ needs :git, :ssh_key
22
+
23
+ cmds login_key: 'timeout %{timeout} ./scalingo login --api-token %{api_token} > /dev/null',
24
+ login_creds: 'echo -e \"%{username}\n%{password}\" | timeout %{timeout} ./scalingo login > /dev/null',
25
+ add_key: 'timeout %{timeout} ./scalingo keys-add dpl_tmp_key %{key}',
26
+ remove_key: 'timeout %{timeout} ./scalingo keys-remove dpl_tmp_key',
27
+ git_setup: './scalingo --app %{app} git-setup --remote %{remote}',
28
+ push: 'git push %{remote} HEAD:%{branch} -f'
29
+
30
+ errs install: 'Failed to install the Scalingo CLI.',
31
+ login: 'Failed to authenticate with the Scalingo API.',
32
+ add_key: 'Failed to add the ssh key.',
33
+ remove_key: 'Failed to remove the ssh key.',
34
+ git_setup: 'Failed to add the git remote.',
35
+ push: 'Failed to push the app.'
36
+
37
+ def install
38
+ script :install
39
+ ENV['SCALINGO_REGION'] = region if region?
40
+ end
41
+
42
+ def login
43
+ shell api_token ? :login_key : :login_creds, assert: err(:login)
44
+ end
45
+
46
+ def add_key(key, type = nil)
47
+ shell :add_key, key: key
48
+ end
49
+
50
+ def setup
51
+ shell :git_setup
52
+ end
53
+
54
+ def deploy
55
+ shell :push
56
+ end
57
+
58
+ def remove_key
59
+ shell :remove_key
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,28 @@
1
+ module Dpl
2
+ module Providers
3
+ class Script < Provider
4
+ status :alpha
5
+
6
+ summary 'Minimal provider that executes a custom command'
7
+
8
+ description sq(<<-str)
9
+ This deployment provider executes a single, custom command. This is
10
+ usually a script that is contained in your repository, but it can be
11
+ any command executable in the build environment.
12
+
13
+ It is possible to pass arguments to a script deployment like so:
14
+
15
+ dpl script -s './scripts/deploy.sh production --verbose'
16
+
17
+ Deployment will be marked a failure if the script exits with nonzero
18
+ status.
19
+ str
20
+
21
+ opt '-s', '--script SCRIPT', 'The script to execute', required: true
22
+
23
+ def deploy
24
+ shell script, assert: 'Script failed with status %{status}'
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,59 @@
1
+ module Dpl
2
+ module Providers
3
+ class Snap < Provider
4
+ status :dev
5
+
6
+ description sq(<<-str)
7
+ tbd
8
+ str
9
+
10
+ env :snap
11
+
12
+ opt '--token TOKEN', 'Snap API token', required: true, secret: true
13
+ opt '--snap STR', 'Path to the snap to be pushed (can be a glob)', default: '**/*.snap'
14
+ opt '--channel CHAN', 'Channel into which the snap will be released', default: 'edge'
15
+
16
+ apt 'snapd', 'snap'
17
+
18
+ cmds install: 'sudo snap install snapcraft --classic',
19
+ login: 'snapcraft login --with %{token}',
20
+ deploy: 'snapcraft push %{snap_path} --release=%{channel}'
21
+
22
+ msgs login: 'Attemping to login ...',
23
+ no_snaps: 'No snap found matching %{snap}',
24
+ multiple_snaps: 'Multiple snaps found matching %{snap}: %{snap_paths}',
25
+ deploy: 'Pushing snap %{snap_path}'
26
+
27
+ def install
28
+ return if which 'snapcraft'
29
+ shell :install
30
+ ENV['PATH'] += ':/snap/bin'
31
+ end
32
+
33
+ def login
34
+ shell :login, assert: 'Failed to authenticate: %{err}', success: '%{out}', capture: true
35
+ end
36
+
37
+ def validate
38
+ error :no_snaps if snaps.empty?
39
+ error :multiple_snaps if snaps.size > 1
40
+ end
41
+
42
+ def deploy
43
+ shell :deploy
44
+ end
45
+
46
+ def snap_path
47
+ snaps.first
48
+ end
49
+
50
+ def snap_paths
51
+ snaps.join(', ')
52
+ end
53
+
54
+ def snaps
55
+ @snaps ||= Dir[snap].sort
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,55 @@
1
+ require 'open-uri'
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Surge < Provider
6
+ status :alpha
7
+
8
+ description sq(<<-str)
9
+ tbd
10
+ str
11
+
12
+ node_js '>= 8.8.1'
13
+
14
+ gem 'json'
15
+ npm :surge
16
+ env :surge
17
+
18
+ opt '--login EMAIL', 'Surge login (the email address you use with Surge)', required: true
19
+ opt '--token TOKEN', 'Surge login token (can be retrieved with `surge token`)', required: true, secret: true
20
+ opt '--domain NAME', 'Domain to publish to. Not required if the domain is set in the CNAME file in the project folder.'
21
+ opt '--project PATH', 'Path to project directory relative to repo root', default: '.'
22
+
23
+ cmds deploy: 'surge %{project} %{domain}'
24
+
25
+ msgs invalid_project: '%{project} is not a directory',
26
+ missing_domain: 'Please set the domain in .travis.yml or in a CNAME file in the project directory'
27
+
28
+ def login
29
+ ENV['SURGE_LOGIN'] ||= opts[:login]
30
+ ENV['SURGE_TOKEN'] ||= opts[:token]
31
+ end
32
+
33
+ def validate
34
+ error :invalid_project if invalid_project?
35
+ error :missing_domain if missing_domain?
36
+ end
37
+
38
+ def deploy
39
+ shell :deploy
40
+ end
41
+
42
+ def invalid_project?
43
+ !File.directory?(project)
44
+ end
45
+
46
+ def missing_domain?
47
+ !domain && !File.exist?("#{project}/CNAME")
48
+ end
49
+
50
+ def project
51
+ expand(super, build_dir)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,93 @@
1
+ require 'dpl/version'
2
+ require 'net/http'
3
+ require 'securerandom'
4
+
5
+ module Dpl
6
+ module Providers
7
+ class Testfairy < Provider
8
+ status :alpha
9
+
10
+ full_name 'TestFairy'
11
+
12
+ description sq(<<-str)
13
+ tbd
14
+ str
15
+
16
+ gem 'json'
17
+ gem 'multipart-post', '~> 2.0.0', require: 'net/http/post/multipart'
18
+
19
+ opt '--api_key KEY', 'TestFairy API key', required: true, secret: true
20
+ opt '--app_file FILE', 'Path to the app file that will be generated after the build (APK/IPA)', required: true
21
+ opt '--symbols_file FILE', 'Path to the symbols file'
22
+ opt '--testers_groups GROUPS', 'Tester groups to be notified about this build', example: 'e.g. group1,group1'
23
+ opt '--notify', 'Send an email with a changelog to your users'
24
+ opt '--auto_update', 'Automaticall upgrade all the previous installations of this app this version'
25
+ opt '--advanced_options OPTS', 'Comma_separated list of advanced options', example: 'option1,option2'
26
+
27
+ URL = 'https://upload.testfairy.com/api/upload'
28
+ UA = "Travis CI dpl version=#{Dpl::VERSION}"
29
+
30
+ msgs deploy: 'Uploading to TestFairy: %s',
31
+ done: 'Done. Check your build at %s'
32
+
33
+ def deploy
34
+ info :deploy, pretty_print(params)
35
+ body = JSON.parse(http.request(request).body)
36
+ error body['message'] if body['status'] == 'fail'
37
+ info :done, body['build_url']
38
+ end
39
+
40
+ private
41
+
42
+ def params
43
+ @params ||= compact(
44
+ 'api_key': api_key,
45
+ 'apk_file': file(app_file),
46
+ 'symbols_file': file(symbols_file),
47
+ 'testers-groups': testers_groups,
48
+ 'notify': bool(notify),
49
+ 'auto-update': bool(auto_update),
50
+ 'advanced-options': advanced_options,
51
+ 'changelog': changelog
52
+ )
53
+ end
54
+
55
+ def changelog
56
+ git_log "--pretty=oneline --abbrev-commit #{commits}" if commits
57
+ end
58
+
59
+ def commits
60
+ ENV['TRAVIS_COMMIT_RANGE']
61
+ end
62
+
63
+ def request
64
+ Net::HTTP::Post::Multipart.new(uri.path, params, 'User-Agent' => UA)
65
+ end
66
+
67
+ def http
68
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => true)
69
+ end
70
+
71
+ def uri
72
+ @uri ||= URI.parse(URL)
73
+ end
74
+
75
+ def file(path)
76
+ UploadIO.new(path, '', File.basename(path)) if path
77
+ end
78
+
79
+ def bool(obj)
80
+ obj ? 'on' : 'off' unless obj.nil?
81
+ end
82
+
83
+ def pretty_print(params)
84
+ params = params.map do |key, value|
85
+ value = obfuscate(value) if key == :api_key
86
+ value = value.path if value.respond_to?(:path)
87
+ [key, value]
88
+ end
89
+ JSON.pretty_generate(params.to_h)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,66 @@
1
+ module Dpl
2
+ module Providers
3
+ class Transifex < Provider
4
+ status :alpha
5
+
6
+ description sq(<<-str)
7
+ tbd
8
+ str
9
+
10
+ python '>= 2.7', '!= 3.0', '!= 3.1', '!= 3.2', '!= 3.3', '< 3.8'
11
+
12
+ required :api_token, [:username, :password]
13
+
14
+ opt '--api_token TOKEN', 'Transifex API token', secret: true
15
+ opt '--username NAME', 'Transifex username'
16
+ opt '--password PASS', 'Transifex password', secret: true
17
+ opt '--hostname NAME', 'Transifex hostname', default: 'www.transifex.com'
18
+ opt '--cli_version VER', 'CLI version to install', default: '>=0.11'
19
+
20
+ cmds status: 'tx status',
21
+ push: 'tx push --source --no-interactive'
22
+
23
+ msgs login: 'Writing ~/.transifexrc (user: %{username}, password: %{password})'
24
+ errs push: 'Failure pushing to Transifex'
25
+
26
+ RC = sq(<<-rc)
27
+ [%{url}]
28
+ hostname = %{url}
29
+ username = %{username}
30
+ password = %{password}
31
+ rc
32
+
33
+ def install
34
+ pip_install 'transifex-client', 'tx', cli_version
35
+ end
36
+
37
+ def login
38
+ info :login
39
+ write_rc
40
+ shell :status
41
+ end
42
+
43
+ def deploy
44
+ shell :push, retry: true
45
+ end
46
+
47
+ private
48
+
49
+ def write_rc
50
+ write_file '~/.transifexrc', interpolate(RC, opts, secure: true)
51
+ end
52
+
53
+ def username
54
+ super || 'api'
55
+ end
56
+
57
+ def password
58
+ super || api_token
59
+ end
60
+
61
+ def url
62
+ hostname.start_with?('https://') ? hostname : "https://#{hostname}"
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,23 @@
1
+ # Silences "Struct::Tms is deprecated" warnings on Ruby 2.6.2 that would
2
+ # otherwise spam hundereds of warnings, on apparently every single const
3
+ # eager loaded (or something). The constant Tms is not used anywhere in
4
+ # the aws-sdk gem, so it seems safe to skip it.
5
+ #
6
+ # Maybe submit a patch to aws-sdk?
7
+
8
+ Aws::EagerLoader.class_eval do
9
+ def load(klass_or_module)
10
+ @loaded << klass_or_module
11
+ klass_or_module.constants.each do |const_name|
12
+ next if const_name == :Tms
13
+ path = klass_or_module.autoload?(const_name)
14
+ begin
15
+ require(path) if path
16
+ const = klass_or_module.const_get(const_name)
17
+ self.load(const) if Module === const && !@loaded.include?(const)
18
+ rescue LoadError
19
+ end
20
+ end
21
+ self
22
+ end
23
+ end
@@ -0,0 +1,69 @@
1
+ require 'ripper'
2
+
3
+ module Dpl
4
+ module Support
5
+ class Gems < Struct.new(:glob, :opts)
6
+ def each(&block)
7
+ all.uniq.each(&block)
8
+ end
9
+
10
+ def all
11
+ Dir[glob].sort.inject([]) do |gems, path|
12
+ next gems if except.any? { |str| path.include?(str) }
13
+ gems + Parse.new(File.read(path)).gems
14
+ end
15
+ end
16
+
17
+ def except
18
+ @except ||= Array(opts[:except]).map(&:to_s)
19
+ end
20
+
21
+ def opts
22
+ super || {}
23
+ end
24
+
25
+ class Parse < Struct.new(:code)
26
+ def gems
27
+ walk(*sexp).flatten.each_slice(3).to_a
28
+ end
29
+
30
+ def walk(key, *nodes)
31
+ case key
32
+ when :program
33
+ nodes[0].map { |node| walk(*node) }.compact
34
+ when :module
35
+ walk(*nodes[1])
36
+ when :class
37
+ walk(*nodes[2])
38
+ when :bodystmt
39
+ nodes[0].map { |node| walk(*node) }.compact
40
+ when :command
41
+ walk(*nodes[1]) if nodes[0][1] == 'gem'
42
+ when :args_add_block
43
+ args = nodes[0].map { |node| walk(*node) }
44
+ opts = args.last.is_a?(Hash) ? args.pop : {}
45
+ name, version = *args
46
+ [name, version, opts]
47
+ when :bare_assoc_hash
48
+ walk(*nodes[0][0])
49
+ when :assoc_new
50
+ [nodes.map { |node| walk(*node) }].to_h
51
+ when :@label
52
+ nodes.first.sub(':', '').to_sym
53
+ when :string_literal
54
+ walk(*nodes[0])
55
+ when :string_content
56
+ nodes[0][1]
57
+ # when :void_stmt
58
+ # else
59
+ # raise key.to_s
60
+ end
61
+ end
62
+
63
+ def sexp
64
+ Ripper.sexp(code)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end