boxci 0.0.30
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +146 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +118 -0
- data/Rakefile +13 -0
- data/bin/boxci +6 -0
- data/boxci.gemspec +28 -0
- data/lib/boxci/builder.rb +29 -0
- data/lib/boxci/cli.rb +70 -0
- data/lib/boxci/config_permutation.rb +15 -0
- data/lib/boxci/config_permutation_component.rb +11 -0
- data/lib/boxci/config_permutation_component_factory.rb +7 -0
- data/lib/boxci/config_permutation_components/rbenv.rb +13 -0
- data/lib/boxci/dependency_checker.rb +55 -0
- data/lib/boxci/global_config.rb +26 -0
- data/lib/boxci/initializer.rb +41 -0
- data/lib/boxci/language.rb +35 -0
- data/lib/boxci/language_factory.rb +7 -0
- data/lib/boxci/languages/ruby.rb +31 -0
- data/lib/boxci/project_config.rb +96 -0
- data/lib/boxci/provider.rb +35 -0
- data/lib/boxci/provider_config.rb +23 -0
- data/lib/boxci/provider_factory.rb +7 -0
- data/lib/boxci/providers/aws.rb +27 -0
- data/lib/boxci/providers/openstack.rb +27 -0
- data/lib/boxci/providers/virtualbox.rb +24 -0
- data/lib/boxci/templates/Vagrantfile +41 -0
- data/lib/boxci/templates/boxci/global_config.yml.tt +1 -0
- data/lib/boxci/templates/dot_boxci.yml.tt +11 -0
- data/lib/boxci/templates/languages/ruby/main.pp +27 -0
- data/lib/boxci/templates/providers/aws/Vagrantfile.erb +45 -0
- data/lib/boxci/templates/providers/aws.yml.tt +5 -0
- data/lib/boxci/templates/providers/openstack/Vagrantfile.erb +37 -0
- data/lib/boxci/templates/providers/openstack.yml.tt +16 -0
- data/lib/boxci/templates/providers/virtualbox/Vagrantfile.erb +47 -0
- data/lib/boxci/templates/providers/virtualbox.yml.tt +2 -0
- data/lib/boxci/templates/puppet/manifests/.empty_directory +0 -0
- data/lib/boxci/templates/puppet/modules/.empty_directory +0 -0
- data/lib/boxci/test_runner.rb +134 -0
- data/lib/boxci/tester.rb +287 -0
- data/lib/boxci/version.rb +3 -0
- data/lib/boxci.rb +71 -0
- data/spec/lib/boxci/builder_spec.rb +86 -0
- data/spec/lib/boxci/config_permutation_component_factory_spec.rb +17 -0
- data/spec/lib/boxci/config_permutation_component_spec.rb +19 -0
- data/spec/lib/boxci/config_permutation_components/rbenv_spec.rb +12 -0
- data/spec/lib/boxci/config_permutation_spec.rb +27 -0
- data/spec/lib/boxci/dependency_checker_spec.rb +215 -0
- data/spec/lib/boxci/global_config_spec.rb +34 -0
- data/spec/lib/boxci/initializer_spec.rb +117 -0
- data/spec/lib/boxci/language_factory_spec.rb +17 -0
- data/spec/lib/boxci/language_spec.rb +31 -0
- data/spec/lib/boxci/project_config_spec.rb +218 -0
- data/spec/lib/boxci/provider_config_spec.rb +39 -0
- data/spec/lib/boxci/provider_factory_spec.rb +17 -0
- data/spec/lib/boxci/provider_spec.rb +30 -0
- data/spec/lib/boxci/tester_spec.rb +15 -0
- data/spec/lib/boxci_spec.rb +176 -0
- data/spec/spec_helper.rb +11 -0
- metadata +213 -0
data/lib/boxci/tester.rb
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "net/ssh"
|
3
|
+
require "net/scp"
|
4
|
+
|
5
|
+
module Boxci
|
6
|
+
class Tester
|
7
|
+
include Thor::Base
|
8
|
+
include Thor::Actions
|
9
|
+
|
10
|
+
def self.exit_on_failure?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
source_root(File.dirname(__FILE__))
|
15
|
+
|
16
|
+
def test(options)
|
17
|
+
File.open('/tmp/boxci.log', 'w') do |f|
|
18
|
+
f.write('')
|
19
|
+
end
|
20
|
+
|
21
|
+
# NOTE: The Signal.trap('SIGTERM') is required for Bamboo's "Stop
|
22
|
+
# Build" functionality because Bamboo basically sends a SIGTERM to
|
23
|
+
# Boxci and then immediately closes its stdout and stderr pipes
|
24
|
+
# before Boxci has had a chance to cleanup. Therefore, it causes
|
25
|
+
# Errno::EPIPE exceptions to be raised. It does seem that in general
|
26
|
+
# the use of SIGTERM is correct however one would hope that stdout and
|
27
|
+
# stderr pipes would stay open until Boxci exits, but sadly they
|
28
|
+
# do not.
|
29
|
+
Signal.trap('SIGTERM') do
|
30
|
+
File.open('/tmp/boxci.log', 'a+') { |f| f.write("Got SIGTERM, going to cleanup...\n") }
|
31
|
+
|
32
|
+
begin
|
33
|
+
cleanup
|
34
|
+
rescue Errno::EPIPE => e
|
35
|
+
File.open('/tmp/boxci.log', 'a+') { |f| f.write("SIGTERM handler swallowed Errno::EPIPE exception\n") }
|
36
|
+
rescue => e
|
37
|
+
File.open('/tmp/boxci.log', 'a+') do |f|
|
38
|
+
f.write("SIGTERM handler caught exception")
|
39
|
+
f.write("#{e.class}\n")
|
40
|
+
f.write("#{e.message}\n")
|
41
|
+
f.write("#{e.backtrace.join("\n")}\n")
|
42
|
+
end
|
43
|
+
raise e
|
44
|
+
end
|
45
|
+
|
46
|
+
File.open('/tmp/boxci.log', 'a+') { |f| f.write("Finished cleanup process from SIGTERM\n") }
|
47
|
+
exit 255
|
48
|
+
end
|
49
|
+
|
50
|
+
Signal.trap('SIGINT') do
|
51
|
+
cleanup
|
52
|
+
exit 255
|
53
|
+
end
|
54
|
+
|
55
|
+
# TODO: I don't believe this is necessary as I think Ruby's default
|
56
|
+
# handler for SIGPIPE is to ignore it. I need to test this though to
|
57
|
+
# verify.
|
58
|
+
Signal.trap('SIGPIPE', 'SIG_IGN')
|
59
|
+
|
60
|
+
@tester_exit_code = 0
|
61
|
+
# depencency_checker = Boxci::DependencyChecker.new
|
62
|
+
# depencency_checker.verify_all
|
63
|
+
initial_config(options)
|
64
|
+
|
65
|
+
create_project_folder
|
66
|
+
create_project_archive
|
67
|
+
write_vagrant_file
|
68
|
+
write_test_runner
|
69
|
+
if @provider_object.requires_plugin?
|
70
|
+
install_vagrant_plugin
|
71
|
+
add_provider_box
|
72
|
+
end
|
73
|
+
spin_up_box
|
74
|
+
setup_ssh_config
|
75
|
+
install_puppet_on_box
|
76
|
+
provision_box
|
77
|
+
create_artifact_directory
|
78
|
+
upload_test_runner
|
79
|
+
run_tests
|
80
|
+
download_artifacts
|
81
|
+
say "Finished!", :green
|
82
|
+
rescue Errno::EPIPE => e
|
83
|
+
File.open('/tmp/boxci.log', 'a+') do |f|
|
84
|
+
f.write("test() method swallowed Errno::EPIPE exception\n")
|
85
|
+
end
|
86
|
+
rescue => e
|
87
|
+
File.open('/tmp/boxci.log', 'a+') do |f|
|
88
|
+
f.write("test() method caught exception")
|
89
|
+
f.write("#{e.class}\n")
|
90
|
+
f.write("#{e.message}\n")
|
91
|
+
f.write("#{e.backtrace.join("\n")}\n")
|
92
|
+
end
|
93
|
+
raise e
|
94
|
+
ensure
|
95
|
+
cleanup
|
96
|
+
exit @tester_exit_code
|
97
|
+
end
|
98
|
+
|
99
|
+
def initial_config(options)
|
100
|
+
@gem_path = File.expand_path(File.dirname(__FILE__) + "/../..")
|
101
|
+
@puppet_path = File.join(Boxci.project_path, "puppet")
|
102
|
+
@project_uid = "#{rand(1000..9000)}-#{rand(1000..9000)}-#{rand(1000..9000)}-#{rand(1000..9000)}"
|
103
|
+
@project_workspace_folder = File.join(File.expand_path(ENV['HOME']), '.boxci', @project_uid)
|
104
|
+
@options = options
|
105
|
+
@provider_config = Boxci.provider_config(provider)
|
106
|
+
@project_config = Boxci.project_config
|
107
|
+
@provider_object = Boxci::ProviderFactory.build(provider)
|
108
|
+
end
|
109
|
+
|
110
|
+
def provider
|
111
|
+
@options["provider"]
|
112
|
+
end
|
113
|
+
|
114
|
+
def verbose?
|
115
|
+
@options["verbose"] == true
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_project_folder
|
119
|
+
empty_directory @project_workspace_folder, :verbose => verbose?
|
120
|
+
end
|
121
|
+
|
122
|
+
def create_project_archive
|
123
|
+
inside Boxci.project_path do
|
124
|
+
run "git checkout #{@options["revision"]}", :verbose => verbose?
|
125
|
+
run "git submodule update --init", :verbose => verbose?
|
126
|
+
run "tar cf #{File.join(@project_workspace_folder, "project.tar")} --exclude .git --exclude \"*.log\" --exclude node_modules .", :verbose => verbose?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def write_vagrant_file
|
131
|
+
erb_template = File.join("templates", "providers", provider, "Vagrantfile.erb")
|
132
|
+
destination = File.join(@project_workspace_folder, "Vagrantfile")
|
133
|
+
|
134
|
+
template erb_template, destination, :verbose => verbose?
|
135
|
+
end
|
136
|
+
|
137
|
+
def write_test_runner
|
138
|
+
destination = File.join(@project_workspace_folder, "test_runner.sh")
|
139
|
+
test_runner = Boxci::TestRunner.new(Boxci::LanguageFactory.build(Boxci.project_config.language))
|
140
|
+
File.open(destination, 'w+') do |f|
|
141
|
+
f.write(test_runner.generate_script)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def install_vagrant_plugin
|
146
|
+
inside @project_workspace_folder do
|
147
|
+
plugin = @provider_object.plugin
|
148
|
+
# check for vagrant plugin
|
149
|
+
if !system("vagrant plugin list | grep -q #{plugin}")
|
150
|
+
# if vagrant plugin is missing
|
151
|
+
say "You are missing the Vagrant plugin for #{provider}", :yellow
|
152
|
+
# ask user if it's ok to install for them
|
153
|
+
if yes?("Would you like to install it now?")
|
154
|
+
run "vagrant plugin install #{plugin}", :verbose => verbose?
|
155
|
+
end
|
156
|
+
else # if vagrant plugin is found
|
157
|
+
say "Provider plugin #{plugin} found", :green
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def add_provider_box
|
163
|
+
dummy_box_url = @provider_object.dummy_box_url
|
164
|
+
if dummy_box_url
|
165
|
+
if run "curl --output /dev/null --silent --head --fail #{dummy_box_url}"
|
166
|
+
say "Using specified VM Box URL", :green
|
167
|
+
else
|
168
|
+
say "Could not resolve the Box URL: #{dummy_box_url}", :red
|
169
|
+
end
|
170
|
+
else
|
171
|
+
inside @project_workspace_folder do
|
172
|
+
# check for box
|
173
|
+
if !system("vagrant box list | grep dummy | grep -q \"(#{provider})\"")
|
174
|
+
# if box is missing
|
175
|
+
say "No box found for #{provider}, installing now...", :blue
|
176
|
+
run "vagrant box add dummy #{dummy_box_url}", :verbose => verbose?
|
177
|
+
else # if vagrant plugin is found
|
178
|
+
say "Provider box found", :green
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def spin_up_box
|
185
|
+
inside @project_workspace_folder do
|
186
|
+
run "vagrant up --no-provision --provider #{provider}", :verbose => verbose?
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def setup_ssh_config
|
191
|
+
inside @project_workspace_folder do
|
192
|
+
run "vagrant ssh-config > ssh-config.local", :verbose => verbose?
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def install_puppet_on_box
|
197
|
+
say "Opening SSH tunnel into the box...", :blue if verbose?
|
198
|
+
Net::SSH.start("default", nil, {:config => File.join(@project_workspace_folder, "ssh-config.local")}) do |ssh|
|
199
|
+
puppet = ssh.exec! "which puppet"
|
200
|
+
unless puppet
|
201
|
+
say "Running: sudo apt-get --yes update", :blue if verbose?
|
202
|
+
ssh.exec! "sudo apt-get --yes update"
|
203
|
+
say "Running: sudo apt-get --yes install puppet", :blue if verbose?
|
204
|
+
ssh.exec! "sudo apt-get --yes install puppet"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def provision_box
|
210
|
+
say "Provisioning the box with puppet...", :blue if verbose?
|
211
|
+
inside @project_workspace_folder do
|
212
|
+
run "vagrant provision", :verbose => verbose?
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def create_artifact_directory
|
217
|
+
say "Creating the artifact directory on the box...", :blue if verbose?
|
218
|
+
Net::SSH.start("default", nil, {:config => File.join(@project_workspace_folder, "ssh-config.local")}) do |ssh|
|
219
|
+
ssh.exec! "mkdir -p #{@project_config.artifact_path}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def upload_test_runner
|
224
|
+
Net::SSH.start("default", nil, {:config => File.join(@project_workspace_folder, "ssh-config.local")}) do |ssh|
|
225
|
+
say "Uploading test_runner.sh to the box...", :blue if verbose?
|
226
|
+
ssh.scp.upload! File.join(@project_workspace_folder, "test_runner.sh"), "/vagrant/test_runner.sh"
|
227
|
+
say "Running: chmod a+x /vagrant/test_runner.sh", :blue if verbose?
|
228
|
+
puts ssh.exec! "chmod a+x /vagrant/test_runner.sh"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def run_tests
|
233
|
+
exit_code = nil
|
234
|
+
exit_signal = nil
|
235
|
+
Net::SSH.start("default", nil, {:config => File.join(@project_workspace_folder, "ssh-config.local")}) do |session|
|
236
|
+
say "Running the test steps on the box...", :blue if verbose?
|
237
|
+
session.open_channel do |channel|
|
238
|
+
channel.on_data do |ch, data|
|
239
|
+
$stdout.write(data)
|
240
|
+
end
|
241
|
+
|
242
|
+
channel.on_extended_data do |ch, type, data|
|
243
|
+
$stderr.write(data)
|
244
|
+
end
|
245
|
+
|
246
|
+
channel.on_request("exit-status") do |ch, data|
|
247
|
+
exit_code = data.read_long
|
248
|
+
@tester_exit_code = exit_code
|
249
|
+
end
|
250
|
+
|
251
|
+
channel.exec "/vagrant/test_runner.sh"
|
252
|
+
end
|
253
|
+
session.loop
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def download_artifacts
|
258
|
+
Net::SSH.start("default", nil, {:config => File.join(@project_workspace_folder, "ssh-config.local")}) do |ssh|
|
259
|
+
say "Downloading the reports...", :blue if verbose?
|
260
|
+
puts ssh.exec! "cd #{@project_config.artifact_path} && tar cf /tmp/boxci_artifacts.tar ."
|
261
|
+
ssh.scp.download! "/tmp/boxci_artifacts.tar", '.'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def cleanup
|
266
|
+
if @project_workspace_folder && File.directory?(@project_workspace_folder)
|
267
|
+
# NOTE: The begin rescue for Errno::EPIPE and the &>>
|
268
|
+
# /tmp/boxci.log in the backtick execution ARE required for
|
269
|
+
# Bamboo's "Stop Build" functionality because Bamboo basically sends
|
270
|
+
# a SIGTERM to Boxci and then immediately closes its stdout and
|
271
|
+
# stderr pipes before Boxci has had a chance to cleanup. Therefore,
|
272
|
+
# it causes Errno::EPIPE exceptions to be raised.
|
273
|
+
begin
|
274
|
+
say "Cleaning up...", :blue
|
275
|
+
rescue Errno::EPIPE => e
|
276
|
+
File.open('/tmp/boxci.log', 'a+') { |f| f.write("Cleaning up...\n") }
|
277
|
+
end
|
278
|
+
inside @project_workspace_folder do
|
279
|
+
`vagrant destroy -f >> /tmp/boxci.log 2>&1`
|
280
|
+
# run "vagrant destroy -f", :verbose => verbose?, :capture => true
|
281
|
+
end
|
282
|
+
`rm -rf #{@project_workspace_folder} >> /tmp/boxci.log 2>&1`
|
283
|
+
# remove_dir @project_workspace_folder, :verbose => verbose?, :capture => true
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
data/lib/boxci.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'boxci/version'
|
2
|
+
require 'boxci/project_config'
|
3
|
+
require 'boxci/global_config'
|
4
|
+
require 'boxci/provider_config'
|
5
|
+
require 'boxci/initializer'
|
6
|
+
require 'boxci/builder'
|
7
|
+
require 'boxci/dependency_checker'
|
8
|
+
require 'boxci/tester'
|
9
|
+
require 'boxci/language_factory'
|
10
|
+
require 'boxci/language'
|
11
|
+
require 'boxci/languages/ruby'
|
12
|
+
require 'boxci/provider_factory'
|
13
|
+
require 'boxci/provider'
|
14
|
+
require 'boxci/providers/virtualbox'
|
15
|
+
require 'boxci/providers/aws'
|
16
|
+
require 'boxci/providers/openstack'
|
17
|
+
require 'boxci/config_permutation'
|
18
|
+
require 'boxci/config_permutation_component'
|
19
|
+
require 'boxci/config_permutation_component_factory'
|
20
|
+
require 'boxci/config_permutation_components/rbenv'
|
21
|
+
require 'boxci/test_runner'
|
22
|
+
|
23
|
+
module Boxci
|
24
|
+
class MissingDependency < StandardError; end
|
25
|
+
class PureVirtualMethod < StandardError; end
|
26
|
+
|
27
|
+
def self.project_config
|
28
|
+
if @project_config
|
29
|
+
return @project_config
|
30
|
+
else
|
31
|
+
@project_config = Boxci::ProjectConfig.new
|
32
|
+
@project_config.load
|
33
|
+
return @project_config
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.global_config
|
38
|
+
if @global_config
|
39
|
+
return @global_config
|
40
|
+
else
|
41
|
+
@global_config = Boxci::GlobalConfig.new
|
42
|
+
@global_config.load
|
43
|
+
return @global_config
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.provider_config(provider)
|
48
|
+
if @provider_config
|
49
|
+
return @provider_config
|
50
|
+
else
|
51
|
+
@provider_config = Boxci::ProviderConfig.new(provider)
|
52
|
+
@provider_config.load
|
53
|
+
return @provider_config
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.default_provider
|
58
|
+
if global_config.default_provider
|
59
|
+
return global_config.default_provider
|
60
|
+
else
|
61
|
+
return ::Boxci::CLI::DEFAULT_PROVIDER
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.project_path
|
66
|
+
@project_path ||= File.expand_path(%x(pwd)).strip
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# TODO: Restructure to prevent this from needing to be here.
|
71
|
+
require 'boxci/cli'
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Boxci::Builder do
|
4
|
+
describe "#build" do
|
5
|
+
it "generates project Vagrantfile" do
|
6
|
+
allow(subject).to receive(:generate_starter_puppet_manifest)
|
7
|
+
expect(subject).to receive(:generate_project_vagrantfile)
|
8
|
+
subject.build
|
9
|
+
end
|
10
|
+
|
11
|
+
it "generates starter Puppet manifiest" do
|
12
|
+
allow(subject).to receive(:generate_project_vagrantfile)
|
13
|
+
expect(subject).to receive(:generate_starter_puppet_manifest)
|
14
|
+
subject.build
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#generate_project_vagrantfile" do
|
19
|
+
let(:project_path) { "/some/path" }
|
20
|
+
let(:dependency_checker) { double(Boxci::DependencyChecker, :verify_boxci_config => nil) }
|
21
|
+
|
22
|
+
it "verifies the boxci config file is present" do
|
23
|
+
allow(subject).to receive(:template)
|
24
|
+
allow(Boxci).to receive(:project_config)
|
25
|
+
allow(Boxci::DependencyChecker).to receive(:new).and_return(dependency_checker)
|
26
|
+
expect(dependency_checker).to receive(:verify_boxci_config)
|
27
|
+
subject.generate_project_vagrantfile
|
28
|
+
end
|
29
|
+
|
30
|
+
it "gets boxci project config hash" do
|
31
|
+
allow(subject).to receive(:template)
|
32
|
+
allow(Boxci::DependencyChecker).to receive(:new).and_return(dependency_checker)
|
33
|
+
expect(Boxci).to receive(:project_config)
|
34
|
+
subject.generate_project_vagrantfile
|
35
|
+
end
|
36
|
+
|
37
|
+
it "assigns the boxci project config to instance variable" do
|
38
|
+
allow(subject).to receive(:template)
|
39
|
+
allow(Boxci::DependencyChecker).to receive(:new).and_return(dependency_checker)
|
40
|
+
project_config_double = double
|
41
|
+
allow(Boxci).to receive(:project_config).and_return(project_config_double)
|
42
|
+
subject.generate_project_vagrantfile
|
43
|
+
expect(subject.instance_variable_get(:@project_config)).to eq(project_config_double)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "copies the Vagrantfile template for the specified language to the user's home directory" do
|
47
|
+
allow(Boxci).to receive(:project_config)
|
48
|
+
allow(Boxci::DependencyChecker).to receive(:new).and_return(dependency_checker)
|
49
|
+
expect(subject).to receive(:template).with("templates/Vagrantfile", File.join(Boxci.project_path, "Vagrantfile"))
|
50
|
+
subject.generate_project_vagrantfile
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#generate_starter_puppet_manifiest" do
|
55
|
+
let(:project_path) { "/some/path" }
|
56
|
+
|
57
|
+
before do
|
58
|
+
allow(Boxci).to receive(:project_path).and_return(project_path)
|
59
|
+
allow(Boxci).to receive(:project_config).and_return(double(:language => 'ruby'))
|
60
|
+
end
|
61
|
+
|
62
|
+
it "copies the template to the repo" do
|
63
|
+
language_factory_double = double(:generate_starter_puppet_manifest => nil)
|
64
|
+
allow(Boxci::LanguageFactory).to receive(:build).and_return(language_factory_double)
|
65
|
+
expect(subject).to receive(:directory).with("templates/puppet", File.join(Boxci.project_path, "puppet"))
|
66
|
+
subject.generate_starter_puppet_manifest
|
67
|
+
end
|
68
|
+
|
69
|
+
it "builds a boxci language object" do
|
70
|
+
allow(subject).to receive(:directory)
|
71
|
+
language_double = double
|
72
|
+
project_config_double = double(:language => language_double)
|
73
|
+
allow(Boxci).to receive(:project_config).and_return(project_config_double)
|
74
|
+
expect(Boxci::LanguageFactory).to receive(:build).with(language_double).and_return(double.as_null_object)
|
75
|
+
subject.generate_starter_puppet_manifest
|
76
|
+
end
|
77
|
+
|
78
|
+
it "generates the language specific starter puppet manifest" do
|
79
|
+
allow(subject).to receive(:directory)
|
80
|
+
language_obj_double = double
|
81
|
+
allow(Boxci::LanguageFactory).to receive(:build).and_return(language_obj_double)
|
82
|
+
expect(language_obj_double).to receive(:generate_starter_puppet_manifest)
|
83
|
+
subject.generate_starter_puppet_manifest
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxci::ConfigPermutationComponentFactory do
|
4
|
+
describe ".build" do
|
5
|
+
it "gets the constant for the config permutation component class" do
|
6
|
+
expect(Boxci::ConfigPermutationComponents).to receive(:const_get).with('Rbenv').and_return(double.as_null_object)
|
7
|
+
subject.build('rbenv', 'foo')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "constructs a new instance of the config permutation component const it previously grabbed" do
|
11
|
+
comp = double
|
12
|
+
allow(Boxci::ConfigPermutationComponents).to receive(:const_get).with('Rbenv').and_return(comp)
|
13
|
+
expect(comp).to receive(:new)
|
14
|
+
subject.build('rbenv', 'foo')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxci::ConfigPermutationComponent do
|
4
|
+
subject { Boxci::ConfigPermutationComponent }
|
5
|
+
|
6
|
+
describe '#initialize' do
|
7
|
+
it 'assigns the given value to an instance variable' do
|
8
|
+
config_permutation_component = subject.new('foeue')
|
9
|
+
expect(config_permutation_component.instance_variable_get(:@val)).to eq('foeue')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#switch_to_script' do
|
14
|
+
it 'raises exception stating it is pure virtual method' do
|
15
|
+
config_permutation_component = subject.new('foeue')
|
16
|
+
expect { config_permutation_component.switch_to_script }.to raise_error(Boxci::PureVirtualMethod)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxci::ConfigPermutationComponents::Rbenv do
|
4
|
+
subject { Boxci::ConfigPermutationComponents::Rbenv }
|
5
|
+
|
6
|
+
describe '#switch_to_script' do
|
7
|
+
it 'generates bash script to switch ruby verisons with rbenv' do
|
8
|
+
comp = subject.new('2.1.0')
|
9
|
+
expect(comp.switch_to_script).to eq("echo \"Switching to ruby 2.1.0\"\nrbenv local 2.1.0\necho \"Swithed to ruby `ruby --version`\"\n")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxci::ConfigPermutation do
|
4
|
+
describe "#initialize" do
|
5
|
+
it "constructs an instance of a Boxci::ConfigPermutation given an array of config permutation components" do
|
6
|
+
config_permutation_components = [double, double, double]
|
7
|
+
config_permutation = Boxci::ConfigPermutation.new(config_permutation_components)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "assigns the given components array to an instance variable" do
|
11
|
+
config_permutation_components = [double, double, double]
|
12
|
+
config_permutation = Boxci::ConfigPermutation.new(config_permutation_components)
|
13
|
+
expect(config_permutation.instance_variable_get(:@components)).to eq(config_permutation_components)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#switch_to_script" do
|
18
|
+
it "grabs the switch to scripts of each of the components and joins them together with newlines" do
|
19
|
+
comp1 = double(:switch_to_script => 'a')
|
20
|
+
comp2 = double(:switch_to_script => 'b')
|
21
|
+
comp3 = double(:switch_to_script => 'c')
|
22
|
+
config_permutation_components = [comp1, comp2, comp3]
|
23
|
+
config_permutation = Boxci::ConfigPermutation.new(config_permutation_components)
|
24
|
+
expect(config_permutation.switch_to_script).to eq("a\nb\nc")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|