dpl 2.0.0.alpha.11 → 2.0.0.alpha.12

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.
@@ -22,12 +22,17 @@ module Dpl
22
22
  end
23
23
 
24
24
  def normalize(args)
25
+ args = unescape(args)
25
26
  args = untaint(args)
26
27
  args = with_cmd_opts(args, provider: 0, strategy: 1)
27
28
  args = with_strategy_default(args, :strategy) # should be a generic dispatch feature in Cl
28
29
  args
29
30
  end
30
31
 
32
+ def unescape(args)
33
+ args.map { |arg| arg.gsub('\\n', "\n") }
34
+ end
35
+
31
36
  # Tainting is being used for automatically obfuscating values for secure
32
37
  # options, so we want to untaint all incoming args here.
33
38
  def untaint(args)
@@ -0,0 +1,20 @@
1
+ require 'dpl/helper/transliterate'
2
+
3
+ # I18n.load_path << File.expand_path('config/transliterate.yml')
4
+ # I18n.eager_load!
5
+ # I18n.config.available_locales_set << :en # seems really wrong, but ¯\_(ツ)_/¯
6
+
7
+ module Dpl
8
+ module Github
9
+ include Transliterate
10
+
11
+ def normalize_filename(str)
12
+ str = File.basename(str)
13
+ str = str.split(' ').first
14
+ str = transliterate(str)
15
+ str.gsub(/[^\w@+\-_]/, '.')
16
+ end
17
+
18
+ extend self
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ module Dpl
2
+ module Transliterate
3
+ APPROXIMATIONS = YAML.load(File.read(File.expand_path('../../../../config/transliterate.yml', __FILE__)))
4
+
5
+ def transliterate(string, replacement = '.')
6
+ string.gsub(/[^\x00-\x7f]/u) do |char|
7
+ APPROXIMATIONS[char] || replacement
8
+ end
9
+ end
10
+ end
11
+ end
@@ -5,7 +5,7 @@ require 'find'
5
5
  module Dpl
6
6
  module Providers
7
7
  class Bintray < Provider
8
- status :beta
8
+ status :stable
9
9
 
10
10
  description sq(<<-str)
11
11
  tbd
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Cloudformation < Provider
4
- status :dev
4
+ status :stable
5
5
 
6
6
  full_name 'AWS CloudFormation'
7
7
 
@@ -27,9 +27,7 @@ module Dpl
27
27
  opt '--wait', 'Wait for CloutFormation to finish the stack creation and update', default: true
28
28
  opt '--wait_timeout SEC', 'How many seconds to wait for stack creation and update.', type: :integer, default: 3600
29
29
  opt '--create_timeout SEC', 'How many seconds to wait before the stack status becomes CREATE_FAILED', type: :integer, default: 3600, note: 'valid only when creating a stack'
30
- # if passing a session_token is not recommended in CI/CD why do we add it to dpl?
31
- opt '--session_token STR', 'AWS Session Access Token if using STS assume role', note: 'Not recommended on CI/CD'
32
- opt '--parameters STR', 'key=value pairs or ENV var names', type: :array, sep: ',', eg: 'one=1 or ENV_VAR_TWO'
30
+ opt '--parameters STR', 'key=value pairs or ENV var names', type: :array, eg: 'one=1 or ENV_VAR_TWO'
33
31
  opt '--output_file PATH', 'Path to output file to store CloudFormation outputs to'
34
32
 
35
33
  msgs login: 'Using Access Key: %{access_key_id}',
@@ -184,7 +182,7 @@ module Dpl
184
182
  end
185
183
 
186
184
  def credentials
187
- Aws::Credentials.new(access_key_id, secret_access_key, session_token)
185
+ Aws::Credentials.new(access_key_id, secret_access_key)
188
186
  end
189
187
 
190
188
  def assume_role(params)
@@ -200,7 +198,7 @@ module Dpl
200
198
  end
201
199
 
202
200
  def now
203
- Time.now.strftime('%Y-%m-%dT%H:%M:%S')
201
+ Time.now.strftime('%Y%m%d%H%M%S')
204
202
  end
205
203
 
206
204
  def url?(str)
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Cloudfoundry < Provider
4
- status :alpha
4
+ status :stable
5
5
 
6
6
  full_name 'Cloud Foundry'
7
7
 
@@ -20,10 +20,12 @@ module Dpl
20
20
  opt '--update_cli'
21
21
  opt '--create'
22
22
  opt '--promote', default: true
23
- opt '--env VARS', type: :array, sep: ','
23
+ opt '--env_names VARS', type: :array, sep: ','
24
+ opt '--env VARS', type: :array
24
25
  opt '--env_file FILE'
25
26
  opt '--description STR'
26
27
  opt '--generation NUM', type: :int, default: '2'
28
+ opt '--prepare CMDS', 'Run commands with convox cli available just before deployment', type: :array
27
29
 
28
30
  # if app and rack are exported to the env, do they need to be passed to these commands?
29
31
  cmds login: 'convox version --rack %{rack}',
@@ -58,28 +60,26 @@ module Dpl
58
60
  shell :create
59
61
  end
60
62
 
63
+ def prepare
64
+ Array(super).each do |cmd|
65
+ cmd.casecmp('restart').zero? ? restart : run_cmd(cmd)
66
+ end
67
+ end
68
+
61
69
  def deploy
62
70
  shell :set_env, echo: false unless env.empty?
63
- shell promote ? :deploy : :build, echo: false
71
+ shell promote? ? :deploy : :build, echo: false
64
72
  end
65
73
 
66
- # not sure about this api. i like that there is an api for people to include
67
- # env vars from the current build env, but maybe it would be better to expose
68
- # FOO=$FOO? is mapping a bare env key to a key/value pair a concept in convox?
69
- #
70
- # def env
71
- # env = env_file.concat(super || []) # TODO Cl should return an empty array, shouldn't it?
72
- # env = env.map { |str| str.include?('=') ? str : "#{str}=#{ENV[str]}" }
73
- # env.map { |str| escape(str) }.join(' ')
74
- # end
75
-
76
- # here's an alternative implementation that would expose FOO=$FOO:
77
- gem 'sh_vars', '~> 1.0.2'
74
+ def env_names
75
+ env = super || []
76
+ env = env.map { |str| "#{str}=#{ENV[str]}" }
77
+ env_file.concat(env)
78
+ end
78
79
 
79
80
  def env
80
- env = env_file.concat(super || [])
81
- env = env.map { |str| ShVars.parse(str).to_h }.inject(&:merge) || {}
82
- env.map { |key, value| "#{key}=#{value.inspect}" }.join(' ')
81
+ env = env_names.concat(super || [])
82
+ env.map { |str| escape(str) }.join(' ')
83
83
  end
84
84
 
85
85
  def env_file
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Elasticbeanstalk < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  full_name 'AWS Elastic Beanstalk'
7
7
 
@@ -29,6 +29,7 @@ module Dpl
29
29
  opt '--zip_file PATH', 'The zip file that you want to deploy'
30
30
  opt '--only_create_app_version', 'Only create the app version, do not actually deploy it'
31
31
  opt '--wait_until_deployed', 'Wait until the deployment has finished'
32
+ opt '--wait_until_deployed_timeout SEC', 'How many seconds to wait for Elastic Beanstalk deployment update.', type: :integer, default: 600
32
33
  opt '--debug', internal: true
33
34
 
34
35
  msgs login: 'Using Access Key: %{access_key_id}',
@@ -122,8 +123,8 @@ module Dpl
122
123
 
123
124
  def wait_until_deployed
124
125
  msgs = []
125
- 1.upto(20) { return if check_deployment(msgs) }
126
- error 'Too many failures'
126
+ 1.upto(wait_until_deployed_timeout / 5) { return if check_deployment(msgs) }
127
+ error 'Deploy status unknown due to timeout. Increase the wait_until_deployed_timeout option'
127
128
  end
128
129
 
129
130
  def check_deployment(msgs)
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Firebase < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  description sq(<<-str)
7
7
  tbd
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Gae < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  full_name 'Google App Engine'
7
7
 
@@ -3,7 +3,7 @@ require 'kconv'
3
3
  module Dpl
4
4
  module Providers
5
5
  class Gcs < Provider
6
- status :beta
6
+ status :stable
7
7
 
8
8
  full_name 'Google Cloud Store'
9
9
 
@@ -4,7 +4,7 @@ module Dpl
4
4
  class Api < Heroku
5
5
  register 'heroku:api'
6
6
 
7
- status :beta
7
+ status :stable
8
8
 
9
9
  full_name 'Heroku API'
10
10
 
@@ -3,7 +3,7 @@ require 'dpl/helper/zip'
3
3
  module Dpl
4
4
  module Providers
5
5
  class Lambda < Provider
6
- status :beta
6
+ status :stable
7
7
 
8
8
  full_name 'AWS Lambda'
9
9
 
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Netlify < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  description sq(<<-str)
7
7
  tbd
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Npm < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  full_name 'npm'
7
7
 
@@ -19,6 +19,7 @@ module Dpl
19
19
  opt '--registry URL', 'npm registry url'
20
20
  opt '--src SRC', 'directory or tarball to publish', default: '.'
21
21
  opt '--tag TAGS', 'distribution tags to add'
22
+ opt '--run_script SCRIPT', 'run the given script from package.json', type: :array, note: 'skips running npm publish'
22
23
  opt '--dry_run', 'performs test run without uploading to registry'
23
24
  opt '--auth_method METHOD', 'Authentication method', enum: %w(auth)
24
25
 
@@ -29,10 +30,12 @@ module Dpl
29
30
  login: 'Authenticated with API token %{api_token}'
30
31
 
31
32
  cmds registry: 'npm config set registry "%{registry}"',
32
- deploy: 'npm publish %{src} %{publish_opts}'
33
+ publish: 'npm publish %{src} %{publish_opts}',
34
+ run: 'npm run %{script}'
33
35
 
34
36
  errs registry: 'Failed to set registry config',
35
- deploy: 'Failed pushing to npm'
37
+ publish: 'Failed to publish',
38
+ run: 'Failed to run script %{script}'
36
39
 
37
40
  def login
38
41
  info :version
@@ -42,7 +45,11 @@ module Dpl
42
45
  end
43
46
 
44
47
  def deploy
45
- shell :deploy
48
+ if run_script?
49
+ run_scripts
50
+ else
51
+ shell :publish
52
+ end
46
53
  end
47
54
 
48
55
  def finish
@@ -51,6 +58,12 @@ module Dpl
51
58
 
52
59
  private
53
60
 
61
+ def run_scripts
62
+ run_script.each do |script|
63
+ shell :run, script: script
64
+ end
65
+ end
66
+
54
67
  def publish_opts
55
68
  opts_for(%i(access tag dry_run), dashed: true)
56
69
  end
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Openshift < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  full_name 'OpenShift'
7
7
 
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Opsworks < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  full_name 'AWS OpsWorks'
7
7
 
@@ -18,7 +18,7 @@ module Dpl
18
18
  open_timeout: 180
19
19
  }
20
20
 
21
- gem 'octokit', '~> 4.14.0'
21
+ gem 'octokit', '~> 4.15.0'
22
22
 
23
23
  full_name 'GitHub Pages (API)'
24
24
 
@@ -4,7 +4,7 @@ module Dpl
4
4
  class Git < Pages
5
5
  register 'pages:git'
6
6
 
7
- status :beta
7
+ status :stable
8
8
 
9
9
  full_name 'GitHub Pages'
10
10
 
@@ -12,7 +12,7 @@ module Dpl
12
12
  tbd
13
13
  str
14
14
 
15
- gem 'octokit', '~> 4.14.0'
15
+ gem 'octokit', '~> 4.15.0'
16
16
  gem 'public_suffix', '~> 3.0.3'
17
17
 
18
18
  required :token, :deploy_key
@@ -66,7 +66,7 @@ module Dpl
66
66
  cname: 'echo "%{fqdn}" > CNAME',
67
67
  git_add: 'git add -A .',
68
68
  git_commit_hook: 'cp %{path} .git/hooks/pre-commit',
69
- git_commit: 'git commit %{git_commit_opts} -qm %{quoted_commit_message}',
69
+ git_commit: 'git commit %{git_commit_opts} -q %{git_commit_msg_opts}',
70
70
  git_show: 'git show --stat-count=10 HEAD',
71
71
  git_push: 'git push%{git_push_opts} --quiet "%{remote_url}" "%{target_branch}":"%{target_branch}" > /dev/null 2>&1'
72
72
 
@@ -170,6 +170,11 @@ module Dpl
170
170
  ' --allow-empty' if allow_empty_commit?
171
171
  end
172
172
 
173
+ def git_commit_msg_opts
174
+ msg = interpolate(commit_message)
175
+ msg.split("\n").reject(&:empty?).map { |msg| %(-m #{quote(msg)}) }
176
+ end
177
+
173
178
  def git_push_opts
174
179
  ' --force' unless keep_history?
175
180
  end
@@ -190,10 +195,6 @@ module Dpl
190
195
  end
191
196
  memoize :email
192
197
 
193
- def commit_message
194
- interpolate(super)
195
- end
196
-
197
198
  def project_name
198
199
  super || fqdn || repo_slug
199
200
  end
@@ -1,7 +1,7 @@
1
1
  module Dpl
2
2
  module Providers
3
3
  class Pypi < Provider
4
- status :beta
4
+ status :stable
5
5
 
6
6
  full_name 'PyPI'
7
7
 
@@ -1,7 +1,11 @@
1
+ require 'dpl/helper/github'
2
+
1
3
  module Dpl
2
4
  module Providers
3
5
  class Releases < Provider
4
- status :beta
6
+ include Github
7
+
8
+ status :stable
5
9
 
6
10
  full_name 'GitHub Releases'
7
11
 
@@ -9,7 +13,7 @@ module Dpl
9
13
  tbd
10
14
  str
11
15
 
12
- gem 'octokit', '~> 4.14.0'
16
+ gem 'octokit', '~> 4.15.0'
13
17
  gem 'mime-types', '~> 3.2.2'
14
18
  gem 'public_suffix', '~> 3.0.3'
15
19
 
@@ -43,6 +47,7 @@ module Dpl
43
47
  insufficient_perm: 'Release resource not found. Make sure your token belongs to an account which has push permission to this repo.',
44
48
  overwrite_existing: 'File %s already exists, overwriting.',
45
49
  skip_existing: 'File %s already exists, skipping.',
50
+ upload_file: 'Uploading file %s ...',
46
51
  set_tag_name: 'Setting tag_name to %s',
47
52
  set_target_commitish: 'Setting target_commitish to %s',
48
53
  missing_file: 'File %s does not exist.',
@@ -88,11 +93,13 @@ module Dpl
88
93
  files.each { |file| upload_file(file) }
89
94
  end
90
95
 
91
- def upload_file(file)
96
+ def upload_file(path)
97
+ file = normalize_filename(path)
92
98
  asset = asset(file)
93
99
  return info :skip_existing, file if asset && !overwrite?
94
100
  delete(asset, file) if asset
95
- api.upload_asset(url, file, name: File.basename(file), content_type: content_type(file))
101
+ info :upload_file, file
102
+ api.upload_asset(url, path, name: file, content_type: content_type(path))
96
103
  end
97
104
 
98
105
  def delete(asset, file)
@@ -168,8 +175,8 @@ module Dpl
168
175
  slug == repo_slug
169
176
  end
170
177
 
171
- def asset(path)
172
- api.release_assets(url).detect { |asset| asset.name == path }
178
+ def asset(name)
179
+ api.release_assets(url).detect { |asset| asset.name == name }
173
180
  end
174
181
 
175
182
  def release_notes