dpl 2.0.3.beta.4 → 2.0.3.beta.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.
- checksums.yaml +4 -4
- data/Gemfile +15 -3
- data/Gemfile.lock +444 -211
- data/Rakefile +36 -34
- data/bin/dpl +3 -1
- data/dpl.gemspec +25 -0
- data/lib/dpl/cli.rb +19 -14
- data/lib/dpl/ctx/bash.rb +18 -12
- data/lib/dpl/ctx/test.rb +21 -15
- data/lib/dpl/ctx.rb +2 -0
- data/lib/dpl/helper/assets.rb +4 -2
- data/lib/dpl/helper/cmd.rb +20 -18
- data/lib/dpl/helper/config_file.rb +5 -3
- data/lib/dpl/helper/cookbook_site_streaming_uploader.rb +249 -0
- data/lib/dpl/helper/env.rb +26 -22
- data/lib/dpl/helper/github.rb +2 -0
- data/lib/dpl/helper/interpolate.rb +8 -4
- data/lib/dpl/helper/memoize.rb +4 -1
- data/lib/dpl/helper/squiggle.rb +3 -1
- data/lib/dpl/helper/transliterate.rb +3 -1
- data/lib/dpl/helper/wrap.rb +3 -1
- data/lib/dpl/helper/zip.rb +3 -1
- data/lib/dpl/provider/dsl.rb +18 -4
- data/lib/dpl/provider/examples.rb +6 -2
- data/lib/dpl/provider/status.rb +26 -24
- data/lib/dpl/providers/anynines.rb +22 -20
- data/lib/dpl/providers/azure_web_apps.rb +21 -19
- data/lib/dpl/providers/bintray.rb +44 -37
- data/lib/dpl/providers/bluemixcloudfoundry.rb +38 -36
- data/lib/dpl/providers/boxfuse.rb +12 -10
- data/lib/dpl/providers/cargo.rb +7 -5
- data/lib/dpl/providers/chef_supermarket.rb +82 -80
- data/lib/dpl/providers/cloud66.rb +17 -15
- data/lib/dpl/providers/cloudfiles.rb +8 -6
- data/lib/dpl/providers/cloudformation.rb +191 -187
- data/lib/dpl/providers/cloudfoundry.rb +32 -30
- data/lib/dpl/providers/codedeploy.rb +35 -33
- data/lib/dpl/providers/convox.rb +32 -25
- data/lib/dpl/providers/datica.rb +30 -28
- data/lib/dpl/providers/ecr.rb +66 -64
- data/lib/dpl/providers/elasticbeanstalk.rb +14 -12
- data/lib/dpl/providers/engineyard.rb +60 -58
- data/lib/dpl/providers/firebase.rb +6 -4
- data/lib/dpl/providers/flynn.rb +8 -6
- data/lib/dpl/providers/gae.rb +28 -25
- data/lib/dpl/providers/gcs.rb +59 -57
- data/lib/dpl/providers/git_push.rb +199 -195
- data/lib/dpl/providers/gleis.rb +19 -17
- data/lib/dpl/providers/hackage.rb +15 -13
- data/lib/dpl/providers/hephy.rb +18 -16
- data/lib/dpl/providers/heroku/api.rb +72 -70
- data/lib/dpl/providers/heroku/git.rb +15 -13
- data/lib/dpl/providers/heroku.rb +40 -38
- data/lib/dpl/providers/lambda.rb +134 -134
- data/lib/dpl/providers/launchpad.rb +45 -43
- data/lib/dpl/providers/netlify.rb +7 -5
- data/lib/dpl/providers/npm.rb +61 -58
- data/lib/dpl/providers/nuget.rb +8 -6
- data/lib/dpl/providers/openshift.rb +8 -6
- data/lib/dpl/providers/opsworks.rb +23 -21
- data/lib/dpl/providers/pages/api.rb +14 -14
- data/lib/dpl/providers/pages/git.rb +53 -47
- data/lib/dpl/providers/pages.rb +3 -1
- data/lib/dpl/providers/puppetforge.rb +6 -4
- data/lib/dpl/providers/pypi.rb +55 -54
- data/lib/dpl/providers/releases.rb +30 -23
- data/lib/dpl/providers/rubygems.rb +35 -31
- data/lib/dpl/providers/s3.rb +148 -142
- data/lib/dpl/providers/scalingo.rb +18 -16
- data/lib/dpl/providers/script.rb +4 -2
- data/lib/dpl/providers/snap.rb +12 -9
- data/lib/dpl/providers/surge.rb +7 -5
- data/lib/dpl/providers/testfairy.rb +47 -43
- data/lib/dpl/providers/transifex.rb +20 -18
- data/lib/dpl/providers.rb +3 -1
- data/lib/dpl/string_ext.rb +3 -1
- data/lib/dpl/support/aws_sdk_patch.rb +4 -1
- data/lib/dpl/support/gems.rb +7 -3
- data/lib/dpl/support/gstore_patch.rb +3 -1
- data/lib/dpl/support/version.rb +13 -12
- data/lib/dpl/version.rb +3 -1
- data/lib/dpl.rb +2 -0
- data/status.json +237 -0
- metadata +32 -15
- /data/lib/dpl/providers/{packagecloud.rb → packagecloud.rb_} +0 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Stanislav Vitvitskiy
|
|
3
|
+
# Author:: Nuo Yan (nuo@chef.io)
|
|
4
|
+
# Author:: Christopher Walters (<cw@chef.io>)
|
|
5
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
|
6
|
+
# License:: Apache License, Version 2.0
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
# you may not use this file except in compliance with the License.
|
|
10
|
+
# You may obtain a copy of the License at
|
|
11
|
+
#
|
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
#
|
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
# See the License for the specific language governing permissions and
|
|
18
|
+
# limitations under the License.
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
autoload :URI, "uri"
|
|
22
|
+
module Net
|
|
23
|
+
autoload :HTTP, "net/http"
|
|
24
|
+
end
|
|
25
|
+
autoload :OpenSSL, "openssl"
|
|
26
|
+
module Mixlib
|
|
27
|
+
module Authentication
|
|
28
|
+
autoload :SignedHeaderAuth, "mixlib/authentication/signedheaderauth"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
require 'chef'
|
|
32
|
+
require "chef-utils/dist" unless defined?(ChefUtils::Dist)
|
|
33
|
+
class Chef
|
|
34
|
+
class Knife
|
|
35
|
+
module Core
|
|
36
|
+
# == Chef::Knife::Core::CookbookSiteStreamingUploader
|
|
37
|
+
# A streaming multipart HTTP upload implementation. Used to upload cookbooks
|
|
38
|
+
# (in tarball form) to https://supermarket.chef.io
|
|
39
|
+
#
|
|
40
|
+
# inspired by http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
|
|
41
|
+
class CookbookSiteStreamingUploader
|
|
42
|
+
|
|
43
|
+
DefaultHeaders = { "accept" => "application/json", "x-chef-version" => ::Chef::VERSION }.freeze # rubocop:disable Naming/ConstantName
|
|
44
|
+
|
|
45
|
+
class << self
|
|
46
|
+
|
|
47
|
+
def create_build_dir(cookbook)
|
|
48
|
+
tmp_cookbook_path = Tempfile.new("#{ChefUtils::Dist::Infra::SHORT}-#{cookbook.name}-build")
|
|
49
|
+
tmp_cookbook_path.close
|
|
50
|
+
tmp_cookbook_dir = tmp_cookbook_path.path
|
|
51
|
+
File.unlink(tmp_cookbook_dir)
|
|
52
|
+
FileUtils.mkdir_p(tmp_cookbook_dir)
|
|
53
|
+
Chef::Log.trace("Staging at #{tmp_cookbook_dir}")
|
|
54
|
+
checksums_to_on_disk_paths = cookbook.checksums
|
|
55
|
+
cookbook.each_file do |manifest_record|
|
|
56
|
+
path_in_cookbook = manifest_record[:path]
|
|
57
|
+
on_disk_path = checksums_to_on_disk_paths[manifest_record[:checksum]]
|
|
58
|
+
dest = File.join(tmp_cookbook_dir, cookbook.name.to_s, path_in_cookbook)
|
|
59
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
|
60
|
+
Chef::Log.trace("Staging #{on_disk_path} to #{dest}")
|
|
61
|
+
FileUtils.cp(on_disk_path, dest)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# First, generate metadata
|
|
65
|
+
Chef::Log.trace("Generating metadata")
|
|
66
|
+
kcm = Chef::Knife::CookbookMetadata.new
|
|
67
|
+
kcm.config[:cookbook_path] = [ tmp_cookbook_dir ]
|
|
68
|
+
kcm.name_args = [ cookbook.name.to_s ]
|
|
69
|
+
kcm.run
|
|
70
|
+
|
|
71
|
+
tmp_cookbook_dir
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def post(to_url, user_id, secret_key_filename, params = {}, headers = {})
|
|
75
|
+
make_request(:post, to_url, user_id, secret_key_filename, params, headers)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def put(to_url, user_id, secret_key_filename, params = {}, headers = {})
|
|
79
|
+
make_request(:put, to_url, user_id, secret_key_filename, params, headers)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def make_request(http_verb, to_url, user_id, secret_key_filename, params = {}, headers = {})
|
|
83
|
+
boundary = "----RubyMultipartClient" + rand(1000000).to_s + "ZZZZZ"
|
|
84
|
+
parts = []
|
|
85
|
+
content_file = nil
|
|
86
|
+
|
|
87
|
+
secret_key = OpenSSL::PKey::RSA.new(File.read(secret_key_filename))
|
|
88
|
+
|
|
89
|
+
unless params.nil? || params.empty?
|
|
90
|
+
params.each do |key, value|
|
|
91
|
+
if value.is_a?(File)
|
|
92
|
+
content_file = value
|
|
93
|
+
filepath = value.path
|
|
94
|
+
filename = File.basename(filepath)
|
|
95
|
+
parts << StringPart.new( "--" + boundary + "\r\n" +
|
|
96
|
+
"Content-Disposition: form-data; name=\"" + key.to_s + "\"; filename=\"" + filename + "\"\r\n" +
|
|
97
|
+
"Content-Type: application/octet-stream\r\n\r\n")
|
|
98
|
+
parts << StreamPart.new(value, File.size(filepath))
|
|
99
|
+
parts << StringPart.new("\r\n")
|
|
100
|
+
else
|
|
101
|
+
parts << StringPart.new( "--" + boundary + "\r\n" +
|
|
102
|
+
"Content-Disposition: form-data; name=\"" + key.to_s + "\"\r\n\r\n")
|
|
103
|
+
parts << StringPart.new(value.to_s + "\r\n")
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
parts << StringPart.new("--" + boundary + "--\r\n")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
body_stream = MultipartStream.new(parts)
|
|
110
|
+
|
|
111
|
+
timestamp = Time.now.utc.iso8601
|
|
112
|
+
|
|
113
|
+
url = URI.parse(to_url)
|
|
114
|
+
|
|
115
|
+
Chef::Log.logger.debug("Signing: method: #{http_verb}, url: #{url}, file: #{content_file}, User-id: #{user_id}, Timestamp: #{timestamp}")
|
|
116
|
+
|
|
117
|
+
# We use the body for signing the request if the file parameter
|
|
118
|
+
# wasn't a valid file or wasn't included. Extract the body (with
|
|
119
|
+
# multi-part delimiters intact) to sign the request.
|
|
120
|
+
# TODO: tim: 2009-12-28: It'd be nice to remove this special case, and
|
|
121
|
+
# always hash the entire request body. In the file case it would just be
|
|
122
|
+
# expanded multipart text - the entire body of the POST.
|
|
123
|
+
content_body = parts.inject("") { |result, part| result + part.read(0, part.size) }
|
|
124
|
+
content_file.rewind if content_file # we consumed the file for the above operation, so rewind it.
|
|
125
|
+
|
|
126
|
+
signing_options = {
|
|
127
|
+
http_method: http_verb,
|
|
128
|
+
path: url.path,
|
|
129
|
+
user_id: user_id,
|
|
130
|
+
timestamp: timestamp }
|
|
131
|
+
(content_file && signing_options[:file] = content_file) || (signing_options[:body] = (content_body || ""))
|
|
132
|
+
|
|
133
|
+
headers.merge!(Mixlib::Authentication::SignedHeaderAuth.signing_object(signing_options).sign(secret_key))
|
|
134
|
+
|
|
135
|
+
content_file.rewind if content_file
|
|
136
|
+
|
|
137
|
+
# net/http doesn't like symbols for header keys, so we'll to_s each one just in case
|
|
138
|
+
headers = DefaultHeaders.merge(Hash[*headers.map { |k, v| [k.to_s, v] }.flatten])
|
|
139
|
+
|
|
140
|
+
req = case http_verb
|
|
141
|
+
when :put
|
|
142
|
+
Net::HTTP::Put.new(url.path, headers)
|
|
143
|
+
when :post
|
|
144
|
+
Net::HTTP::Post.new(url.path, headers)
|
|
145
|
+
end
|
|
146
|
+
req.content_length = body_stream.size
|
|
147
|
+
req.content_type = "multipart/form-data; boundary=" + boundary unless parts.empty?
|
|
148
|
+
req.body_stream = body_stream
|
|
149
|
+
|
|
150
|
+
http = Chef::HTTP::BasicClient.new(url).http_client
|
|
151
|
+
res = http.request(req)
|
|
152
|
+
|
|
153
|
+
# alias status to code and to_s to body for test purposes
|
|
154
|
+
# TODO: stop the following madness!
|
|
155
|
+
class << res
|
|
156
|
+
alias :to_s :body
|
|
157
|
+
|
|
158
|
+
# BUG this makes the response compatible with what response_steps expects to test headers (response.headers[] -> response[])
|
|
159
|
+
def headers # rubocop:disable Lint/NestedMethodDefinition
|
|
160
|
+
self
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def status # rubocop:disable Lint/NestedMethodDefinition
|
|
164
|
+
code.to_i
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
res
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
class StreamPart
|
|
173
|
+
def initialize(stream, size)
|
|
174
|
+
@stream, @size = stream, size
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def size
|
|
178
|
+
@size
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# read the specified amount from the stream
|
|
182
|
+
def read(offset, how_much)
|
|
183
|
+
@stream.read(how_much)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
class StringPart
|
|
188
|
+
def initialize(str)
|
|
189
|
+
@str = str
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def size
|
|
193
|
+
@str.length
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# read the specified amount from the string starting at the offset
|
|
197
|
+
def read(offset, how_much)
|
|
198
|
+
@str[offset, how_much]
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
class MultipartStream
|
|
203
|
+
def initialize(parts)
|
|
204
|
+
@parts = parts
|
|
205
|
+
@part_no = 0
|
|
206
|
+
@part_offset = 0
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def size
|
|
210
|
+
@parts.inject(0) { |size, part| size + part.size }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def read(how_much, dst_buf = nil)
|
|
214
|
+
if @part_no >= @parts.size
|
|
215
|
+
dst_buf.replace("") if dst_buf
|
|
216
|
+
return dst_buf
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
how_much_current_part = @parts[@part_no].size - @part_offset
|
|
220
|
+
|
|
221
|
+
how_much_current_part = if how_much_current_part > how_much
|
|
222
|
+
how_much
|
|
223
|
+
else
|
|
224
|
+
how_much_current_part
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
how_much_next_part = how_much - how_much_current_part
|
|
228
|
+
|
|
229
|
+
current_part = @parts[@part_no].read(@part_offset, how_much_current_part)
|
|
230
|
+
|
|
231
|
+
# recurse into the next part if the current one was not large enough
|
|
232
|
+
if how_much_next_part > 0
|
|
233
|
+
@part_no += 1
|
|
234
|
+
@part_offset = 0
|
|
235
|
+
next_part = read(how_much_next_part)
|
|
236
|
+
result = current_part + (next_part || "")
|
|
237
|
+
else
|
|
238
|
+
@part_offset += how_much_current_part
|
|
239
|
+
result = current_part
|
|
240
|
+
end
|
|
241
|
+
dst_buf ? dst_buf.replace(result || "") : result
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
data/lib/dpl/helper/env.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'dpl/helper/memoize'
|
|
2
4
|
|
|
3
5
|
module Dpl
|
|
@@ -21,8 +23,8 @@ module Dpl
|
|
|
21
23
|
def env(cmd)
|
|
22
24
|
@cmd = cmd
|
|
23
25
|
env = @env.select { |key, _| keys.include?(key) }
|
|
24
|
-
env = env.
|
|
25
|
-
env.
|
|
26
|
+
env = env.transform_keys { |key| unprefix(key).downcase.to_sym }
|
|
27
|
+
env.transform_keys { |key| dealias(key) }
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def description(cmd)
|
|
@@ -33,39 +35,41 @@ module Dpl
|
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
def example(cmd)
|
|
36
|
-
return unless opt = cmd.opts.detect { |
|
|
37
|
-
|
|
38
|
-
env
|
|
38
|
+
return unless opt = cmd.opts.detect { |option| option.secret? }
|
|
39
|
+
|
|
40
|
+
env = strs.map { |str| "`#{str}_#{opt.name.upcase}=<#{opt.name}>`" }
|
|
41
|
+
env += strs.map { |str| "`#{str}#{opt.name.upcase}=<#{opt.name}>`" } if opts[:allow_skip_underscore]
|
|
39
42
|
"E.g. the option `--#{opt.name}` can be given as #{sentence(env)}."
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
def sentence(strs)
|
|
43
46
|
return strs.join if strs.size == 1
|
|
47
|
+
|
|
44
48
|
[strs[0..-2].join(', '), strs[-1]].join(' or ')
|
|
45
49
|
end
|
|
46
50
|
|
|
47
51
|
private
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
def dealias(key)
|
|
54
|
+
opt = cmd.opts.detect { |option| option.aliases.include?(key) }
|
|
55
|
+
opt ? opt.name : key
|
|
56
|
+
end
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
def unprefix(key)
|
|
59
|
+
strs.inject(key) { |key, str| key.sub(/^#{str}_?/, '') }
|
|
60
|
+
end
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
def keys
|
|
63
|
+
keys = cmd.opts.map(&:name) + cmd.opts.map(&:aliases).flatten
|
|
64
|
+
strs.map { |str| keys.map { |key| keys_for(str, key) } }.flatten
|
|
65
|
+
end
|
|
66
|
+
memoize :keys
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
def keys_for(str, key)
|
|
69
|
+
keys = [["#{str}_", key.upcase].join]
|
|
70
|
+
keys << [str, key.upcase].join if opts[:allow_skip_underscore]
|
|
71
|
+
keys
|
|
72
|
+
end
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
# should this sit in Cl?
|
data/lib/dpl/helper/github.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'uri'
|
|
2
4
|
|
|
3
5
|
module Dpl
|
|
@@ -67,15 +69,16 @@ module Dpl
|
|
|
67
69
|
# length of the original string.
|
|
68
70
|
def obfuscate(str, opts = {})
|
|
69
71
|
return str if opts[:secure] || !str.blacklisted?
|
|
72
|
+
|
|
70
73
|
keep = (str.length / (4.0 + str.length / 5).round).round
|
|
71
|
-
keep = 1 if keep
|
|
74
|
+
keep = 1 if keep.zero?
|
|
72
75
|
str[0, keep] + '*' * (20 - keep)
|
|
73
76
|
end
|
|
74
77
|
|
|
75
78
|
class Interpolator < Struct.new(:str, :obj, :args, :opts)
|
|
76
79
|
include Interpolate
|
|
77
80
|
|
|
78
|
-
MODIFIER = %i
|
|
81
|
+
MODIFIER = %i[obfuscate escape quote].freeze
|
|
79
82
|
PATTERN = /%\{(\$?[\w]+)\}/
|
|
80
83
|
ENV_VAR = /^\$[A-Z_]+$/
|
|
81
84
|
UPCASE = /^[A-Z_]+$/
|
|
@@ -93,7 +96,7 @@ module Dpl
|
|
|
93
96
|
@blacklist_result = false
|
|
94
97
|
str = str.to_s.gsub(PATTERN) do
|
|
95
98
|
@blacklist_result = true
|
|
96
|
-
normalize(lookup(
|
|
99
|
+
normalize(lookup(::Regexp.last_match(1).to_sym))
|
|
97
100
|
end
|
|
98
101
|
@blacklist_result || (args.is_a?(Array) && args.any? { |arg| arg.is_a?(String) && arg.blacklisted? }) ? str.blacklist : str
|
|
99
102
|
end
|
|
@@ -108,6 +111,7 @@ module Dpl
|
|
|
108
111
|
|
|
109
112
|
def secrets(str)
|
|
110
113
|
return [] unless str.is_a?(String) && str.blacklisted?
|
|
114
|
+
|
|
111
115
|
opts = obj.class.opts.select(&:secret?)
|
|
112
116
|
secrets = opts.map { |opt| obj.opts[opt.name] }.compact
|
|
113
117
|
secrets.select { |secret| str.include?(secret) }
|
|
@@ -117,7 +121,7 @@ module Dpl
|
|
|
117
121
|
obj.is_a?(Array) ? obj.join(' ') : obj.to_s
|
|
118
122
|
end
|
|
119
123
|
|
|
120
|
-
def lookup(key)
|
|
124
|
+
def lookup(key)
|
|
121
125
|
if vars? && !var?(key)
|
|
122
126
|
UNKNOWN % key
|
|
123
127
|
elsif mod = modifier(key)
|
data/lib/dpl/helper/memoize.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Memoize
|
|
2
4
|
class ArgsError < StandardError; end
|
|
3
5
|
|
|
@@ -6,8 +8,9 @@ module Memoize
|
|
|
6
8
|
ivar = :"@#{name.to_s.sub('?', '_predicate')}"
|
|
7
9
|
prepend Module.new {
|
|
8
10
|
define_method(name) do |*args|
|
|
9
|
-
raise ArgsError
|
|
11
|
+
raise ArgsError, 'cannot pass arguments to memoized method %p' % name unless args.empty?
|
|
10
12
|
return instance_variable_get(ivar) if instance_variable_defined?(ivar)
|
|
13
|
+
|
|
11
14
|
instance_variable_set(ivar, super())
|
|
12
15
|
end
|
|
13
16
|
}
|
data/lib/dpl/helper/squiggle.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Beloved squiggly heredocs did not exist in Ruby 2.1, which we still want to
|
|
2
4
|
# support, so let's give kudos with a method `sq`.
|
|
3
5
|
module Squiggle
|
|
@@ -16,7 +18,7 @@ module Squiggle
|
|
|
16
18
|
# while this line sits on the same level as the first line.
|
|
17
19
|
# str
|
|
18
20
|
def sq(str)
|
|
19
|
-
width = str =~ /( *)\S/ &&
|
|
21
|
+
width = str =~ /( *)\S/ && ::Regexp.last_match(1).size
|
|
20
22
|
str.lines.map { |line| line.gsub(/^ {#{width}}/, '') }.join
|
|
21
23
|
end
|
|
22
24
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Dpl
|
|
2
4
|
module Transliterate
|
|
3
|
-
APPROXIMATIONS = YAML.load(File.read(File.expand_path('
|
|
5
|
+
APPROXIMATIONS = YAML.load(File.read(File.expand_path('../../../config/transliterate.yml', __dir__)))
|
|
4
6
|
|
|
5
7
|
def transliterate(string, replacement = '.')
|
|
6
8
|
string.gsub(/[^\x00-\x7f]/u) do |char|
|
data/lib/dpl/helper/wrap.rb
CHANGED
data/lib/dpl/helper/zip.rb
CHANGED
data/lib/dpl/provider/dsl.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'dpl/helper/squiggle'
|
|
2
4
|
require 'dpl/helper/wrap'
|
|
3
5
|
require 'dpl/provider/status'
|
|
4
6
|
|
|
5
|
-
# TODO figure out how to allow adding domain specific behavior like this to Cl
|
|
7
|
+
# TODO: figure out how to allow adding domain specific behavior like this to Cl
|
|
6
8
|
class Cl::Opt
|
|
7
9
|
OPTS << :interpolate
|
|
8
10
|
|
|
@@ -55,9 +57,10 @@ module Dpl
|
|
|
55
57
|
def vars(*vars)
|
|
56
58
|
return self.vars.concat(vars) if vars.any?
|
|
57
59
|
return @vars if instance_variable_defined?(:@vars)
|
|
60
|
+
|
|
58
61
|
vars = superclass.respond_to?(:vars) ? superclass.vars : []
|
|
59
|
-
reject = %i
|
|
60
|
-
opts = reject.inject(self.opts) { |
|
|
62
|
+
reject = %i[flag array internal interpolate secret]
|
|
63
|
+
opts = reject.inject(self.opts) { |options, attr| options.reject(&:"#{attr}?") }
|
|
61
64
|
@vars = vars.dup.concat(opts.map(&:name)).uniq.sort - [:strategy]
|
|
62
65
|
end
|
|
63
66
|
|
|
@@ -108,6 +111,7 @@ module Dpl
|
|
|
108
111
|
|
|
109
112
|
def runtimes(name = nil, requirements = nil)
|
|
110
113
|
return @runtimes ||= [] unless name
|
|
114
|
+
|
|
111
115
|
runtimes << [name, requirements]
|
|
112
116
|
end
|
|
113
117
|
|
|
@@ -121,6 +125,7 @@ module Dpl
|
|
|
121
125
|
# @return Previously declared apt packages if no arguments were given.
|
|
122
126
|
def apt(package = nil, cmd = nil)
|
|
123
127
|
return apt << [package, cmd].compact if package
|
|
128
|
+
|
|
124
129
|
@apt ||= self == Provider ? [] : superclass.apt.dup
|
|
125
130
|
end
|
|
126
131
|
|
|
@@ -144,6 +149,7 @@ module Dpl
|
|
|
144
149
|
# @return Previously declared gems if no arguments were given
|
|
145
150
|
def gem(name = nil, version = nil, opts = {})
|
|
146
151
|
return gem << [name, version, opts] if name
|
|
152
|
+
|
|
147
153
|
@gem ||= self == Provider ? [] : superclass.gem.dup
|
|
148
154
|
end
|
|
149
155
|
|
|
@@ -161,6 +167,7 @@ module Dpl
|
|
|
161
167
|
# @return Previously declared NPM packages if no arguments are given.
|
|
162
168
|
def npm(package = nil, cmd = nil)
|
|
163
169
|
return npm << [package, cmd].compact if package
|
|
170
|
+
|
|
164
171
|
@npm ||= self == Provider ? [] : superclass.npm.dup
|
|
165
172
|
end
|
|
166
173
|
|
|
@@ -181,6 +188,7 @@ module Dpl
|
|
|
181
188
|
# @return Previously declared Python packages if no arguments are given.
|
|
182
189
|
def pip(package = nil, cmd = nil, version = nil)
|
|
183
190
|
return pip << [package, cmd, version].compact if package
|
|
191
|
+
|
|
184
192
|
@pip ||= self == Provider ? [] : superclass.pip.dup
|
|
185
193
|
end
|
|
186
194
|
|
|
@@ -223,6 +231,7 @@ module Dpl
|
|
|
223
231
|
# commands.
|
|
224
232
|
def cmds(cmds = nil)
|
|
225
233
|
return self.cmds.update(cmds) if cmds
|
|
234
|
+
|
|
226
235
|
@cmds ||= self == Provider ? {} : superclass.cmds.dup
|
|
227
236
|
end
|
|
228
237
|
|
|
@@ -265,6 +274,7 @@ module Dpl
|
|
|
265
274
|
# commands.
|
|
266
275
|
def errs(errs = nil)
|
|
267
276
|
return self.errs.update(errs) if errs
|
|
277
|
+
|
|
268
278
|
@errs ||= self == Provider ? {} : superclass.errs.dup
|
|
269
279
|
end
|
|
270
280
|
|
|
@@ -327,11 +337,13 @@ module Dpl
|
|
|
327
337
|
# @return Previously declared msgs if no argument is given.
|
|
328
338
|
def msgs(msgs = nil)
|
|
329
339
|
return self.msgs.update(msgs) if msgs
|
|
340
|
+
|
|
330
341
|
@msgs ||= self == Provider ? {} : superclass.msgs.dup
|
|
331
342
|
end
|
|
332
343
|
|
|
333
344
|
def strs(strs = nil)
|
|
334
345
|
return self.strs.update(strs) if strs
|
|
346
|
+
|
|
335
347
|
@strs ||= self == Provider ? {} : superclass.strs.dup
|
|
336
348
|
end
|
|
337
349
|
|
|
@@ -342,6 +354,7 @@ module Dpl
|
|
|
342
354
|
# @return Previously declared artifacts to keep if no argument is given.
|
|
343
355
|
def keep(*paths)
|
|
344
356
|
return keep.concat(paths) if paths.any?
|
|
357
|
+
|
|
345
358
|
@keep ||= self == Provider ? [] : superclass.keep.dup
|
|
346
359
|
end
|
|
347
360
|
|
|
@@ -364,6 +377,7 @@ module Dpl
|
|
|
364
377
|
# @return Previously declared features needed if no argument is given.
|
|
365
378
|
def needs(*features)
|
|
366
379
|
return needs.concat(features) if features.any?
|
|
380
|
+
|
|
367
381
|
@needs ||= self == Provider ? [] : superclass.needs.dup
|
|
368
382
|
end
|
|
369
383
|
|
|
@@ -380,7 +394,7 @@ module Dpl
|
|
|
380
394
|
def user_agent(*strs)
|
|
381
395
|
strs.unshift "dpl/#{Dpl::VERSION}"
|
|
382
396
|
strs.unshift 'travis/0.1.0' if ENV['TRAVIS']
|
|
383
|
-
strs = strs.flat_map { |e| Hash
|
|
397
|
+
strs = strs.flat_map { |e| e.is_a?(Hash) ? e.map { |k, v| "#{k}/#{v}" } : e }
|
|
384
398
|
strs.join(' ').gsub(/\s+/, ' ').strip
|
|
385
399
|
end
|
|
386
400
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Dpl
|
|
2
4
|
class Examples < Struct.new(:const)
|
|
3
5
|
def cmds
|
|
@@ -58,12 +60,13 @@ module Dpl
|
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
def without_required(opts)
|
|
61
|
-
opts
|
|
63
|
+
opts -= const.required.flatten.map { |key| const.opts[key] }
|
|
62
64
|
opts - required_opts.map(&:opts)
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
def example(opts)
|
|
66
68
|
return unless opts.any?
|
|
69
|
+
|
|
67
70
|
opts = required_opts.concat(opts).uniq.compact
|
|
68
71
|
Example.new(const, opts)
|
|
69
72
|
end
|
|
@@ -117,7 +120,8 @@ module Dpl
|
|
|
117
120
|
return if opt.type == :flag
|
|
118
121
|
return 1 if opt.type == :integer
|
|
119
122
|
return opt.enum.first if opt.enum?
|
|
120
|
-
|
|
123
|
+
|
|
124
|
+
str = opt.strs.detect { |str| str =~ /^--#{opt.name} (.*)$/ } && ::Regexp.last_match(1)
|
|
121
125
|
str ? str.downcase : 'str'
|
|
122
126
|
end
|
|
123
127
|
|
data/lib/dpl/provider/status.rb
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Dpl
|
|
2
4
|
class Provider < Cl::Cmd
|
|
3
5
|
class Status < Struct.new(:provider, :status, :info)
|
|
4
|
-
STATUS = %i
|
|
6
|
+
STATUS = %i[dev alpha beta stable deprecated].freeze
|
|
5
7
|
|
|
6
8
|
MSG = {
|
|
7
|
-
dev:
|
|
8
|
-
alpha:
|
|
9
|
-
beta:
|
|
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**',
|
|
10
12
|
deprecated: 'Support for deployments to %s is *deprecated**',
|
|
11
13
|
pre_stable: 'Please see [Maturity Levels](%s) for details.'
|
|
12
|
-
}
|
|
14
|
+
}.freeze
|
|
13
15
|
|
|
14
16
|
URL = 'https://github.com/travis-ci/dpl/#maturity-levels'
|
|
15
17
|
|
|
@@ -23,7 +25,7 @@ module Dpl
|
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def msg
|
|
26
|
-
msg =
|
|
28
|
+
msg = (MSG[status] % name).to_s
|
|
27
29
|
msg << "(#{info})" if info
|
|
28
30
|
msg << ". #{MSG[:pre_stable] % URL}" if pre_stable?
|
|
29
31
|
msg
|
|
@@ -31,29 +33,29 @@ module Dpl
|
|
|
31
33
|
|
|
32
34
|
private
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
def name
|
|
37
|
+
provider.full_name
|
|
38
|
+
end
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
def pre_stable?
|
|
41
|
+
STATUS.index(status) < STATUS.index(:stable)
|
|
42
|
+
end
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
def stable?
|
|
45
|
+
status == :stable
|
|
46
|
+
end
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
def deprecated?
|
|
49
|
+
status == :deprecated
|
|
50
|
+
end
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
def known?(status)
|
|
53
|
+
STATUS.include?(status)
|
|
54
|
+
end
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
def unknown!(status)
|
|
57
|
+
raise "Unknown status: #{status.inspect}. Known statuses are: #{STATUS.map(&:inspect).join(', ')}"
|
|
58
|
+
end
|
|
57
59
|
end
|
|
58
60
|
end
|
|
59
61
|
end
|