dpl-thib 1.10.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 +7 -0
- data/.coveralls.yml +1 -0
- data/.github/CONTRIBUTING.md +173 -0
- data/.github/stale.yml +53 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.travis.yml +55 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/LICENSE +22 -0
- data/README.md +968 -0
- data/Rakefile +208 -0
- data/bin/dpl +5 -0
- data/dpl-anynines.gemspec +3 -0
- data/dpl-atlas.gemspec +3 -0
- data/dpl-azure_webapps.gemspec +3 -0
- data/dpl-bintray.gemspec +3 -0
- data/dpl-bitballoon.gemspec +3 -0
- data/dpl-bluemix_cloud_foundry.gemspec +3 -0
- data/dpl-boxfuse.gemspec +3 -0
- data/dpl-cargo.gemspec +3 -0
- data/dpl-catalyze.gemspec +3 -0
- data/dpl-chef_supermarket.gemspec +10 -0
- data/dpl-cloud66.gemspec +3 -0
- data/dpl-cloud_files.gemspec +3 -0
- data/dpl-cloud_foundry.gemspec +3 -0
- data/dpl-code_deploy.gemspec +3 -0
- data/dpl-deis.gemspec +3 -0
- data/dpl-elastic_beanstalk.gemspec +3 -0
- data/dpl-engine_yard.gemspec +3 -0
- data/dpl-firebase.gemspec +3 -0
- data/dpl-gae.gemspec +3 -0
- data/dpl-gcs.gemspec +3 -0
- data/dpl-hackage.gemspec +3 -0
- data/dpl-hephy.gemspec +3 -0
- data/dpl-heroku.gemspec +3 -0
- data/dpl-lambda.gemspec +3 -0
- data/dpl-launchpad.gemspec +3 -0
- data/dpl-npm.gemspec +3 -0
- data/dpl-openshift.gemspec +3 -0
- data/dpl-ops_works.gemspec +3 -0
- data/dpl-packagecloud.gemspec +3 -0
- data/dpl-pages.gemspec +3 -0
- data/dpl-puppet_forge.gemspec +3 -0
- data/dpl-pypi.gemspec +3 -0
- data/dpl-releases.gemspec +3 -0
- data/dpl-rubygems.gemspec +3 -0
- data/dpl-s3.gemspec +3 -0
- data/dpl-scalingo.gemspec +3 -0
- data/dpl-script.gemspec +3 -0
- data/dpl-snap.gemspec +3 -0
- data/dpl-surge.gemspec +3 -0
- data/dpl-testfairy.gemspec +3 -0
- data/dpl-transifex.gemspec +3 -0
- data/dpl.gemspec +3 -0
- data/gemspec_helper.rb +51 -0
- data/lib/dpl/cli.rb +66 -0
- data/lib/dpl/error.rb +3 -0
- data/lib/dpl/provider.rb +308 -0
- data/lib/dpl/version.rb +3 -0
- data/notes/engine_yard.md +1 -0
- data/notes/heroku.md +3 -0
- data/spec/cli_spec.rb +36 -0
- data/spec/provider_spec.rb +191 -0
- data/spec/spec_helper.rb +20 -0
- metadata +237 -0
data/lib/dpl/cli.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'dpl/error'
|
2
|
+
require 'dpl/provider'
|
3
|
+
|
4
|
+
module DPL
|
5
|
+
class CLI
|
6
|
+
def self.run(*args)
|
7
|
+
new(args).run
|
8
|
+
end
|
9
|
+
|
10
|
+
OPTION_PATTERN = /\A--([a-z][a-z_\-]*)(?:=(.+))?\z/
|
11
|
+
attr_accessor :options, :fold_count
|
12
|
+
|
13
|
+
def initialize(*args)
|
14
|
+
options = {}
|
15
|
+
args.flatten.each do |arg|
|
16
|
+
next options.update(arg) if arg.is_a? Hash
|
17
|
+
die("invalid option %p" % arg) unless match = OPTION_PATTERN.match(arg)
|
18
|
+
key = match[1].tr('-', '_').to_sym
|
19
|
+
if options.include? key
|
20
|
+
options[key] = Array(options[key]) << match[2]
|
21
|
+
else
|
22
|
+
options[key] = match[2] || true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
self.fold_count = 0
|
27
|
+
self.options = default_options.merge(options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
provider = Provider.new(self, options)
|
32
|
+
provider.deploy
|
33
|
+
rescue Error => error
|
34
|
+
options[:debug] ? raise(error) : die(error.message)
|
35
|
+
end
|
36
|
+
|
37
|
+
def fold(message)
|
38
|
+
self.fold_count += 1
|
39
|
+
print "travis_fold:start:dpl.#{fold_count}\r" if options[:fold]
|
40
|
+
puts "\e[33m#{message}\e[0m"
|
41
|
+
yield
|
42
|
+
ensure
|
43
|
+
print "\ntravis_fold:end:dpl.#{fold_count}\r" if options[:fold]
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_options
|
47
|
+
{
|
48
|
+
:app => File.basename(Dir.pwd),
|
49
|
+
:key_name => %x[hostname].strip
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def shell(command)
|
54
|
+
system(command)
|
55
|
+
end
|
56
|
+
|
57
|
+
def die(message)
|
58
|
+
$stderr.puts(message)
|
59
|
+
exit 1
|
60
|
+
end
|
61
|
+
|
62
|
+
def env
|
63
|
+
ENV
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/dpl/error.rb
ADDED
data/lib/dpl/provider.rb
ADDED
@@ -0,0 +1,308 @@
|
|
1
|
+
require 'dpl/error'
|
2
|
+
require 'dpl/version'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module DPL
|
6
|
+
class Provider
|
7
|
+
include FileUtils
|
8
|
+
|
9
|
+
# map of DPL provider class name constants to their corresponding
|
10
|
+
# file names. There is no simple rule to map them automatically
|
11
|
+
# (camel-cases, snake-cases, call-caps, etc.), so we need an explicit
|
12
|
+
# map.
|
13
|
+
GEM_NAME_OF = {
|
14
|
+
'Anynines' => 'anynines',
|
15
|
+
'Appfog' => 'appfog',
|
16
|
+
'Atlas' => 'atlas',
|
17
|
+
'AzureWebApps' => 'azure_webapps',
|
18
|
+
'Bintray' => 'bintray',
|
19
|
+
'BitBalloon' => 'bitballoon',
|
20
|
+
'BluemixCloudFoundry' => 'bluemix_cloud_foundry',
|
21
|
+
'Boxfuse' => 'boxfuse',
|
22
|
+
'Catalyze' => 'catalyze',
|
23
|
+
'ChefSupermarket' => 'chef_supermarket',
|
24
|
+
'Cloud66' => 'cloud66',
|
25
|
+
'CloudFiles' => 'cloud_files',
|
26
|
+
'CloudFoundry' => 'cloud_foundry',
|
27
|
+
'CodeDeploy' => 'code_deploy',
|
28
|
+
'Cargo' => 'cargo',
|
29
|
+
'Deis' => 'deis',
|
30
|
+
'ElasticBeanstalk' => 'elastic_beanstalk',
|
31
|
+
'EngineYard' => 'engine_yard',
|
32
|
+
'Firebase' => 'firebase',
|
33
|
+
'GAE' => 'gae',
|
34
|
+
'GCS' => 'gcs',
|
35
|
+
'Hackage' => 'hackage',
|
36
|
+
'Hephy' => 'hephy',
|
37
|
+
'Heroku' => 'heroku',
|
38
|
+
'Lambda' => 'lambda',
|
39
|
+
'Launchpad' => 'launchpad',
|
40
|
+
'Nodejitsu' => 'nodejitsu',
|
41
|
+
'NPM' => 'npm',
|
42
|
+
'Openshift' => 'openshift',
|
43
|
+
'OpsWorks' => 'ops_works',
|
44
|
+
'Packagecloud' => 'packagecloud',
|
45
|
+
'Pages' => 'pages',
|
46
|
+
'PuppetForge' => 'puppet_forge',
|
47
|
+
'PyPI' => 'pypi',
|
48
|
+
'Releases' => 'releases',
|
49
|
+
'RubyGems' => 'rubygems',
|
50
|
+
'S3' => 's3',
|
51
|
+
'Scalingo' => 'scalingo',
|
52
|
+
'Script' => 'script',
|
53
|
+
'Snap' => 'snap',
|
54
|
+
'Surge' => 'surge',
|
55
|
+
'TestFairy' => 'testfairy',
|
56
|
+
'Transifex' => 'transifex',
|
57
|
+
}
|
58
|
+
|
59
|
+
def self.new(context, options)
|
60
|
+
return super if self < Provider
|
61
|
+
|
62
|
+
# when requiring the file corresponding to the provider name
|
63
|
+
# given in the options, the general strategy is to normalize
|
64
|
+
# the option to lower-case alphanumeric, then
|
65
|
+
# use that key to find the file name using the GEM_NAME_OF map.
|
66
|
+
|
67
|
+
context.fold("Installing deploy dependencies") do
|
68
|
+
begin
|
69
|
+
opt_lower = super.option(:provider).to_s.downcase
|
70
|
+
opt = opt_lower.gsub(/[^a-z0-9]/, '')
|
71
|
+
class_name = class_of(opt)
|
72
|
+
raise Error, "could not find provider %p" % opt unless class_name
|
73
|
+
require "dpl/provider/#{GEM_NAME_OF[class_name]}"
|
74
|
+
provider = const_get(class_name).new(context, options)
|
75
|
+
rescue NameError, LoadError => e
|
76
|
+
if /uninitialized constant DPL::Provider::(?<provider_wanted>\S+)/ =~ e.message
|
77
|
+
provider_gem_name = GEM_NAME_OF[provider_wanted]
|
78
|
+
elsif %r(cannot load such file -- dpl/provider/(?<provider_file_name>\S+)) =~ e.message
|
79
|
+
provider_gem_name = GEM_NAME_OF[class_name]
|
80
|
+
else
|
81
|
+
# don't know what to do with this error
|
82
|
+
raise e
|
83
|
+
end
|
84
|
+
install_cmd = "gem install dpl-#{provider_gem_name || opt} -v #{ENV['DPL_VERSION'] || DPL::VERSION}"
|
85
|
+
|
86
|
+
if File.exist?(local_gem = File.join(Dir.pwd, "dpl-#{GEM_NAME_OF[provider_gem_name] || opt_lower}-#{ENV['DPL_VERSION'] || DPL::VERSION}.gem"))
|
87
|
+
install_cmd = "gem install #{local_gem}"
|
88
|
+
end
|
89
|
+
|
90
|
+
context.shell(install_cmd)
|
91
|
+
Gem.clear_paths
|
92
|
+
|
93
|
+
require "dpl/provider/#{GEM_NAME_OF[class_name]}"
|
94
|
+
provider = const_get(class_name).new(context, options)
|
95
|
+
rescue DPL::Error
|
96
|
+
if opt_lower
|
97
|
+
provider = const_get(opt.capitalize).new(context, options)
|
98
|
+
else
|
99
|
+
raise Error, 'missing provider'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
if options[:no_deploy]
|
104
|
+
def provider.deploy; end
|
105
|
+
else
|
106
|
+
provider.install_deploy_dependencies if provider.respond_to? :install_deploy_dependencies
|
107
|
+
end
|
108
|
+
|
109
|
+
provider
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.experimental(name)
|
114
|
+
puts "", "!!! #{name} support is experimental !!!", ""
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.deprecated(*lines)
|
118
|
+
puts ''
|
119
|
+
lines.each do |line|
|
120
|
+
puts "\e[31;1m#{line}\e[0m"
|
121
|
+
end
|
122
|
+
puts ''
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.context
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.shell(command, options = {})
|
130
|
+
system(command)
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.apt_get(name, command = name)
|
134
|
+
context.shell("sudo apt-get -qq install #{name}", retry: true) if `which #{command}`.chop.empty?
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.pip(name, command = name, version = nil)
|
138
|
+
if version
|
139
|
+
puts "pip install --user #{name}==#{version}"
|
140
|
+
context.shell("pip uninstall --user -y #{name}") unless `which #{command}`.chop.empty?
|
141
|
+
context.shell("pip install --user #{name}==#{version}", retry: true)
|
142
|
+
else
|
143
|
+
puts "pip install --user #{name}"
|
144
|
+
context.shell("pip install --user #{name}", retry: true) if `which #{command}`.chop.empty?
|
145
|
+
end
|
146
|
+
context.shell("export PATH=$PATH:$HOME/.local/bin")
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.npm_g(name, command = name)
|
150
|
+
context.shell("npm install -g #{name}", retry: true) if `which #{command}`.chop.empty?
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.class_of(filename)
|
154
|
+
GEM_NAME_OF.keys.detect { |p| p.to_s.downcase == filename }
|
155
|
+
end
|
156
|
+
|
157
|
+
attr_reader :context, :options
|
158
|
+
|
159
|
+
def initialize(context, options)
|
160
|
+
@context, @options = context, options
|
161
|
+
context.env['GIT_HTTP_USER_AGENT'] = user_agent(git: `git --version`[/[\d\.]+/])
|
162
|
+
end
|
163
|
+
|
164
|
+
def user_agent(*strings)
|
165
|
+
strings.unshift "dpl/#{DPL::VERSION}"
|
166
|
+
strings.unshift "travis/0.1.0" if context.env['TRAVIS']
|
167
|
+
strings = strings.flat_map { |e| Hash === e ? e.map { |k,v| "#{k}/#{v}" } : e }
|
168
|
+
strings.join(" ").gsub(/\s+/, " ").strip
|
169
|
+
end
|
170
|
+
|
171
|
+
def option(name, *alternatives)
|
172
|
+
options.fetch(name) do
|
173
|
+
alternatives.any? ? option(*alternatives) : raise(Error, "missing #{name}")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def deploy
|
178
|
+
setup_git_credentials
|
179
|
+
rm_rf ".dpl"
|
180
|
+
mkdir_p ".dpl"
|
181
|
+
|
182
|
+
context.fold("Preparing deploy") do
|
183
|
+
check_auth
|
184
|
+
check_app
|
185
|
+
|
186
|
+
if needs_key?
|
187
|
+
create_key(".dpl/id_rsa")
|
188
|
+
setup_key(".dpl/id_rsa.pub")
|
189
|
+
setup_git_ssh(".dpl/git-ssh", ".dpl/id_rsa")
|
190
|
+
end
|
191
|
+
|
192
|
+
cleanup
|
193
|
+
end
|
194
|
+
|
195
|
+
context.fold("Deploying application") { push_app }
|
196
|
+
|
197
|
+
Array(options[:run]).each do |command|
|
198
|
+
if command == 'restart'
|
199
|
+
context.fold("Restarting application") { restart }
|
200
|
+
else
|
201
|
+
context.fold("Running %p" % command) { run(command) }
|
202
|
+
end
|
203
|
+
end
|
204
|
+
ensure
|
205
|
+
if needs_key?
|
206
|
+
remove_key rescue nil
|
207
|
+
end
|
208
|
+
uncleanup
|
209
|
+
end
|
210
|
+
|
211
|
+
def sha
|
212
|
+
@sha ||= context.env['TRAVIS_COMMIT'] || `git rev-parse HEAD`.strip
|
213
|
+
end
|
214
|
+
|
215
|
+
def commit_msg
|
216
|
+
@commit_msg ||= %x{git log #{sha} -n 1 --pretty=%B}.strip
|
217
|
+
end
|
218
|
+
|
219
|
+
def cleanup
|
220
|
+
return if options[:skip_cleanup]
|
221
|
+
context.shell "mv .dpl ~/dpl"
|
222
|
+
log "Cleaning up git repository with `git stash --all`. " \
|
223
|
+
"If you need build artifacts for deployment, set `deploy.skip_cleanup: true`. " \
|
224
|
+
"See https://docs.travis-ci.com/user/deployment#Uploading-Files-and-skip_cleanup."
|
225
|
+
context.shell "git stash --all"
|
226
|
+
context.shell "mv ~/dpl .dpl"
|
227
|
+
end
|
228
|
+
|
229
|
+
def uncleanup
|
230
|
+
return if options[:skip_cleanup]
|
231
|
+
context.shell "git stash pop"
|
232
|
+
end
|
233
|
+
|
234
|
+
def needs_key?
|
235
|
+
true
|
236
|
+
end
|
237
|
+
|
238
|
+
def check_app
|
239
|
+
end
|
240
|
+
|
241
|
+
def create_key(file)
|
242
|
+
context.shell "ssh-keygen -t rsa -N \"\" -C #{option(:key_name)} -f #{file}"
|
243
|
+
end
|
244
|
+
|
245
|
+
def setup_git_credentials
|
246
|
+
context.shell "git config user.email >/dev/null 2>/dev/null || git config user.email `whoami`@localhost"
|
247
|
+
context.shell "git config user.name >/dev/null 2>/dev/null || git config user.name `whoami`@localhost"
|
248
|
+
end
|
249
|
+
|
250
|
+
def setup_git_ssh(path, key_path)
|
251
|
+
key_path = File.expand_path(key_path)
|
252
|
+
path = File.expand_path(path)
|
253
|
+
|
254
|
+
File.open(path, 'w') do |file|
|
255
|
+
file.write "#!/bin/sh\n"
|
256
|
+
file.write "exec ssh -o StrictHostKeychecking=no -o CheckHostIP=no -o UserKnownHostsFile=/dev/null -i #{key_path} -- \"$@\"\n"
|
257
|
+
end
|
258
|
+
|
259
|
+
chmod(0740, path)
|
260
|
+
context.env['GIT_SSH'] = path
|
261
|
+
end
|
262
|
+
|
263
|
+
def detect_encoding?
|
264
|
+
options[:detect_encoding]
|
265
|
+
end
|
266
|
+
|
267
|
+
def default_text_charset?
|
268
|
+
options[:default_text_charset]
|
269
|
+
end
|
270
|
+
|
271
|
+
def default_text_charset
|
272
|
+
options[:default_text_charset].downcase
|
273
|
+
end
|
274
|
+
|
275
|
+
def install_deploy_dependencies
|
276
|
+
end
|
277
|
+
|
278
|
+
def encoding_for(path)
|
279
|
+
file_cmd_output = `file '#{path}'`
|
280
|
+
case file_cmd_output
|
281
|
+
when /gzip compressed/
|
282
|
+
'gzip'
|
283
|
+
when /compress'd/
|
284
|
+
'compress'
|
285
|
+
when /text/
|
286
|
+
'text'
|
287
|
+
when /data/
|
288
|
+
# Shrugs?
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def log(message)
|
293
|
+
$stderr.puts(message)
|
294
|
+
end
|
295
|
+
|
296
|
+
def warn(message)
|
297
|
+
log "\e[31;1m#{message}\e[0m"
|
298
|
+
end
|
299
|
+
|
300
|
+
def run(command)
|
301
|
+
error "running commands not supported"
|
302
|
+
end
|
303
|
+
|
304
|
+
def error(message)
|
305
|
+
raise Error, message
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
data/lib/dpl/version.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
EY has a a special deploy app. Get in touch with Kevin Holler if we don't hear back from them.
|
data/notes/heroku.md
ADDED
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dpl/cli'
|
3
|
+
|
4
|
+
describe DPL::CLI do
|
5
|
+
describe "#options" do
|
6
|
+
example { expect(described_class.new.options[:app]) .to eq(File.basename(Dir.pwd)) }
|
7
|
+
example { expect(described_class.new(:app => 'foo') .options[:app]).to eq('foo') }
|
8
|
+
example { expect(described_class.new("--app=foo") .options[:app]).to eq('foo') }
|
9
|
+
example { expect(described_class.new("--app") .options[:app]).to eq(true) }
|
10
|
+
example { expect(described_class.new("--app=foo", "--app=bar") .options[:app]).to eq(['foo', 'bar']) }
|
11
|
+
|
12
|
+
example "error handling" do
|
13
|
+
expect($stderr).to receive(:puts).with('invalid option "app"')
|
14
|
+
expect { described_class.new("app") }.to raise_error(SystemExit)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#run" do
|
19
|
+
example "triggers deploy" do
|
20
|
+
provider = double('provider')
|
21
|
+
expect(DPL::Provider).to receive(:new).and_return(provider)
|
22
|
+
expect(provider).to receive(:deploy)
|
23
|
+
|
24
|
+
described_class.run("--provider=foo")
|
25
|
+
end
|
26
|
+
|
27
|
+
example "error handling" do
|
28
|
+
expect($stderr).to receive(:puts).with('missing provider')
|
29
|
+
expect { described_class.run }.to raise_error(SystemExit)
|
30
|
+
end
|
31
|
+
|
32
|
+
example "error handling in debug mode" do
|
33
|
+
expect { described_class.run("--debug") }.to raise_error(DPL::Error, 'missing provider')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dpl/provider'
|
3
|
+
|
4
|
+
describe DPL::Provider do
|
5
|
+
let(:example_provider) { Class.new(described_class)}
|
6
|
+
let(:context) { DummyContext.new }
|
7
|
+
subject(:provider) { example_provider.new(context, :app => 'example', :key_name => 'foo', :run => ["foo", "bar"]) }
|
8
|
+
|
9
|
+
before { stub_const "DPL::Provider::Example", example_provider }
|
10
|
+
|
11
|
+
describe "#new" do
|
12
|
+
example { expect(described_class.new(context, :provider => "example")) .to be_an(example_provider) }
|
13
|
+
example { expect(described_class.new(context, :provider => "Example")) .to be_an(example_provider) }
|
14
|
+
example { expect(described_class.new(context, :provider => "exa_mple")).to be_an(example_provider) }
|
15
|
+
example { expect(described_class.new(context, :provider => "exa-mple")).to be_an(example_provider) }
|
16
|
+
example { expect(described_class.new(context, :provider => "scri_pt")).to be_an(DPL::Provider::Script) }
|
17
|
+
example { expect(described_class.new(context, :provider => "scri _pt")).to be_an(DPL::Provider::Script) }
|
18
|
+
example { expect(described_class.new(context, :provider => "cloudfoundry")).to be_an(DPL::Provider::CloudFoundry) }
|
19
|
+
example "install deployment dependencies" do
|
20
|
+
expect_any_instance_of(described_class).to receive(:respond_to?).with(:install_deploy_dependencies).and_return(true)
|
21
|
+
expect_any_instance_of(described_class).to receive(:install_deploy_dependencies)
|
22
|
+
described_class.new(context, :provider => "example")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "installs correct gem when provider name does not match" do
|
26
|
+
expect(context).to receive(:shell).with("gem install dpl-cloud_foundry -v #{ENV['DPL_VERSION'] || DPL::VERSION}")
|
27
|
+
expect(described_class).to receive(:require).with("dpl/provider/cloud_foundry").and_raise LoadError.new("cannot load such file -- dpl/provider/cloud_foundry")
|
28
|
+
expect(described_class).to receive(:require).with("dpl/provider/cloud_foundry").and_call_original
|
29
|
+
described_class.new(context, :provider => 'cloudfoundry')
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#pip" do
|
35
|
+
example "installed" do
|
36
|
+
expect(example_provider).to receive(:`).with("which foo").and_return("/bin/foo\n")
|
37
|
+
expect(example_provider).not_to receive(:system)
|
38
|
+
expect(example_provider.context).to receive(:shell).with("export PATH=$PATH:$HOME/.local/bin")
|
39
|
+
example_provider.pip("foo")
|
40
|
+
end
|
41
|
+
|
42
|
+
example "missing" do
|
43
|
+
expect(example_provider).to receive(:`).with("which foo").and_return("")
|
44
|
+
expect(example_provider.context).to receive(:shell).with("pip install --user foo", retry: true)
|
45
|
+
expect(example_provider.context).to receive(:shell).with("export PATH=$PATH:$HOME/.local/bin")
|
46
|
+
example_provider.pip("foo")
|
47
|
+
end
|
48
|
+
|
49
|
+
example "specific version" do
|
50
|
+
expect(example_provider).to receive(:`).with("which foo").and_return("")
|
51
|
+
expect(example_provider.context).to receive(:shell).with("pip install --user foo==1.0", retry: true)
|
52
|
+
expect(example_provider.context).to receive(:shell).with("export PATH=$PATH:$HOME/.local/bin")
|
53
|
+
example_provider.pip("foo", "foo", "1.0")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#deploy" do
|
58
|
+
before do
|
59
|
+
expect(provider).to receive(:check_auth)
|
60
|
+
expect(provider).to receive(:check_app)
|
61
|
+
expect(provider).to receive(:push_app)
|
62
|
+
expect(provider).to receive(:run).with("foo")
|
63
|
+
expect(provider).to receive(:run).with("bar")
|
64
|
+
end
|
65
|
+
|
66
|
+
example "needs key" do
|
67
|
+
expect(provider).to receive(:remove_key)
|
68
|
+
expect(provider).to receive(:create_key)
|
69
|
+
expect(provider).to receive(:setup_key)
|
70
|
+
expect(provider).to receive(:setup_git_ssh)
|
71
|
+
provider.deploy
|
72
|
+
end
|
73
|
+
|
74
|
+
example "does not need key" do
|
75
|
+
allow(provider).to receive_messages(:needs_key? => false)
|
76
|
+
provider.deploy
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#cleanup" do
|
81
|
+
example do
|
82
|
+
expect(provider.context).to receive(:shell).with('mv .dpl ~/dpl')
|
83
|
+
expect(provider.context).to receive(:shell).with('git stash --all')
|
84
|
+
expect(provider.context).to receive(:shell).with('mv ~/dpl .dpl')
|
85
|
+
provider.cleanup
|
86
|
+
end
|
87
|
+
|
88
|
+
example "skip cleanup" do
|
89
|
+
expect(provider.options).to receive(:[]).with(:skip_cleanup).and_return("true")
|
90
|
+
expect(provider.context).not_to receive(:shell)
|
91
|
+
provider.cleanup
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#uncleanup" do
|
96
|
+
example do
|
97
|
+
expect(provider.context).to receive(:shell).with('git stash pop')
|
98
|
+
provider.uncleanup
|
99
|
+
end
|
100
|
+
|
101
|
+
example "skip cleanup" do
|
102
|
+
expect(provider.options).to receive(:[]).with(:skip_cleanup).and_return("true")
|
103
|
+
expect(provider.context).not_to receive(:shell)
|
104
|
+
provider.uncleanup
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#create_key" do
|
109
|
+
example do
|
110
|
+
expect(provider.context).to receive(:shell).with('ssh-keygen -t rsa -N "" -C foo -f thekey')
|
111
|
+
provider.create_key('thekey')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#setup_git_ssh" do
|
116
|
+
after { FileUtils.rm provider.context.env.delete('GIT_SSH') }
|
117
|
+
|
118
|
+
example do
|
119
|
+
provider.setup_git_ssh('foo', 'bar')
|
120
|
+
expect(provider.context.env['GIT_SSH']).to eq(File.expand_path('foo'))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#detect_encoding?" do
|
125
|
+
example do
|
126
|
+
provider.options.update(:detect_encoding => true)
|
127
|
+
expect(provider.detect_encoding?).to eq(true)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#encoding_for" do
|
132
|
+
example do
|
133
|
+
path = 'foo.js'
|
134
|
+
expect(provider).to receive(:`).at_least(1).times.with("file '#{path}'").and_return("#{path}: gzip compressed")
|
135
|
+
expect(provider.encoding_for(path)).to eq('gzip')
|
136
|
+
end
|
137
|
+
|
138
|
+
example do
|
139
|
+
path = 'file with a space'
|
140
|
+
expect(provider).to receive(:`).at_least(1).times.with("file '#{path}'").and_return("#{path}: empty")
|
141
|
+
expect(provider.encoding_for(path)).to be_nil
|
142
|
+
end
|
143
|
+
|
144
|
+
example do
|
145
|
+
path = 'foo.js'
|
146
|
+
expect(provider).to receive(:`).at_least(1).times.with("file '#{path}'").and_return("#{path}: ASCII text, with very long line")
|
147
|
+
expect(provider.encoding_for(path)).to eq('text')
|
148
|
+
end
|
149
|
+
|
150
|
+
example do
|
151
|
+
path = 'foo.js'
|
152
|
+
provider.options.update(:default_text_charset => 'UTF-8')
|
153
|
+
expect(provider).to receive(:`).at_least(1).times.with("file '#{path}'").and_return("#{path}: ASCII text, with very long line")
|
154
|
+
expect(provider.encoding_for(path)).to eq('text')
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "#log" do
|
159
|
+
example do
|
160
|
+
expect($stderr).to receive(:puts).with("foo")
|
161
|
+
provider.log("foo")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "#shell" do
|
166
|
+
example do
|
167
|
+
expect(example_provider).to receive(:system).with("command")
|
168
|
+
example_provider.shell("command")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#npm_g" do
|
173
|
+
example do
|
174
|
+
expect(example_provider.context).to receive(:shell).with("npm install -g foo", retry: true)
|
175
|
+
example_provider.npm_g("foo")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "#run" do
|
180
|
+
example do
|
181
|
+
expect(provider).to receive(:error).with("running commands not supported")
|
182
|
+
provider.run "blah"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "#error" do
|
187
|
+
example do
|
188
|
+
expect { provider.error("Foo") }.to raise_error("Foo")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|