cany 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -0
- data/Gemfile +12 -0
- data/Guardfile +20 -0
- data/Rakefile +11 -0
- data/lib/cany.rb +88 -19
- data/lib/cany/dependency.rb +70 -0
- data/lib/cany/dpkg/builder.rb +4 -16
- data/lib/cany/dpkg/creator.rb +39 -29
- data/lib/cany/dpkg/deb_helper_recipe.rb +105 -20
- data/lib/cany/errors.rb +62 -0
- data/lib/cany/mixins/depend_mixin.rb +22 -0
- data/lib/cany/recipe.rb +182 -11
- data/lib/cany/recipes/bundler.rb +28 -5
- data/lib/cany/recipes/bundler/gem.rb +50 -0
- data/lib/cany/recipes/bundler/gem_db.rb +27 -0
- data/lib/cany/recipes/rails.rb +19 -2
- data/lib/cany/recipes/sidekiq.rb +38 -0
- data/lib/cany/recipes/thin.rb +24 -18
- data/lib/cany/recipes/unicorn.rb +16 -0
- data/lib/cany/recipes/web_server.rb +5 -19
- data/lib/cany/specification.rb +49 -1
- data/lib/cany/specification/dsl.rb +23 -3
- data/lib/cany/version.rb +2 -2
- data/spec/cany/dependency_spec.rb +120 -0
- data/spec/cany/dpkg/builder_spec.rb +38 -0
- data/spec/{dpkg → cany/dpkg}/creator_spec.rb +26 -2
- data/spec/cany/dpkg/deb_helper_recipe_spec.rb +91 -0
- data/spec/cany/recipe_spec.rb +213 -0
- data/spec/cany/recipes/bundler/gem_spec.rb +46 -0
- data/spec/cany/recipes/bundler_spec.rb +29 -0
- data/spec/cany/recipes/rails_spec.rb +28 -0
- data/spec/cany/recipes/sidekiq_spec.rb +52 -0
- data/spec/cany/specification_spec.rb +113 -1
- data/spec/spec_helper.rb +31 -4
- metadata +29 -6
- data/spec/dpkg/builder_spec.rb +0 -53
@@ -20,6 +20,11 @@ describe Cany::Dpkg::Creator do
|
|
20
20
|
end
|
21
21
|
let(:run) { Cany::Dpkg::Creator.new(spec).run *(@run_args || []) }
|
22
22
|
|
23
|
+
it 'should set the system recipe' do
|
24
|
+
expect(spec).to receive(:system_recipe=).with(kind_of(Cany::Dpkg::DebHelperRecipe)).and_call_original
|
25
|
+
run
|
26
|
+
end
|
27
|
+
|
23
28
|
context 'debian directory' do
|
24
29
|
subject { File.join dir, 'debian' }
|
25
30
|
|
@@ -45,7 +50,7 @@ describe Cany::Dpkg::Creator do
|
|
45
50
|
it do
|
46
51
|
run
|
47
52
|
expect(subject).to be_a_file
|
48
|
-
expect(subject).to have_the_content '
|
53
|
+
expect(subject).to have_the_content '9'
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
@@ -128,7 +133,10 @@ describe Cany::Dpkg::Creator do
|
|
128
133
|
end
|
129
134
|
|
130
135
|
it 'should add extra deps in specific gems are used' do
|
131
|
-
FileUtils.copy File.expand_path('
|
136
|
+
FileUtils.copy File.expand_path('../../../fixtures/testgem.lock', __FILE__), File.join(dir, 'Gemfile.lock')
|
137
|
+
spec.setup do
|
138
|
+
use :bundler
|
139
|
+
end
|
132
140
|
run
|
133
141
|
expect(subject.paragraphs.size).to eq 2
|
134
142
|
source =
|
@@ -200,6 +208,22 @@ describe Cany::Dpkg::Creator do
|
|
200
208
|
expect(subject).to include "\truby1.9.1 -S cany dpkg-builder $@"
|
201
209
|
expect(subject).to include "\truby1.9.1 -cS cany >/dev/null || ruby1.9.1 -S gem install --no-ri --no-rdoc --install-dir debian/gems --bindir debian/bin $${CANY_GEM:-cany}"
|
202
210
|
end
|
211
|
+
|
212
|
+
it 'should contain cany version constraint' do
|
213
|
+
expect(Cany::VERSION).to receive(:to_s).and_return('0.1').at_least(:once)
|
214
|
+
spec.setup { require_cany '~> 0.1' }
|
215
|
+
run
|
216
|
+
|
217
|
+
should match /gem install.+ \$\${CANY_GEM:-cany}.+--version "~> 0\.1"/
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'should allow pre cany versions if the contraint contain characters' do
|
221
|
+
expect(Cany::VERSION).to receive(:to_s).and_return('0.1.rc2').at_least(:once)
|
222
|
+
spec.setup { require_cany '~> 0.1.rc1' }
|
223
|
+
run
|
224
|
+
|
225
|
+
should match /gem install.+ \$\${CANY_GEM:-cany}.+--version "~> 0\.1\.rc1" --prerelease/
|
226
|
+
end
|
203
227
|
end
|
204
228
|
|
205
229
|
context 'changelog file' do
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cany::Dpkg::DebHelperRecipe do
|
4
|
+
let!(:dir) { Dir.mktmpdir }
|
5
|
+
before do
|
6
|
+
Dir.mkdir File.join(dir, 'debian')
|
7
|
+
@old_path = Dir.pwd
|
8
|
+
Dir.chdir(dir)
|
9
|
+
end
|
10
|
+
after do
|
11
|
+
Dir.chdir @old_path
|
12
|
+
FileUtils.remove_entry dir
|
13
|
+
end
|
14
|
+
let(:spec) do
|
15
|
+
s = Cany::Specification.new do
|
16
|
+
name 'test'
|
17
|
+
description 'Your RSpec Upstart-Scripts'
|
18
|
+
end
|
19
|
+
s.base_dir = dir
|
20
|
+
s
|
21
|
+
end
|
22
|
+
let(:recipe) { described_class.new spec }
|
23
|
+
subject { recipe }
|
24
|
+
|
25
|
+
describe '#binary' do
|
26
|
+
it 'should install services' do
|
27
|
+
should receive(:install_services)
|
28
|
+
subject.binary
|
29
|
+
end
|
30
|
+
it 'should install base service' do
|
31
|
+
should receive(:install_base_service)
|
32
|
+
subject.binary
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#install_services' do
|
37
|
+
before do
|
38
|
+
recipe.install_service :service, %w(hans args1), user: 'www-data', group: 'www-data'
|
39
|
+
recipe.install_services
|
40
|
+
end
|
41
|
+
subject { File.read File.join(dir, 'debian', 'test.test-service.upstart') }
|
42
|
+
|
43
|
+
it 'should create files' do
|
44
|
+
should eq <<EOF
|
45
|
+
description "Your RSpec Upstart-Scripts - service"
|
46
|
+
|
47
|
+
start on started test
|
48
|
+
stop on stopping test
|
49
|
+
|
50
|
+
respawn
|
51
|
+
respawn limit 10 5
|
52
|
+
umask 022
|
53
|
+
|
54
|
+
chdir /usr/share/test
|
55
|
+
|
56
|
+
setuid www-data
|
57
|
+
setgid www-data
|
58
|
+
|
59
|
+
exec hans args1
|
60
|
+
EOF
|
61
|
+
expect(@executed_programs).to match_array [['dh_installinit', '--name', 'test-service']]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#install_base_services' do
|
66
|
+
before do
|
67
|
+
recipe.configure :service_pre_scripts, mkdir_run: "mkdir /var/run/#{spec.name}", chown_run: "chown www-data /var/run/#{spec.name}"
|
68
|
+
Dir.chdir(dir) { recipe.install_base_service }
|
69
|
+
end
|
70
|
+
subject { File.read File.join(dir, 'debian', 'test.upstart') }
|
71
|
+
it 'should create files' do
|
72
|
+
should eq <<EOF
|
73
|
+
description "Your RSpec Upstart-Scripts"
|
74
|
+
|
75
|
+
start on filesystem or runlevel [2345]
|
76
|
+
stop on runlevel [!2345]
|
77
|
+
|
78
|
+
respawn
|
79
|
+
respawn limit 10 5
|
80
|
+
umask 022
|
81
|
+
|
82
|
+
pre-start script
|
83
|
+
mkdir /var/run/test
|
84
|
+
chown www-data /var/run/test
|
85
|
+
end script
|
86
|
+
|
87
|
+
exec sleep 1d
|
88
|
+
EOF
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cany::Recipe do
|
4
|
+
let(:spec) do
|
5
|
+
Cany::Specification.new do
|
6
|
+
name 'test-spec'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
let(:recipe) { Cany::Recipe.new(spec) }
|
10
|
+
let(:test_recipe) { TestRecipe.new(spec) }
|
11
|
+
|
12
|
+
describe '#exec' do
|
13
|
+
it 'should execute system command' do
|
14
|
+
expect(recipe).to receive(:system).with('a', 'b', 'c').and_return true
|
15
|
+
recipe.exec_('a', 'b', 'c')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should flatten the passed arguments' do
|
19
|
+
expect(recipe).to receive(:system).with('a', 'b', 'c').and_return true
|
20
|
+
recipe.exec_(%w(a b c))
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should flatten the passed arguments #2' do
|
24
|
+
expect(recipe).to receive(:system).with('a', 'b', 'c', 'd', 'e', 'f').and_return true
|
25
|
+
recipe.exec_('a', %w(b c), 'd', ['e', 'f'])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should raise an exception on failed program execution' do
|
29
|
+
expect { recipe.exec_ 'false' }.to raise_exception Cany::CommandExecutionFailed, /Could not execute.*false/
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should raise an exception on failed program execution with args' do
|
33
|
+
expect { recipe.exec_ %w(false 4) }.to raise_exception Cany::CommandExecutionFailed, /Could not execute.*false 4/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'hook handling' do
|
38
|
+
it 'should raise an error on an unknown hooks' do
|
39
|
+
expect { recipe.run_hook :test, :after }.to raise_exception Cany::UnknownHook, /Unknown hook.*test/
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should handle hooks without defined block' do
|
43
|
+
test_recipe.run_hook :test_hook, :after
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should passed block for hook' do
|
47
|
+
expect(Cany).to receive(:hook_executed)
|
48
|
+
spec.setup do
|
49
|
+
use :test_recipe do
|
50
|
+
before :test_hook do
|
51
|
+
Cany.hook_executed
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
spec.recipes[0].run_hook :test_hook, :before
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'hook should be limited to recipe' do
|
59
|
+
expect do
|
60
|
+
spec.setup do
|
61
|
+
use :bundler do
|
62
|
+
before :test_hook do
|
63
|
+
Dummy.hook_executed
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end.to raise_exception Cany::UnknownHook, /Unknown hook.*test_hook/
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'recipe configure options' do
|
72
|
+
let(:option_name) { :test_conf }
|
73
|
+
subject { test_recipe.option option_name }
|
74
|
+
|
75
|
+
context 'with an undefined config' do
|
76
|
+
let(:option_name) { :unknown_option }
|
77
|
+
it 'should raise an exception' do
|
78
|
+
expect { subject }.to raise_exception Cany::UnknownOption, /Unknown option .*unknown_option/
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'with a defined config' do
|
83
|
+
let(:recipe2) { Cany::Recipe.new(spec) }
|
84
|
+
it 'should be initialized with {} per default' do
|
85
|
+
expect(subject).to eq Hash.new
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'should be configurable' do
|
89
|
+
before do
|
90
|
+
test_recipe.configure :test_conf, env: 'production'
|
91
|
+
end
|
92
|
+
it { expect(subject).to eq(env: 'production') }
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'options should be merged between multiple calls' do
|
96
|
+
before do
|
97
|
+
test_recipe.configure :test_conf, env: 'production'
|
98
|
+
test_recipe.configure :test_conf, env2: 'hans'
|
99
|
+
end
|
100
|
+
it { expect(subject).to eq(env: 'production', env2: 'hans') }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#recipe' do
|
106
|
+
let(:other_recipe) { :test_recipe }
|
107
|
+
subject { recipe.recipe other_recipe }
|
108
|
+
context 'to access other loaded recipe' do
|
109
|
+
before { spec.setup { use :test_recipe } }
|
110
|
+
it 'should return the recipe instance from this specification' do
|
111
|
+
expect(subject).to be spec.recipes.first
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'to access an unloaded recipe' do
|
116
|
+
it 'should raise an exception' do
|
117
|
+
expect { subject }.to raise_exception Cany::UnloadedRecipe, /[Rr]ecipe.+test_recipe.+no.+loaded/
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'to access an unknown recipe' do
|
122
|
+
let(:other_recipe) { :unknown_recipe }
|
123
|
+
it 'should raise an exception' do
|
124
|
+
expect { subject }.to raise_exception Cany::UnknownRecipe, /[Rr]ecipe.+unknown_recipe.+not.+registered./
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#depend' do
|
130
|
+
subject { spec.dependencies }
|
131
|
+
|
132
|
+
context 'without any call' do
|
133
|
+
it 'it should be empty' do
|
134
|
+
should eq []
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'with a single string' do
|
139
|
+
subject { super().first }
|
140
|
+
|
141
|
+
context 'without other options' do
|
142
|
+
before { recipe.depend 'hans-otto-lib' }
|
143
|
+
it 'should converted into a runtime dependency object' do
|
144
|
+
should be_instance_of Cany::Dependency
|
145
|
+
should be_runtime
|
146
|
+
should_not be_build
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'with situation option' do
|
151
|
+
before { recipe.depend 'hans-otto-lib', situation: :build }
|
152
|
+
it 'should converted into a runtime dependency object' do
|
153
|
+
should be_instance_of Cany::Dependency
|
154
|
+
should_not be_runtime
|
155
|
+
should be_build
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'with a version option' do
|
160
|
+
before { recipe.depend 'hans-otto', version: '>= 4' }
|
161
|
+
it 'should be convert' do
|
162
|
+
should be_instance_of Cany::Dependency
|
163
|
+
expect(subject.determine(:a, :b)).to match_array [['hans-otto', '>= 4']]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
context 'with a dependency object' do
|
168
|
+
let(:dep) { Cany::Dependency.new }
|
169
|
+
subject { super().first }
|
170
|
+
before { recipe.depend dep }
|
171
|
+
it 'should be passed without modification' do
|
172
|
+
should eq dep
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context '#name' do
|
178
|
+
context 'on an unregistered recipe' do
|
179
|
+
subject { recipe.name }
|
180
|
+
it 'should raise a NoMethodError' do
|
181
|
+
expect { subject }.to raise_exception NoMethodError
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'on a registered recipe' do
|
186
|
+
subject { test_recipe.name }
|
187
|
+
it 'should return its registered name' do
|
188
|
+
should eq :test_recipe
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context '#install_service' do
|
194
|
+
let(:name) { :test }
|
195
|
+
let(:command) { :command }
|
196
|
+
let(:opts) { {} }
|
197
|
+
subject { recipe.install_service name, command, opts }
|
198
|
+
|
199
|
+
context 'on recipe without loaded system recipe' do
|
200
|
+
it 'should raise an exception' do
|
201
|
+
expect { subject }.to raise_exception Cany::NoSystemRecipe
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'with loaded deb helper recipe' do
|
206
|
+
before { spec.system_recipe = Cany::Dpkg::DebHelperRecipe.new spec }
|
207
|
+
it 'should pass call to system recipe' do
|
208
|
+
expect_any_instance_of(Cany::Dpkg::DebHelperRecipe).to receive(:install_service).with(name, command, opts)
|
209
|
+
subject
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cany::Recipes::Bundler::Gem do
|
4
|
+
let(:gem_name) { :bundler }
|
5
|
+
subject { described_class.get gem_name }
|
6
|
+
context '#get' do
|
7
|
+
it 'should return always the same instance per gem' do
|
8
|
+
should be_instance_of described_class
|
9
|
+
expect(subject).to eq described_class.get gem_name
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should return different instances for different gems' do
|
13
|
+
should_not eq described_class.get :bundler2
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'returned gem instance' do
|
17
|
+
context '\s gem_name' do
|
18
|
+
subject { super().name }
|
19
|
+
it { eq gem_name }
|
20
|
+
end
|
21
|
+
|
22
|
+
context '\' dependencies' do
|
23
|
+
subject { super().dependencies }
|
24
|
+
it 'should be empty per default' do
|
25
|
+
should match_array []
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context '#specify' do
|
32
|
+
subject { super().dependencies.first }
|
33
|
+
let(:default) { subject.determine(:a, :b).first }
|
34
|
+
context 'with added dependencies' do
|
35
|
+
before do
|
36
|
+
described_class.specify gem_name do
|
37
|
+
depend 'hans_otto'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
it 'should added as runtime dependencies' do
|
41
|
+
should be_runtime
|
42
|
+
expect(default).to match_array [ 'hans_otto', nil]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cany::Recipes::Bundler do
|
4
|
+
let(:spec) do
|
5
|
+
Cany::Specification.new do
|
6
|
+
name 'test'
|
7
|
+
use :bundler
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:recipe) { spec.recipes[0] }
|
11
|
+
before { recipe.prepare }
|
12
|
+
|
13
|
+
context 'wrapper-script' do
|
14
|
+
subject { recipe.wrapper_script }
|
15
|
+
context 'without additional env variables' do
|
16
|
+
it 'should contain GEM_PATH to find bundler' do
|
17
|
+
expect(subject).to include('export GEM_PATH="bundler"')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with additional env variables' do
|
22
|
+
before { recipe.configure :env_vars, RAILS_ENV: 'production' }
|
23
|
+
it 'should contain all environment variables' do
|
24
|
+
expect(subject).to include('export GEM_PATH="bundler"')
|
25
|
+
expect(subject).to include('export RAILS_ENV="production"')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cany::Recipes::Rails do
|
4
|
+
describe 'DSL' do
|
5
|
+
let(:spec) do
|
6
|
+
Cany::Specification.new do
|
7
|
+
name 'test'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:recipe) { spec.recipes[0] }
|
11
|
+
|
12
|
+
it 'should compile assets by default' do
|
13
|
+
spec.setup do
|
14
|
+
use :rails
|
15
|
+
end
|
16
|
+
expect(recipe.compile_assets).to eq true
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should be able to disable assets compilation' do
|
20
|
+
spec.setup do
|
21
|
+
use :rails do
|
22
|
+
compile_assets false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
expect(recipe.compile_assets).to eq false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|