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

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