travis_dpl_test 2.0.3.beta.4.ror
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +172 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +392 -0
- data/Gemfile +32 -0
- data/Gemfile.lock +611 -0
- data/LICENSE +19 -0
- data/README.md +2744 -0
- data/Rakefile +210 -0
- data/bin/dpl +11 -0
- data/config/transliterate.yml +733 -0
- data/dpl.gemspec +23 -0
- data/lib/dpl/assets/atlas/install +19 -0
- data/lib/dpl/assets/convox/install +11 -0
- data/lib/dpl/assets/dpl/README.erb.md +138 -0
- data/lib/dpl/assets/dpl/git_ssh +8 -0
- data/lib/dpl/assets/git/detect_private_key +8 -0
- data/lib/dpl/assets/hephy/filter_log +3 -0
- data/lib/dpl/assets/pypi/install +4 -0
- data/lib/dpl/assets/scalingo/install +6 -0
- data/lib/dpl/cli.rb +100 -0
- data/lib/dpl/ctx/bash.rb +549 -0
- data/lib/dpl/ctx/test.rb +255 -0
- data/lib/dpl/ctx.rb +4 -0
- data/lib/dpl/helper/assets.rb +38 -0
- data/lib/dpl/helper/cmd.rb +169 -0
- data/lib/dpl/helper/config_file.rb +49 -0
- data/lib/dpl/helper/cookbook_site_streaming_uploader.rb +249 -0
- data/lib/dpl/helper/env.rb +92 -0
- data/lib/dpl/helper/github.rb +22 -0
- data/lib/dpl/helper/interpolate.rb +160 -0
- data/lib/dpl/helper/memoize.rb +23 -0
- data/lib/dpl/helper/squiggle.rb +24 -0
- data/lib/dpl/helper/transliterate.rb +13 -0
- data/lib/dpl/helper/wrap.rb +11 -0
- data/lib/dpl/helper/zip.rb +71 -0
- data/lib/dpl/provider/dsl.rb +410 -0
- data/lib/dpl/provider/examples.rb +132 -0
- data/lib/dpl/provider/status.rb +61 -0
- data/lib/dpl/provider.rb +651 -0
- data/lib/dpl/providers/anynines.rb +71 -0
- data/lib/dpl/providers/azure_web_apps.rb +63 -0
- data/lib/dpl/providers/bintray.rb +324 -0
- data/lib/dpl/providers/bluemixcloudfoundry.rb +98 -0
- data/lib/dpl/providers/boxfuse.rb +52 -0
- data/lib/dpl/providers/cargo.rb +32 -0
- data/lib/dpl/providers/chef_supermarket.rb +132 -0
- data/lib/dpl/providers/cloud66.rb +46 -0
- data/lib/dpl/providers/cloudfiles.rb +62 -0
- data/lib/dpl/providers/cloudformation.rb +281 -0
- data/lib/dpl/providers/cloudfoundry.rb +89 -0
- data/lib/dpl/providers/codedeploy.rb +190 -0
- data/lib/dpl/providers/convox.rb +130 -0
- data/lib/dpl/providers/datica.rb +64 -0
- data/lib/dpl/providers/ecr.rb +129 -0
- data/lib/dpl/providers/elasticbeanstalk.rb +207 -0
- data/lib/dpl/providers/engineyard.rb +113 -0
- data/lib/dpl/providers/firebase.rb +45 -0
- data/lib/dpl/providers/flynn.rb +35 -0
- data/lib/dpl/providers/gae.rb +78 -0
- data/lib/dpl/providers/gcs.rb +132 -0
- data/lib/dpl/providers/git_push.rb +273 -0
- data/lib/dpl/providers/gleis.rb +74 -0
- data/lib/dpl/providers/hackage.rb +53 -0
- data/lib/dpl/providers/hephy.rb +107 -0
- data/lib/dpl/providers/heroku/api.rb +123 -0
- data/lib/dpl/providers/heroku/git.rb +54 -0
- data/lib/dpl/providers/heroku.rb +111 -0
- data/lib/dpl/providers/lambda.rb +211 -0
- data/lib/dpl/providers/launchpad.rb +80 -0
- data/lib/dpl/providers/netlify.rb +38 -0
- data/lib/dpl/providers/npm.rb +130 -0
- data/lib/dpl/providers/nuget.rb +41 -0
- data/lib/dpl/providers/openshift.rb +52 -0
- data/lib/dpl/providers/opsworks.rb +146 -0
- data/lib/dpl/providers/packagecloud.rb_ +194 -0
- data/lib/dpl/providers/pages/api.rb +106 -0
- data/lib/dpl/providers/pages/git.rb +262 -0
- data/lib/dpl/providers/pages.rb +18 -0
- data/lib/dpl/providers/puppetforge.rb +50 -0
- data/lib/dpl/providers/pypi.rb +125 -0
- data/lib/dpl/providers/releases.rb +234 -0
- data/lib/dpl/providers/rubygems.rb +97 -0
- data/lib/dpl/providers/s3.rb +251 -0
- data/lib/dpl/providers/scalingo.rb +69 -0
- data/lib/dpl/providers/script.rb +32 -0
- data/lib/dpl/providers/snap.rb +68 -0
- data/lib/dpl/providers/surge.rb +59 -0
- data/lib/dpl/providers/testfairy.rb +101 -0
- data/lib/dpl/providers/transifex.rb +72 -0
- data/lib/dpl/providers.rb +48 -0
- data/lib/dpl/string_ext.rb +23 -0
- data/lib/dpl/support/aws_sdk_patch.rb +26 -0
- data/lib/dpl/support/gems.rb +73 -0
- data/lib/dpl/support/gstore_patch.rb +8 -0
- data/lib/dpl/support/version.rb +84 -0
- data/lib/dpl/version.rb +5 -0
- data/lib/dpl.rb +23 -0
- data/status.json +237 -0
- metadata +161 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'dpl/helper/squiggle'
|
|
4
|
+
require 'dpl/helper/wrap'
|
|
5
|
+
require 'dpl/provider/status'
|
|
6
|
+
|
|
7
|
+
# TODO: figure out how to allow adding domain specific behavior like this to Cl
|
|
8
|
+
class Cl::Opt
|
|
9
|
+
OPTS << :interpolate
|
|
10
|
+
|
|
11
|
+
def interpolate?
|
|
12
|
+
opts[:interpolate]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module Dpl
|
|
17
|
+
class Provider < Cl::Cmd
|
|
18
|
+
# DSL available on the provider's class body.
|
|
19
|
+
#
|
|
20
|
+
# Use this to declare various features, requirements, and attributes that
|
|
21
|
+
# apply to your provider.
|
|
22
|
+
module Dsl
|
|
23
|
+
include Squiggle
|
|
24
|
+
|
|
25
|
+
# Declare the full name of the provider. Required if the proper provider
|
|
26
|
+
# name does not match the provider's class name.
|
|
27
|
+
#
|
|
28
|
+
# @param name [String] The provider's full name
|
|
29
|
+
# @return The previously declared full name if no argument is given
|
|
30
|
+
def full_name(name = nil)
|
|
31
|
+
name ? @full_name = name : @full_name || self.name.split('::').last
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Summary of the provider's functionality.
|
|
35
|
+
def summary(summary = nil)
|
|
36
|
+
summary ? super : @summary || "#{full_name} deployment provider"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Summary of the provider's functionality.
|
|
40
|
+
def description(str = nil)
|
|
41
|
+
str = str.strip if str
|
|
42
|
+
super
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Set or read the provider's maturity status with an optional message
|
|
46
|
+
def status(status = nil, msg = nil)
|
|
47
|
+
status ? @status = Status.new(self, status, msg) : @status
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Declare additional variables available for interpolation.
|
|
51
|
+
#
|
|
52
|
+
# Interpolating strings, when these exposed to the user, should safelist
|
|
53
|
+
# which variables are available. Options declared on a provider are
|
|
54
|
+
# always available, except if they are flags, arrays, internal, or
|
|
55
|
+
# secrets. This method can be used to allow additional variables, e.g.
|
|
56
|
+
# from the git context.
|
|
57
|
+
def vars(*vars)
|
|
58
|
+
return self.vars.concat(vars) if vars.any?
|
|
59
|
+
return @vars if instance_variable_defined?(:@vars)
|
|
60
|
+
|
|
61
|
+
vars = superclass.respond_to?(:vars) ? superclass.vars : []
|
|
62
|
+
reject = %i[flag array internal interpolate secret]
|
|
63
|
+
opts = reject.inject(self.opts) { |options, attr| options.reject(&:"#{attr}?") }
|
|
64
|
+
@vars = vars.dup.concat(opts.map(&:name)).uniq.sort - [:strategy]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @!method env
|
|
68
|
+
# Declare an environment variable prefix to accept env vars as options
|
|
69
|
+
#
|
|
70
|
+
# This method is defined in `Env::ClassMethods`.
|
|
71
|
+
#
|
|
72
|
+
# Declares an environment variable prefix that imports environment
|
|
73
|
+
# variables into `opts` if they match declared options.
|
|
74
|
+
#
|
|
75
|
+
# For example, with the following declaration on the class body:
|
|
76
|
+
#
|
|
77
|
+
# ```ruby
|
|
78
|
+
# env :aws
|
|
79
|
+
# opt '--access_key_id ID'
|
|
80
|
+
# ```
|
|
81
|
+
#
|
|
82
|
+
# if the environment variable `AWS_ACCESS_KEY_ID` is set then the option
|
|
83
|
+
# `opts[:access_key_id]` will default to the value given on that
|
|
84
|
+
# variable (i.e. it could still be overwritten by the user by passing
|
|
85
|
+
# the `--access_key_id` option).
|
|
86
|
+
|
|
87
|
+
# @!method opt
|
|
88
|
+
# Declare command line options that the provider supports.
|
|
89
|
+
#
|
|
90
|
+
# This method is inherited from the base class `Cl::Cmd` which is defined
|
|
91
|
+
# in the Rubygem `Cl`. See the gem's documentation for details on how
|
|
92
|
+
# to declare command line options.
|
|
93
|
+
#
|
|
94
|
+
# @see https://github.com/svenfuchs/cl
|
|
95
|
+
|
|
96
|
+
def path(path)
|
|
97
|
+
ENV['PATH'] = "#{File.expand_path(path)}:#{ENV['PATH']}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def move(*paths)
|
|
101
|
+
paths.any? ? @move = paths : @move ||= []
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def node_js(*requirements)
|
|
105
|
+
runtimes(:node_js, requirements)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def python(*requirements)
|
|
109
|
+
runtimes(:python, requirements)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def runtimes(name = nil, requirements = nil)
|
|
113
|
+
return @runtimes ||= [] unless name
|
|
114
|
+
|
|
115
|
+
runtimes << [name, requirements]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Declare APT packages the provider depends on. These will be installed
|
|
119
|
+
# during the `before_install` stage using `apt-get install`, unless the
|
|
120
|
+
# given cmd is already available according to `which [cmd]`.
|
|
121
|
+
#
|
|
122
|
+
# @param package [String] Package name (required).
|
|
123
|
+
# @param cmd [String] Executable command installed by that package (optional, defaults to the package name).
|
|
124
|
+
#
|
|
125
|
+
# @return Previously declared apt packages if no arguments were given.
|
|
126
|
+
def apt(package = nil, cmd = nil)
|
|
127
|
+
return apt << [package, cmd].compact if package
|
|
128
|
+
|
|
129
|
+
@apt ||= self == Provider ? [] : superclass.apt.dup
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Whether or not the provider depends on any apt packages.
|
|
133
|
+
def apt?
|
|
134
|
+
apt.any?
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Declare additional paths to Ruby gem source code that this provider
|
|
138
|
+
# requires.
|
|
139
|
+
#
|
|
140
|
+
# These gems will be installed, and files required at runtime, during the
|
|
141
|
+
# `before_init` stage (not at install time, and/or load time), unless they
|
|
142
|
+
# are already installed.
|
|
143
|
+
#
|
|
144
|
+
# @param name [String] Ruby gem name (required)
|
|
145
|
+
# @param version [String] Ruby gem version (required)
|
|
146
|
+
# @param opts [Hash] options
|
|
147
|
+
# @option opts [Array<String>, String] :require A single path or a list of paths to source files to require from this Ruby gem. If not given the name of the gem will be assumed to be the path to be required.
|
|
148
|
+
#
|
|
149
|
+
# @return Previously declared gems if no arguments were given
|
|
150
|
+
def gem(name = nil, version = nil, opts = {})
|
|
151
|
+
return gem << [name, version, opts] if name
|
|
152
|
+
|
|
153
|
+
@gem ||= self == Provider ? [] : superclass.gem.dup
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def gem?
|
|
157
|
+
gem.any?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Declare NPM packages the provider depends on. These will be installed
|
|
161
|
+
# during the `before_install` stage using `npm install -g`, unless the
|
|
162
|
+
# given cmd is already available according to `which [cmd]`.
|
|
163
|
+
#
|
|
164
|
+
# @param package [String] Package name (required).
|
|
165
|
+
# @param cmd [String] Executable command installed by that package (optional, defaults to the package name).
|
|
166
|
+
#
|
|
167
|
+
# @return Previously declared NPM packages if no arguments are given.
|
|
168
|
+
def npm(package = nil, cmd = nil)
|
|
169
|
+
return npm << [package, cmd].compact if package
|
|
170
|
+
|
|
171
|
+
@npm ||= self == Provider ? [] : superclass.npm.dup
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Whether or not the provider depends on any NPM packages.
|
|
175
|
+
def npm?
|
|
176
|
+
npm.any?
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Declare Python packages the provider depends on. These will be installed
|
|
180
|
+
# during the `before_install` stage using `pip install --user`. A previously
|
|
181
|
+
# installed package is uninstalled before that, but only if `version` was
|
|
182
|
+
# given.
|
|
183
|
+
#
|
|
184
|
+
# @param package [String] Package name (required).
|
|
185
|
+
# @param cmd [String] Executable command installed by that package (optional, defaults to the package name).
|
|
186
|
+
# @param version [String] Package version (optional).
|
|
187
|
+
#
|
|
188
|
+
# @return Previously declared Python packages if no arguments are given.
|
|
189
|
+
def pip(package = nil, cmd = nil, version = nil)
|
|
190
|
+
return pip << [package, cmd, version].compact if package
|
|
191
|
+
|
|
192
|
+
@pip ||= self == Provider ? [] : superclass.pip.dup
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Whether or not the provider depends on any Python packages.
|
|
196
|
+
def pip?
|
|
197
|
+
pip.any?
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Declare shell commands used by the provider.
|
|
201
|
+
#
|
|
202
|
+
# This exists so shell commands used can be separated from the
|
|
203
|
+
# implementation that runs them. This is useful in order to easily get an
|
|
204
|
+
# overview of all shell commands used by a provider on one hand, and in
|
|
205
|
+
# order to keep the implementation code focussed on the logic and
|
|
206
|
+
# functionality it provides, rather than the details of (potentially long
|
|
207
|
+
# winded) shell commands.
|
|
208
|
+
#
|
|
209
|
+
# For example, a shell command declared on the class body like so:
|
|
210
|
+
#
|
|
211
|
+
# ```ruby
|
|
212
|
+
# cmds git_push: 'git push -f %{target}'
|
|
213
|
+
# ```
|
|
214
|
+
#
|
|
215
|
+
# can be used in the deploy stage like so:
|
|
216
|
+
#
|
|
217
|
+
# ```ruby
|
|
218
|
+
# def deploy
|
|
219
|
+
# shell :git_push
|
|
220
|
+
# end
|
|
221
|
+
# ```
|
|
222
|
+
#
|
|
223
|
+
# The variable `%{target}` will be interpolated by calling the method
|
|
224
|
+
# `target` on the provider instance, so it will expect that method to
|
|
225
|
+
# exist.
|
|
226
|
+
#
|
|
227
|
+
# @param cmds [Hash] Commands to declare.
|
|
228
|
+
# @return Previously declared cmds if no argument is given.
|
|
229
|
+
#
|
|
230
|
+
# @see Dpl::Ctx::Bash#shell Ctx::Bash#shell for more details on how to call shell
|
|
231
|
+
# commands.
|
|
232
|
+
def cmds(cmds = nil)
|
|
233
|
+
return self.cmds.update(cmds) if cmds
|
|
234
|
+
|
|
235
|
+
@cmds ||= self == Provider ? {} : superclass.cmds.dup
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Declare error messages that are raised if a shell command fails.
|
|
239
|
+
#
|
|
240
|
+
# This exists so error messages can be separated from the implementation
|
|
241
|
+
# that uses them. This is useful in order to easily get an overview of
|
|
242
|
+
# all error messages used by a provider on one hand, and in order to keep
|
|
243
|
+
# the implementation code focussed on the logic and functionality it
|
|
244
|
+
# provides, rather than the details of (potentially long winded) error
|
|
245
|
+
# message strings.
|
|
246
|
+
#
|
|
247
|
+
# The method `shell` will raise an error if the given shell command fails
|
|
248
|
+
# (returns a non-zero exit code) unless it is called with the option
|
|
249
|
+
# `assert: false`. The error message declared using `errs` will be used
|
|
250
|
+
# to raise with the eror.
|
|
251
|
+
#
|
|
252
|
+
# For example, an error message declared on the class body like so:
|
|
253
|
+
#
|
|
254
|
+
# ```ruby
|
|
255
|
+
# errs git_push: 'Failed to push to %{target}'
|
|
256
|
+
# ```
|
|
257
|
+
#
|
|
258
|
+
# will be included to the raised error if the given command has failed:
|
|
259
|
+
#
|
|
260
|
+
# ```ruby
|
|
261
|
+
# def deploy
|
|
262
|
+
# shell :git_push
|
|
263
|
+
# end
|
|
264
|
+
# ```
|
|
265
|
+
#
|
|
266
|
+
# The variable `%{target}` will be interpolated by calling the method
|
|
267
|
+
# `target` on the provider instance, so it will expect that method to
|
|
268
|
+
# exist.
|
|
269
|
+
#
|
|
270
|
+
# @param errs [Hash] Error messages to declare.
|
|
271
|
+
# @return Previously declared errs if no argument is given.
|
|
272
|
+
#
|
|
273
|
+
# See Dpl::Ctx::Bash#shell for more details on how to call shell
|
|
274
|
+
# commands.
|
|
275
|
+
def errs(errs = nil)
|
|
276
|
+
return self.errs.update(errs) if errs
|
|
277
|
+
|
|
278
|
+
@errs ||= self == Provider ? {} : superclass.errs.dup
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Declare other messages, such as info level log output, warnings, or
|
|
282
|
+
# custom strings, such as commit messages or descriptions.
|
|
283
|
+
#
|
|
284
|
+
# This exists so various messages can be separated from the
|
|
285
|
+
# implementation that uses them. This is useful in order to easily get an
|
|
286
|
+
# overview of all error messages used by a provider on one hand, and in
|
|
287
|
+
# order to keep the implementation code focussed on the logic and
|
|
288
|
+
# functionality it provides, rather than the details of (potentially long
|
|
289
|
+
# winded) message strings.
|
|
290
|
+
#
|
|
291
|
+
# For example, a message declared on the class body like so:
|
|
292
|
+
#
|
|
293
|
+
# ```ruby
|
|
294
|
+
# msgs login: 'Logging in to the service %{full_name}'
|
|
295
|
+
# ```
|
|
296
|
+
#
|
|
297
|
+
# could be used by the implementation like so:
|
|
298
|
+
#
|
|
299
|
+
# ```ruby
|
|
300
|
+
# def login
|
|
301
|
+
# info :login
|
|
302
|
+
# end
|
|
303
|
+
# ```
|
|
304
|
+
#
|
|
305
|
+
# The variable `%{full_name}` will be interpolated by calling the method
|
|
306
|
+
# `full_name` on the provider instance, so it will expect that method to
|
|
307
|
+
# exist.
|
|
308
|
+
#
|
|
309
|
+
# It is possible to use msgs in order to declare and use custom messages,
|
|
310
|
+
# e.g. for the commit message on a commit a provider needs to create, or
|
|
311
|
+
# a description that needs to be included to an API call.
|
|
312
|
+
#
|
|
313
|
+
# For example, a message declared on the class body like so:
|
|
314
|
+
#
|
|
315
|
+
# ```ruby
|
|
316
|
+
# cmds git_commit: 'git commit -am "%{commit_msg}"'
|
|
317
|
+
# msgs commit_msg: 'Commit build artifacts on build %{build_number}'
|
|
318
|
+
# ```
|
|
319
|
+
#
|
|
320
|
+
# could be used by the implementation like so:
|
|
321
|
+
#
|
|
322
|
+
# ```ruby
|
|
323
|
+
# def create_commit
|
|
324
|
+
# shell :git_commit
|
|
325
|
+
# end
|
|
326
|
+
#
|
|
327
|
+
# def commit_msg
|
|
328
|
+
# interpolate(msg(:commit_msg))
|
|
329
|
+
# end
|
|
330
|
+
# ```
|
|
331
|
+
#
|
|
332
|
+
# Note that in cases where builtin methods such as `shell`, `info`,
|
|
333
|
+
# `warn` etc. are not used the method `interpolate` needs to be used in
|
|
334
|
+
# order to interpolate variables used in a message (if any).
|
|
335
|
+
#
|
|
336
|
+
# @param msgs [Hash] Messages to declare.
|
|
337
|
+
# @return Previously declared msgs if no argument is given.
|
|
338
|
+
def msgs(msgs = nil)
|
|
339
|
+
return self.msgs.update(msgs) if msgs
|
|
340
|
+
|
|
341
|
+
@msgs ||= self == Provider ? {} : superclass.msgs.dup
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def strs(strs = nil)
|
|
345
|
+
return self.strs.update(strs) if strs
|
|
346
|
+
|
|
347
|
+
@strs ||= self == Provider ? {} : superclass.strs.dup
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
# Declare artifacts, such as executables during the `install` stage that
|
|
351
|
+
# need to be kept during `cleanup`.
|
|
352
|
+
#
|
|
353
|
+
# @param paths [String] Paths to artifacts to keep during `cleanup`
|
|
354
|
+
# @return Previously declared artifacts to keep if no argument is given.
|
|
355
|
+
def keep(*paths)
|
|
356
|
+
return keep.concat(paths) if paths.any?
|
|
357
|
+
|
|
358
|
+
@keep ||= self == Provider ? [] : superclass.keep.dup
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# Declare features that the provider needs.
|
|
362
|
+
#
|
|
363
|
+
# Known features currently are:
|
|
364
|
+
#
|
|
365
|
+
# * `ssh_key`: Generates a temporary, per-build SSH key, and calls the
|
|
366
|
+
# methods `add_key` and `remove_key` if the provider defines them.
|
|
367
|
+
# This gives providers the opportunity to install this key on their
|
|
368
|
+
# service, and remove it after the deployment has finished.
|
|
369
|
+
# * `git`: Populates the git config.user and config.email attributes,
|
|
370
|
+
# unless present.
|
|
371
|
+
# * `git_http_user_agent`: Changes the environment variable
|
|
372
|
+
# `GIT_HTTP_USER_AGENT` to the one generated by `user_agent`. This
|
|
373
|
+
# gives providers the opportunity to identify and track coming from
|
|
374
|
+
# Travis CI and/or dpl.
|
|
375
|
+
#
|
|
376
|
+
# @param features [Symbol] Features to activate for this provider
|
|
377
|
+
# @return Previously declared features needed if no argument is given.
|
|
378
|
+
def needs(*features)
|
|
379
|
+
return needs.concat(features) if features.any?
|
|
380
|
+
|
|
381
|
+
@needs ||= self == Provider ? [] : superclass.needs.dup
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Whether or not the provider has declared any features it needs.
|
|
385
|
+
def needs?(feature)
|
|
386
|
+
needs.include?(feature)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# Generates a useragent string that identifies the current dpl version,
|
|
390
|
+
# and whether it runs int he context of Travis CI. Can include arbitrary
|
|
391
|
+
# extra strings or key value pairs (passed as String or Hash arguments).
|
|
392
|
+
# @param strs [String(s) or Hash(es)] Additional strings or key value pairs to include to the useragent string.
|
|
393
|
+
# @return [String] The useragent string
|
|
394
|
+
def user_agent(*strs)
|
|
395
|
+
strs.unshift "dpl/#{Dpl::VERSION}"
|
|
396
|
+
strs.unshift 'travis/0.1.0' if ENV['TRAVIS']
|
|
397
|
+
strs = strs.flat_map { |e| e.is_a?(Hash) ? e.map { |k, v| "#{k}/#{v}" } : e }
|
|
398
|
+
strs.join(' ').gsub(/\s+/, ' ').strip
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def ruby_version
|
|
402
|
+
Gem::Version.new(RUBY_VERSION)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def ruby_pre?(version)
|
|
406
|
+
ruby_version < Gem::Version.new(version)
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dpl
|
|
4
|
+
class Examples < Struct.new(:const)
|
|
5
|
+
def cmds
|
|
6
|
+
examples.map(&:cmd).join("\n")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def full_config
|
|
10
|
+
full.config
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def configs
|
|
14
|
+
examples.map(&:config)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def examples
|
|
18
|
+
[requireds, required, many].flatten.compact.uniq
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def requireds
|
|
22
|
+
requireds_opts.map { |opts| example(opts) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def required
|
|
26
|
+
opts = required_opts
|
|
27
|
+
example(opts)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def many
|
|
31
|
+
opts = const.opts.opts
|
|
32
|
+
opts = order(opts)
|
|
33
|
+
opts = without_required(opts)
|
|
34
|
+
opts = with_required(opts)
|
|
35
|
+
opts = filter(opts)
|
|
36
|
+
opts = opts[0, 5]
|
|
37
|
+
example(opts)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def full
|
|
41
|
+
opts = const.opts.opts
|
|
42
|
+
opts = filter(opts)
|
|
43
|
+
example(opts)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def filter(opts)
|
|
47
|
+
opts = opts.reject(&:internal?)
|
|
48
|
+
opts.reject { |opt| opt.name == :help }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def order(opts)
|
|
52
|
+
cmmn = const.superclass.opts.opts
|
|
53
|
+
opts - cmmn + cmmn
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def with_required(opts)
|
|
57
|
+
requireds = requireds_opts.first || []
|
|
58
|
+
opts = requireds + required_opts + opts
|
|
59
|
+
opts.uniq
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def without_required(opts)
|
|
63
|
+
opts -= const.required.flatten.map { |key| const.opts[key] }
|
|
64
|
+
opts - required_opts.map(&:opts)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def example(opts)
|
|
68
|
+
return unless opts.any?
|
|
69
|
+
|
|
70
|
+
opts = required_opts.concat(opts).uniq.compact
|
|
71
|
+
Example.new(const, opts)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def requireds_opts
|
|
75
|
+
opts = const.required.flatten(1)
|
|
76
|
+
opts.map { |keys| Array(keys).map { |key| const.opts[key] } }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def required_opts
|
|
80
|
+
const.opts.select(&:required?)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class Example < Struct.new(:const, :opts)
|
|
85
|
+
def config
|
|
86
|
+
config = opts_for(opts)
|
|
87
|
+
config = config.merge(strategy: strategy) # hmm.
|
|
88
|
+
compact(config)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def strategy
|
|
92
|
+
const.registry_key.to_s.split(':').last if const.registry_key.to_s.include?(':')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def cmd
|
|
96
|
+
"dpl #{name} #{strs_for(opts)}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def ==(other)
|
|
100
|
+
const == other.const && opts == other.opts
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def name
|
|
104
|
+
const.registry_key.to_s.split(':').join(' ')
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def opts_for(opts)
|
|
108
|
+
opts.map { |opt| [opt.name, value_for(opt)] }.to_h
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def strs_for(opts)
|
|
112
|
+
opts.map { |opt| str_for(opt) }.join(' ')
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def str_for(opt)
|
|
116
|
+
"--#{opt.name} #{value_for(opt)}".strip
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def value_for(opt)
|
|
120
|
+
return if opt.type == :flag
|
|
121
|
+
return 1 if opt.type == :integer
|
|
122
|
+
return opt.enum.first if opt.enum?
|
|
123
|
+
|
|
124
|
+
str = opt.strs.detect { |str| str =~ /^--#{opt.name} (.*)$/ } && ::Regexp.last_match(1)
|
|
125
|
+
str ? str.downcase : 'str'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def compact(hash)
|
|
129
|
+
hash.reject { |_, value| value.nil? }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dpl
|
|
4
|
+
class Provider < Cl::Cmd
|
|
5
|
+
class Status < Struct.new(:provider, :status, :info)
|
|
6
|
+
STATUS = %i[dev alpha beta stable deprecated].freeze
|
|
7
|
+
|
|
8
|
+
MSG = {
|
|
9
|
+
dev: 'Support for deployments to %s is in **development**',
|
|
10
|
+
alpha: 'Support for deployments to %s is in **alpha**',
|
|
11
|
+
beta: 'Support for deployments to %s is in **beta**',
|
|
12
|
+
deprecated: 'Support for deployments to %s is *deprecated**',
|
|
13
|
+
pre_stable: 'Please see [Maturity Levels](%s) for details.'
|
|
14
|
+
}.freeze
|
|
15
|
+
|
|
16
|
+
URL = 'https://github.com/travis-ci/dpl/#maturity-levels'
|
|
17
|
+
|
|
18
|
+
def initialize(provider, status, info)
|
|
19
|
+
unknown!(status) unless known?(status)
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def announce?
|
|
24
|
+
!stable?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def msg
|
|
28
|
+
msg = (MSG[status] % name).to_s
|
|
29
|
+
msg << "(#{info})" if info
|
|
30
|
+
msg << ". #{MSG[:pre_stable] % URL}" if pre_stable?
|
|
31
|
+
msg
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def name
|
|
37
|
+
provider.full_name
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def pre_stable?
|
|
41
|
+
STATUS.index(status) < STATUS.index(:stable)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def stable?
|
|
45
|
+
status == :stable
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def deprecated?
|
|
49
|
+
status == :deprecated
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def known?(status)
|
|
53
|
+
STATUS.include?(status)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def unknown!(status)
|
|
57
|
+
raise "Unknown status: #{status.inspect}. Known statuses are: #{STATUS.map(&:inspect).join(', ')}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|