dpl 2.0.0.alpha.2 → 2.0.0.alpha.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -1
  3. data/Gemfile.lock +13 -8
  4. data/NOTES.md +1 -74
  5. data/README.md +464 -193
  6. data/lib/dpl/assets/convox/install +11 -0
  7. data/lib/dpl/assets/dpl/README.erb.md +4 -0
  8. data/lib/dpl/cli.rb +54 -18
  9. data/lib/dpl/ctx/test.rb +7 -3
  10. data/lib/dpl/helper/env.rb +67 -18
  11. data/lib/dpl/helper/wrap.rb +9 -0
  12. data/lib/dpl/provider.rb +11 -9
  13. data/lib/dpl/provider/dsl.rb +3 -1
  14. data/lib/dpl/provider/status.rb +6 -6
  15. data/lib/dpl/providers.rb +3 -1
  16. data/lib/dpl/providers/anynines.rb +5 -3
  17. data/lib/dpl/providers/azure_web_apps.rb +1 -1
  18. data/lib/dpl/providers/bintray.rb +2 -0
  19. data/lib/dpl/providers/bluemixcloudfoundry.rb +5 -3
  20. data/lib/dpl/providers/boxfuse.rb +1 -1
  21. data/lib/dpl/providers/cargo.rb +10 -1
  22. data/lib/dpl/providers/chef_supermarket.rb +3 -1
  23. data/lib/dpl/providers/cloud66.rb +2 -0
  24. data/lib/dpl/providers/cloudfiles.rb +2 -0
  25. data/lib/dpl/providers/cloudformation.rb +278 -0
  26. data/lib/dpl/providers/cloudfoundry.rb +6 -4
  27. data/lib/dpl/providers/codedeploy.rb +5 -5
  28. data/lib/dpl/providers/convox.rb +121 -0
  29. data/lib/dpl/providers/datica.rb +1 -1
  30. data/lib/dpl/providers/engineyard.rb +2 -0
  31. data/lib/dpl/providers/gae.rb +6 -7
  32. data/lib/dpl/providers/gcs.rb +5 -3
  33. data/lib/dpl/providers/gleis.rb +70 -0
  34. data/lib/dpl/providers/hackage.rb +2 -0
  35. data/lib/dpl/providers/hephy.rb +3 -1
  36. data/lib/dpl/providers/heroku.rb +4 -8
  37. data/lib/dpl/providers/heroku/api.rb +4 -2
  38. data/lib/dpl/providers/heroku/git.rb +3 -1
  39. data/lib/dpl/providers/lambda.rb +4 -4
  40. data/lib/dpl/providers/launchpad.rb +3 -1
  41. data/lib/dpl/providers/netlify.rb +2 -0
  42. data/lib/dpl/providers/npm.rb +2 -0
  43. data/lib/dpl/providers/openshift.rb +2 -0
  44. data/lib/dpl/providers/opsworks.rb +1 -1
  45. data/lib/dpl/providers/packagecloud.rb +2 -0
  46. data/lib/dpl/providers/pages.rb +4 -7
  47. data/lib/dpl/providers/pages/api.rb +16 -12
  48. data/lib/dpl/providers/pages/git.rb +16 -12
  49. data/lib/dpl/providers/puppetforge.rb +2 -0
  50. data/lib/dpl/providers/pypi.rb +2 -0
  51. data/lib/dpl/providers/releases.rb +8 -6
  52. data/lib/dpl/providers/rubygems.rb +3 -1
  53. data/lib/dpl/providers/s3.rb +7 -7
  54. data/lib/dpl/providers/scalingo.rb +2 -0
  55. data/lib/dpl/providers/testfairy.rb +2 -0
  56. data/lib/dpl/providers/transifex.rb +2 -0
  57. data/lib/dpl/version.rb +1 -1
  58. metadata +7 -3
  59. data/lib/dpl/providers/atlas.rb +0 -49
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+
3
+ if ! command -v convox &> /dev/null; then
4
+ echo "Downloading convox CLI"
5
+ mkdir -p $HOME/bin
6
+ export PATH="$HOME/bin:$PATH"
7
+ curl -sL -o $HOME/bin/convox %{install_url}
8
+ chmod +x $HOME/bin/convox
9
+ else
10
+ echo "Convox CLI exists. Skipping installation"
11
+ fi
@@ -101,9 +101,13 @@ Dpl supports the following providers:
101
101
  <% providers.each do |key, name|%>
102
102
  ### <%= name %>
103
103
 
104
+ <%= header(key) %>
105
+
104
106
  ```
105
107
  <%= help(key) %>
106
108
  ```
109
+
110
+ <%= footer(key) %>
107
111
  <% end -%>
108
112
 
109
113
  <%= File.read('./CONTRIBUTING.md').gsub(/^#/, '##') %>
@@ -8,37 +8,77 @@ module Dpl
8
8
  end
9
9
 
10
10
  def run(args)
11
- args = untaint(args)
12
- args = with_provider_opt(args)
13
11
  super
14
- rescue UnknownCmd
15
- unknown_provider(args.first)
16
- rescue Error => e
12
+ rescue UnknownCmd => e
13
+ unknown_provider(e)
14
+ rescue UnknownOption => e
15
+ unknown_option(e)
16
+ rescue Cl::Error, Error => e
17
17
  error(e)
18
18
  end
19
19
 
20
+ def runner(args)
21
+ super(normalize(args))
22
+ end
23
+
24
+ def normalize(args)
25
+ args = untaint(args)
26
+ args = with_cmd_opts(args, provider: 0, strategy: 1)
27
+ args = with_strategy_default(args, :strategy) # should be a generic dispatch feature in Cl
28
+ args
29
+ end
30
+
20
31
  # Tainting is being used for automatically obfuscating values for secure
21
32
  # options, so we want to untaint all incoming args here.
22
33
  def untaint(args)
23
34
  args.map(&:dup).each(&:untaint)
24
35
  end
25
36
 
26
- # backwards compatibility for travis-build dpl v1 integration
27
- def with_provider_opt(args)
28
- return args unless arg = args.detect { |arg| arg.include?('--provider') }
29
- args.delete(arg)
30
- [arg.split('=').last, *args]
37
+ def with_cmd_opts(args, cmds)
38
+ cmds.inject(args) do |args, (cmd, pos)|
39
+ with_cmd_opt(args, cmd, pos)
40
+ end
41
+ end
42
+
43
+ def with_cmd_opt(args, cmd, pos)
44
+ return args unless opt = args.detect { |arg| arg.start_with?("--#{cmd}") }
45
+ ix = args.index(opt)
46
+ args.delete(opt)
47
+ value = opt.include?('=') ? opt.split('=').last : args.delete_at(ix)
48
+ args.insert(pos, value)
49
+ args
50
+ end
51
+
52
+ STRATEGIES = {
53
+ 'heroku' => 'api',
54
+ 'pages' => 'git'
55
+ }
56
+
57
+ def with_strategy_default(args, cmd)
58
+ return args unless default = STRATEGIES[args.first]
59
+ args.insert(1, default) if args[1].nil? || args[1].to_s.start_with?('--')
60
+ args
31
61
  end
32
62
 
33
63
  def error(e)
34
64
  msg = "\e[31m#{e.message}\e[0m"
35
- msg = [msg, *e.backtrace].join("\n") if e.backtrace?
65
+ msg = [msg, *e.backtrace].join("\n") if backtrace?(e)
66
+ abort msg
67
+ end
68
+
69
+ def backtrace?(e)
70
+ e.respond_to?(:backtrace?) && e.backtrace?
71
+ end
72
+
73
+ def unknown_provider(e)
74
+ msg = "\e[31m#{e.message}\e[0m"
75
+ msg << "\nDid you mean: #{e.suggestions.join(', ')}?" if e.suggestions.any?
36
76
  abort msg
37
77
  end
38
78
 
39
- def unknown_provider(name)
40
- msg = "\e[31mUnknown provider: #{name}\e[0m"
41
- msg << "\nDid you mean: #{suggestions(name).join(', ')}?" if suggestions(name).any?
79
+ def unknown_option(e)
80
+ msg = "\e[31m#{e.message}\e[0m"
81
+ msg << "\nDid you mean: #{e.suggestions.join(', ')}?" if e.suggestions.any?
42
82
  abort msg
43
83
  end
44
84
 
@@ -46,9 +86,5 @@ module Dpl
46
86
  return [] unless defined?(DidYouMean)
47
87
  DidYouMean::SpellChecker.new(dictionary: providers).correct(name)
48
88
  end
49
-
50
- def providers
51
- Cl::Cmd.registry.keys.map(&:to_s)
52
- end
53
89
  end
54
90
  end
@@ -60,8 +60,8 @@ module Dpl
60
60
  info cmd.msg if cmd.msg?
61
61
  info cmd.echo if cmd.echo?
62
62
  cmds << cmd.cmd
63
- return true unless cmd.capture?
64
- stdout[cmd.key] || 'captured_stdout'
63
+ return stdout[cmd.key] if stdout.key?(cmd.key)
64
+ cmd.capture? ? 'captured_stdout' : true
65
65
  end
66
66
 
67
67
  def success?
@@ -86,7 +86,7 @@ module Dpl
86
86
 
87
87
  def deprecate_opt(key, msg)
88
88
  msg = "please use #{msg}" if msg.is_a?(Symbol)
89
- warn("deprecated option #{key} (#{msg})")
89
+ warn "Deprecated option #{key} used (#{msg})."
90
90
  end
91
91
 
92
92
  def repo_name
@@ -105,6 +105,10 @@ module Dpl
105
105
  1
106
106
  end
107
107
 
108
+ def git_branch
109
+ 'git branch'
110
+ end
111
+
108
112
  def git_commit_msg
109
113
  'commit msg'
110
114
  end
@@ -1,35 +1,84 @@
1
+ require 'dpl/helper/memoize'
2
+
1
3
  module Dpl
2
4
  module Env
3
5
  def self.included(base)
4
6
  base.extend(ClassMethods)
5
7
  end
6
8
 
9
+ class Env
10
+ include Memoize
11
+ # opts[:allow_skip_underscore] allows unconventional ENV vars such as GOOGLECLOUDKEYFILE
12
+
13
+ attr_reader :cmd, :env, :strs, :keys, :opts
14
+
15
+ def initialize(env, args)
16
+ @env = env
17
+ @opts = args.last.is_a?(Hash) ? args.pop : {}
18
+ @strs = args.map(&:to_s).map(&:upcase)
19
+ end
20
+
21
+ def env(cmd)
22
+ @cmd = cmd
23
+ env = @env.select { |key, _| keys.include?(key) }
24
+ env = env.map { |key, value| [unprefix(key).downcase.to_sym, value] }.to_h
25
+ env.map { |key, value| [dealias(key), value] }.to_h
26
+ end
27
+
28
+ def description(cmd)
29
+ strs = self.strs.map { |str| "#{str}_" }
30
+ strs += self.strs if opts[:allow_skip_underscore]
31
+ strs = strs.size > 1 ? "[#{strs.sort.join('|')}]" : strs.join
32
+ "Options can be given via env vars if prefixed with `#{strs}`. #{example(cmd)}"
33
+ end
34
+
35
+ def example(cmd)
36
+ return unless opt = cmd.opts.detect { |opt| opt.secret? }
37
+ env = self.strs.map { |str| "`#{str}_#{opt.name.upcase}=<#{opt.name}>`" }
38
+ env += self.strs.map { |str| "`#{str}#{opt.name.upcase}=<#{opt.name}>`" } if opts[:allow_skip_underscore]
39
+ "E.g. the option `--#{opt.name}` can be given as #{sentence(env)}."
40
+ end
41
+
42
+ def sentence(strs)
43
+ return strs.join if strs.size == 1
44
+ [strs[0..-2].join(', '), strs[-1]].join(' or ')
45
+ end
46
+
47
+ private
48
+
49
+ def dealias(key)
50
+ opt = cmd.opts.detect { |opt| opt.aliases.include?(key) }
51
+ opt ? opt.name : key
52
+ end
53
+
54
+ def unprefix(key)
55
+ strs.inject(key) { |key, str| key.sub(/^#{str}_?/, '') }
56
+ end
57
+
58
+ def keys
59
+ keys = cmd.opts.map(&:name) + cmd.opts.map(&:aliases).flatten
60
+ strs.map { |str| keys.map { |key| keys_for(str, key) } }.flatten
61
+ end
62
+ memoize :keys
63
+
64
+ def keys_for(str, key)
65
+ keys = [["#{str}_", key.upcase].join]
66
+ keys << [str, key.upcase].join if opts[:allow_skip_underscore]
67
+ keys
68
+ end
69
+ end
70
+
7
71
  # should this sit in Cl?
8
72
  module ClassMethods
9
- attr_reader :env_prefixes
10
-
11
73
  def env(*strs)
12
- opts = strs.last.is_a?(Hash) ? strs.pop : {}
13
74
  if strs.any?
14
- strs = strs.map(&:to_s).map(&:upcase)
15
- @env_prefixes = strs.map { |str| "#{str.to_s.upcase}_" }
16
- # allow unconventional ENV vars such as GOOGLECLOUDKEYFILE
17
- @env_prefixes += strs if opts[:allow_skip_underscore]
18
- elsif env_prefixes
19
- opts = ENV.select { |key, _| prefixed?(key) }
20
- opts.map { |key, value| [unprefix(key).downcase.to_sym, value] }.to_h
75
+ @env = Env.new(ENV, strs)
76
+ elsif env = @env || superclass.instance_variable_get(:@env)
77
+ env.env(self)
21
78
  else
22
79
  {}
23
80
  end
24
81
  end
25
-
26
- def prefixed?(key)
27
- env_prefixes.any? { |prefix| key.to_s.start_with?(prefix) }
28
- end
29
-
30
- def unprefix(key)
31
- env_prefixes.inject(key) { |key, prefix| key.sub(prefix, '') }
32
- end
33
82
  end
34
83
 
35
84
  def opts
@@ -0,0 +1,9 @@
1
+ module Wrap
2
+ extend self
3
+
4
+ def wrap(str, width = 80)
5
+ str.lines.map do |line|
6
+ line.size > width ? line.gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n").strip : line
7
+ end.join("\n")
8
+ end
9
+ end
@@ -147,8 +147,8 @@ module Dpl
147
147
 
148
148
  arg :provider, 'The provider name', required: true
149
149
 
150
- opt '--run CMD', 'Command to execute after the deployment finished successfully', type: :array
151
- opt '--cleanup', 'Skip cleaning up build artifacts before the deployment', negate: %w(skip)
150
+ opt '--cleanup', 'Clean up build artifacts from the Git working directory before the deployment', negate: %w(skip)
151
+ opt '--run CMD', 'Commands to execute after the deployment finished successfully', type: :array
152
152
  opt '--stage NAME', 'Execute the given stage(s) only', type: :array, internal: true, default: STAGES
153
153
  opt '--backtrace', 'Print the backtrace for exceptions', internal: true
154
154
  opt '--fold', 'Wrap log output in folds', internal: true
@@ -170,13 +170,15 @@ module Dpl
170
170
  :validate_runtimes, :user_agent
171
171
 
172
172
  def_delegators :ctx, :apt_get, :gem_require, :npm_install, :pip_install,
173
- :build_dir, :build_number, :repo_slug, :encoding, :git_author_email,
174
- :git_author_name, :git_branch, :git_commit_msg, :git_dirty?, :git_log,
175
- :git_ls_files, :git_ls_remote?, :git_remote_urls, :git_rev_parse,
176
- :git_sha, :git_tag, :machine_name, :node_version, :npm_version, :sleep,
177
- :ssh_keygen, :success?, :tmp_dir, :which, :logger, :rendezvous,
178
- :file_size, :write_file, :write_netrc, :last_out, :last_err, :test?,
179
- :tty?
173
+ :build_dir, :build_number, :encoding, :file_size, :git_author_email,
174
+ :git_author_name, :git_branch, :git_branch, :git_commit_author,
175
+ :git_commit_msg, :git_commit_msg, :git_dirty?, :git_log, :git_log,
176
+ :git_ls_files, :git_ls_remote?, :git_remote_urls, :git_remote_urls,
177
+ :git_rev_parse, :git_rev_parse, :git_sha, :git_tag, :last_err, :last_out,
178
+ :last_out, :logger, :machine_name, :mv, :node_version, :node_version,
179
+ :npm_version, :rendezvous, :rendezvous, :repo_slug, :sleep, :sleep,
180
+ :ssh_keygen, :success?, :test?, :test?, :tmp_dir, :tty?, :which, :which,
181
+ :write_file, :write_netrc
180
182
 
181
183
  attr_reader :repo_name, :key_name
182
184
 
@@ -1,3 +1,5 @@
1
+ require 'dpl/helper/squiggle'
2
+ require 'dpl/helper/wrap'
1
3
  require 'dpl/provider/status'
2
4
 
3
5
  module Dpl
@@ -25,7 +27,7 @@ module Dpl
25
27
 
26
28
  # Summary of the provider's functionality.
27
29
  def description(str = nil)
28
- str << status.msg if str && status && status.announce?
30
+ str = str.strip if str
29
31
  super
30
32
  end
31
33
 
@@ -4,11 +4,11 @@ module Dpl
4
4
  STATUS = %i(dev alpha beta stable deprecated)
5
5
 
6
6
  MSG = {
7
- dev: 'Support for deployments to %s is in development',
8
- alpha: 'Support for deployments to %s is in alpha',
9
- beta: 'Support for deployments to %s is in beta',
10
- deprecated: 'Support for deployments to %s is deprecated',
11
- pre_stable: 'Please see here: %s'
7
+ dev: 'Support for deployments to %s is in **development**',
8
+ alpha: 'Support for deployments to %s is in **alpha**',
9
+ beta: 'Support for deployments to %s is in **beta**',
10
+ deprecated: 'Support for deployments to %s is *deprecated**',
11
+ pre_stable: 'Please see [Maturity Levels](%s) for details.'
12
12
  }
13
13
 
14
14
  URL = 'https://github.com/travis-ci/dpl/#maturity-levels'
@@ -26,7 +26,7 @@ module Dpl
26
26
  msg = "#{MSG[status] % name}"
27
27
  msg << "(#{info})" if info
28
28
  msg << ". #{MSG[:pre_stable] % URL}" if pre_stable?
29
- "\n#{msg}\n"
29
+ msg
30
30
  end
31
31
 
32
32
  private
@@ -1,5 +1,4 @@
1
1
  require 'dpl/providers/anynines'
2
- require 'dpl/providers/atlas'
3
2
  require 'dpl/providers/azure_web_apps'
4
3
  require 'dpl/providers/bintray'
5
4
  require 'dpl/providers/boxfuse'
@@ -9,13 +8,16 @@ require 'dpl/providers/datica'
9
8
  require 'dpl/providers/chef_supermarket'
10
9
  require 'dpl/providers/cloud66'
11
10
  require 'dpl/providers/cloudfiles'
11
+ require 'dpl/providers/cloudformation'
12
12
  require 'dpl/providers/cloudfoundry'
13
13
  require 'dpl/providers/codedeploy'
14
+ require 'dpl/providers/convox'
14
15
  require 'dpl/providers/elasticbeanstalk'
15
16
  require 'dpl/providers/engineyard'
16
17
  require 'dpl/providers/firebase'
17
18
  require 'dpl/providers/gae'
18
19
  require 'dpl/providers/gcs'
20
+ require 'dpl/providers/gleis'
19
21
  require 'dpl/providers/hackage'
20
22
  require 'dpl/providers/hephy'
21
23
  require 'dpl/providers/heroku'
@@ -7,12 +7,14 @@ module Dpl
7
7
  tbd
8
8
  str
9
9
 
10
+ env :anynines
11
+
10
12
  opt '--username USER', 'anynines username', required: true
11
13
  opt '--password PASS', 'anynines password', required: true, secret: true
12
- opt '--organization ORG', 'anynines target organization', required: true
13
- opt '--space SPACE', 'anynines target space', required: true
14
+ opt '--organization ORG', 'anynines organization', required: true
15
+ opt '--space SPACE', 'anynines space', required: true
14
16
  opt '--app_name APP', 'Application name'
15
- opt '--buildpack PACK', 'Custom buildpack name or Git URL'
17
+ opt '--buildpack PACK', 'Buildpack name or Git URL'
16
18
  opt '--manifest FILE', 'Path to the manifest'
17
19
  opt '--logout', default: true, internal: true
18
20
 
@@ -11,9 +11,9 @@ module Dpl
11
11
 
12
12
  env :AZURE_WA
13
13
 
14
- opt '--site SITE', 'Web App name (e.g. myapp in myapp.azurewebsites.net)', required: true
15
14
  opt '--username NAME', 'Web App Deployment Username', required: true
16
15
  opt '--password PASS', 'Web App Deployment Password', required: true, secret: true
16
+ opt '--site SITE', 'Web App name (e.g. myapp in myapp.azurewebsites.net)', required: true
17
17
  opt '--slot SLOT', 'Slot name (if your app uses staging deployment)'
18
18
  opt '--verbose', 'Print deployment output from Azure. Warning: If authentication fails, Git prints credentials in clear text. Correct credentials remain hidden.'
19
19
 
@@ -13,6 +13,8 @@ module Dpl
13
13
 
14
14
  gem 'json'
15
15
 
16
+ env :bintray
17
+
16
18
  opt '--user USER', 'Bintray user', required: true
17
19
  opt '--key KEY', 'Bintray API key', required: true, secret: true
18
20
  opt '--file FILE', 'Path to a descriptor file for the Bintray upload', required: true
@@ -9,14 +9,16 @@ module Dpl
9
9
  tbd
10
10
  str
11
11
 
12
+ env :cloudfoundry
13
+
12
14
  opt '--username USER', 'Bluemix username', required: true
13
15
  opt '--password PASS', 'Bluemix password', required: true, secret: true
14
- opt '--organization ORG', 'Bluemix target organization', required: true
15
- opt '--space SPACE', 'Bluemix target space', required: true
16
+ opt '--organization ORG', 'Bluemix organization', required: true
17
+ opt '--space SPACE', 'Bluemix space', required: true
16
18
  opt '--region REGION', 'Bluemix region', default: 'ng', enum: %w(ng eu-gb eu-de au-syd)
17
19
  opt '--api URL', 'Bluemix api URL'
18
20
  opt '--app_name APP', 'Application name'
19
- opt '--buildpack PACK', 'Custom buildpack name or Git URL'
21
+ opt '--buildpack PACK', 'Buildpack name or Git URL'
20
22
  opt '--manifest FILE', 'Path to the manifest'
21
23
  opt '--skip_ssl_validation', 'Skip SSL validation'
22
24
  opt '--logout', default: true, internal: true
@@ -11,11 +11,11 @@ module Dpl
11
11
 
12
12
  opt '--user USER', required: true
13
13
  opt '--secret SECRET', required: true, secret: true
14
- opt '--config_file FILE', alias: :configfile, deprecated: :configfile
15
14
  opt '--payload PAYLOAD'
16
15
  opt '--app APP'
17
16
  opt '--version VERSION'
18
17
  opt '--env ENV'
18
+ opt '--config_file FILE', alias: :configfile, deprecated: :configfile
19
19
  opt '--extra_args ARGS'
20
20
 
21
21
  URL = 'https://files.boxfuse.com/com/boxfuse/client/boxfuse-commandline/latest/boxfuse-commandline-latest-linux-x64.tar.gz'
@@ -7,13 +7,22 @@ module Dpl
7
7
  tbd
8
8
  str
9
9
 
10
+ env :cargo
11
+
10
12
  opt '--token TOKEN', 'Cargo registry API token', required: true, secret: true
13
+ opt '--allow_dirty', 'Allow publishing from a dirty git working directory'
11
14
 
12
- cmds publish: 'cargo publish --token %{token}'
15
+ cmds publish: 'cargo publish %{publish_opts}'
13
16
 
14
17
  def deploy
15
18
  shell :publish
16
19
  end
20
+
21
+ private
22
+
23
+ def publish_opts
24
+ opts_for(%i(token allow_dirty), dashed: true)
25
+ end
17
26
  end
18
27
  end
19
28
  end