omnibus 5.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +26 -0
  5. data/Gemfile +3 -0
  6. data/MAINTAINERS.md +1 -0
  7. data/appveyor.yml +1 -1
  8. data/bin/omnibus +5 -0
  9. data/lib/omnibus/builder.rb +165 -26
  10. data/lib/omnibus/digestable.rb +4 -2
  11. data/lib/omnibus/fetcher.rb +18 -5
  12. data/lib/omnibus/fetchers/git_fetcher.rb +38 -22
  13. data/lib/omnibus/fetchers/net_fetcher.rb +106 -37
  14. data/lib/omnibus/fetchers/path_fetcher.rb +13 -12
  15. data/lib/omnibus/file_syncer.rb +33 -14
  16. data/lib/omnibus/generator_files/README.md.erb +1 -1
  17. data/lib/omnibus/generator_files/package_scripts/postinst.erb +3 -3
  18. data/lib/omnibus/generator_files/package_scripts/postrm.erb +1 -1
  19. data/lib/omnibus/generator_files/package_scripts/preinst.erb +1 -1
  20. data/lib/omnibus/generator_files/package_scripts/prerm.erb +3 -3
  21. data/lib/omnibus/git_cache.rb +20 -7
  22. data/lib/omnibus/health_check.rb +144 -12
  23. data/lib/omnibus/packagers/bff.rb +57 -5
  24. data/lib/omnibus/packagers/deb.rb +2 -2
  25. data/lib/omnibus/packagers/pkg.rb +2 -2
  26. data/lib/omnibus/packagers/solaris.rb +18 -6
  27. data/lib/omnibus/project.rb +1 -1
  28. data/lib/omnibus/s3_cache.rb +8 -2
  29. data/lib/omnibus/software.rb +152 -18
  30. data/lib/omnibus/sugarable.rb +1 -5
  31. data/lib/omnibus/util.rb +1 -1
  32. data/lib/omnibus/version.rb +1 -1
  33. data/omnibus.gemspec +4 -1
  34. data/resources/bff/config.erb +7 -0
  35. data/resources/deb/md5sums.erb +1 -1
  36. data/spec/functional/builder_spec.rb +89 -2
  37. data/spec/functional/fetchers/git_fetcher_spec.rb +44 -37
  38. data/spec/functional/fetchers/net_fetcher_spec.rb +36 -5
  39. data/spec/functional/fetchers/path_fetcher_spec.rb +28 -28
  40. data/spec/unit/builder_spec.rb +143 -11
  41. data/spec/unit/fetchers/git_fetcher_spec.rb +23 -59
  42. data/spec/unit/fetchers/net_fetcher_spec.rb +151 -63
  43. data/spec/unit/fetchers/path_fetcher_spec.rb +4 -35
  44. data/spec/unit/git_cache_spec.rb +13 -14
  45. data/spec/unit/health_check_spec.rb +90 -0
  46. data/spec/unit/library_spec.rb +1 -1
  47. data/spec/unit/packagers/bff_spec.rb +126 -3
  48. data/spec/unit/packagers/deb_spec.rb +8 -3
  49. data/spec/unit/packagers/pkg_spec.rb +19 -19
  50. data/spec/unit/packagers/solaris_spec.rb +13 -1
  51. data/spec/unit/software_spec.rb +242 -38
  52. metadata +7 -6
  53. data/lib/omnibus/generator_files/package_scripts/makeselfinst.erb +0 -0
@@ -21,6 +21,8 @@ module Omnibus
21
21
  end
22
22
 
23
23
  subject { described_class.new(manifest_entry, project_dir, build_dir) }
24
+
25
+ let(:revision) { shellout!('git rev-parse HEAD', cwd: project_dir).stdout.strip }
24
26
 
25
27
  describe '#fetch_required?' do
26
28
  context 'when the repo is not cloned' do
@@ -32,15 +34,16 @@ module Omnibus
32
34
  context 'when the repo is cloned' do
33
35
  before { subject.fetch }
34
36
 
35
- context 'when the revisions are different' do
36
- it 'return true' do
37
- # Dirty the project_dir to differ the revisions
38
- Dir.chdir(project_dir) do
39
- FileUtils.touch("file-#{Time.now.to_i}")
40
- git %|add .|
41
- git %|commit -am "Add new file"|
42
- end
37
+ context 'when the revision is not available' do
38
+ let(:manifest_entry) do
39
+ double(ManifestEntry,
40
+ name: 'software',
41
+ locked_version: 'abcdefabcdef5d66ed866b2c3eb418426e6382b0',
42
+ described_version: version,
43
+ locked_source: source)
44
+ end
43
45
 
46
+ it 'return true' do
44
47
  expect(subject.fetch_required?).to be_truthy
45
48
  end
46
49
  end
@@ -60,37 +63,49 @@ module Omnibus
60
63
  end
61
64
 
62
65
  describe '#clean' do
63
- context 'when the project directory exists' do
64
- before do
65
- subject.fetch
66
- create_file("#{project_dir}/file_a")
67
- create_file("#{project_dir}/.file_b")
68
- end
66
+ before do
67
+ subject.fetch
68
+ end
69
+
70
+ it 'returns true' do
71
+ expect(subject.clean).to be_truthy
72
+ end
69
73
 
74
+ context 'when the project directory has extra files in it' do
70
75
  it 'cleans the git repo' do
76
+ create_file("#{project_dir}/file_a")
77
+ create_file("#{project_dir}/.file_b")
71
78
  subject.clean
72
79
  expect("#{project_dir}/file_a").to_not be_a_file
73
80
  expect("#{project_dir}/.file_b").to_not be_a_file
74
81
  end
75
-
76
- it 'returns true' do
77
- expect(subject.clean).to be_truthy
78
- end
79
82
  end
80
83
 
81
- context 'when the project directory does not exist' do
84
+ context 'when the project directory is at a different version' do
82
85
  before do
83
- remove_directory(project_dir)
86
+ # Dirty the project_dir by giving it a conflicting commit.
87
+ create_file("#{project_dir}/file_a") { 'some new file' }
88
+ create_file("#{project_dir}/configure") { 'LALALALA' }
89
+ shellout!('git add .', cwd: project_dir)
90
+ shellout!('git commit -am "Some commit"', cwd: project_dir)
91
+ create_file("#{project_dir}/.file_b")
84
92
  end
85
93
 
86
- it 'returns false' do
87
- expect(subject.clean).to be(false)
94
+ it 'checks out the right version' do
95
+ subject.clean
96
+ expect(revision).to eq(manifest_entry.locked_version)
97
+ end
98
+
99
+ it 'resets the working tree' do
100
+ subject.clean
101
+ expect("#{project_dir}/file_a").to_not be_a_file
102
+ expect("#{project_dir}/.file_b").to_not be_a_file
103
+ expect(File.read("#{project_dir}/configure")).to_not match('LA')
88
104
  end
89
105
  end
90
106
  end
91
107
 
92
108
  describe '#fetch' do
93
- let(:revision) { shellout!('git rev-parse HEAD', cwd: project_dir).stdout.strip }
94
109
  let(:version) { 'v1.2.4' }
95
110
  let(:remote) { remote_git_repo('zlib', annotated_tags: [version]) }
96
111
  let(:manifest_entry) do
@@ -108,11 +123,6 @@ module Omnibus
108
123
  subject.fetch
109
124
  expect("#{project_dir}/.git").to be_a_directory
110
125
  end
111
-
112
- it 'fetches the locked_version from the manifest' do
113
- subject.fetch
114
- expect(revision).to eq(manifest_entry.locked_version)
115
- end
116
126
  end
117
127
 
118
128
 
@@ -173,18 +183,15 @@ module Omnibus
173
183
  end
174
184
 
175
185
  describe '#version_for_cache' do
176
- let(:revision) { shellout!('git rev-parse HEAD', cwd: project_dir).stdout.strip }
177
-
178
- it 'includes the revision' do
179
- expect(subject.version_for_cache).to eq("revision:#{revision}")
186
+ it 'includes the resolved revision' do
187
+ expect(subject.version_for_cache).to eq('revision:45ded6d3b1a35d66ed866b2c3eb418426e6382b0')
180
188
  end
181
189
 
182
- it 'does not returned cached revision after fetching' do
183
- before_fetch = subject.version_for_cache
190
+ it 'not use the current version on disk after fetching' do
191
+ expect(subject.version_for_cache).to eq('revision:45ded6d3b1a35d66ed866b2c3eb418426e6382b0')
184
192
  subject.fetch
185
- after_fetch = revision
186
- expect(subject.version_for_cache).to eq("revision:#{after_fetch}")
187
- expect(subject.version_for_cache).not_to eq("revision:#{before_fetch}")
193
+ expect(subject.version_for_cache).to eq('revision:45ded6d3b1a35d66ed866b2c3eb418426e6382b0')
194
+ expect(revision).to_not eq('revision:45ded6d3b1a35d66ed866b2c3eb418426e6382b0')
188
195
  end
189
196
  end
190
197
  end
@@ -1,6 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Omnibus
4
+ module RSpec
5
+ module OhaiHelpers
6
+ # Turn off the mandatory Ohai helper.
7
+ def stub_ohai(options = {}, &block)
8
+ end
9
+ end
10
+ end
11
+
4
12
  describe NetFetcher do
5
13
  include_examples 'a software', 'zlib'
6
14
 
@@ -119,6 +127,34 @@ module Omnibus
119
127
  expect(subject.clean).to be(false)
120
128
  end
121
129
  end
130
+
131
+ context 'when the source has read-only files' do
132
+ let(:source_url) { 'http://dl.bintray.com/oneclick/OpenKnapsack/x86/openssl-1.0.0q-x86-windows.tar.lzma' }
133
+ let(:source_md5) { '577dbe528415c6f178a9431fd0554df4' }
134
+
135
+ it 'extracts the asset without crashing' do
136
+ subject.clean
137
+ expect(extracted).to_not be_a_file
138
+ subject.clean
139
+ expect(extracted).to_not be_a_file
140
+ end
141
+ end
142
+
143
+ context 'when the source has broken symlinks' do
144
+ let(:source_url) { 'http://www.openssl.org/source/openssl-1.0.1q.tar.gz' }
145
+ let(:source_md5) { '54538d0cdcb912f9bc2b36268388205e' }
146
+
147
+ let(:source) do
148
+ { url: source_url, md5: source_md5, extract: :lax_tar }
149
+ end
150
+
151
+ it 'extracts the asset without crashing' do
152
+ subject.clean
153
+ expect(extracted).to_not be_a_file
154
+ subject.clean
155
+ expect(extracted).to_not be_a_file
156
+ end
157
+ end
122
158
  end
123
159
 
124
160
  describe '#fetch' do
@@ -218,11 +254,6 @@ module Omnibus
218
254
  expect(retry_count).to eq(Omnibus::Config.fetcher_retries)
219
255
  end
220
256
 
221
- it 'extracts the file' do
222
- fetch!
223
- expect(extracted).to be_a_directory
224
- end
225
-
226
257
  context 'when the file is less than 10240 bytes' do
227
258
  let(:source_url) { 'https://downloads.chef.io/packages-chef-io-public.key' }
228
259
  let(:source_md5) { '369efc3a19b9118cdf51c7e87a34f266' }
@@ -55,45 +55,45 @@ module Omnibus
55
55
  end
56
56
  end
57
57
 
58
- describe '#clean' do
59
- context 'when the project directory exists' do
60
- before do
61
- create_file("#{source_path}/file_a")
62
- create_file("#{source_path}/file_b")
63
- create_file("#{source_path}/.file_c")
64
-
65
- create_file("#{project_dir}/file_a")
66
- end
58
+ describe "#fetch" do
59
+ before do
60
+ create_file("#{source_path}/file_a")
61
+ create_file("#{source_path}/file_b")
62
+ create_file("#{source_path}/.file_c")
63
+ remove_file("#{source_path}/file_d")
67
64
 
68
- it 'fetches new files' do
69
- subject.clean
65
+ create_file("#{project_dir}/file_a")
66
+ remove_file("#{project_dir}/file_b")
67
+ remove_file("#{project_dir}/.file_c")
68
+ create_file("#{project_dir}/file_d")
69
+ end
70
70
 
71
- expect("#{project_dir}/file_a").to be_a_file
72
- expect("#{project_dir}/file_b").to be_a_file
73
- expect("#{project_dir}/.file_c").to be_a_file
74
- end
71
+ it 'fetches new files' do
72
+ subject.fetch
75
73
 
76
- it 'returns true' do
77
- expect(subject.clean).to be_truthy
78
- end
74
+ expect("#{project_dir}/file_a").to be_a_file
75
+ expect("#{project_dir}/file_b").to be_a_file
76
+ expect("#{project_dir}/.file_c").to be_a_file
79
77
  end
80
78
 
81
- context 'when the project directory does not exist' do
82
- before do
83
- remove_directory(project_dir)
84
- end
79
+ it 'removes extraneous files' do
80
+ subject.fetch
85
81
 
86
- it 'returns false' do
87
- expect(subject.clean).to be(false)
88
- end
82
+ expect("#{project_dir}/file_d").to_not be_a_file
83
+ end
84
+ end
85
+
86
+ describe '#clean' do
87
+ it 'returns true' do
88
+ expect(subject.clean).to be_truthy
89
89
  end
90
90
  end
91
91
 
92
92
  describe '#version_for_cache' do
93
93
  before do
94
- create_file("#{project_dir}/file_a")
95
- create_file("#{project_dir}/file_b")
96
- create_file("#{project_dir}/.file_c")
94
+ create_file("#{source_path}/file_a")
95
+ create_file("#{source_path}/file_b")
96
+ create_file("#{source_path}/.file_c")
97
97
  end
98
98
 
99
99
  let(:sha) { '69553b23b84e69e095b4a231877b38022b1ffb41ae0ecbba6bb2625410c49f7e' }
@@ -5,22 +5,32 @@ module Omnibus
5
5
  let(:software) do
6
6
  double(Software,
7
7
  name: 'chefdk',
8
- install_dir: '/opt/chefdk',
9
- project_dir: '/opt/chefdk',
8
+ install_dir: project_dir,
9
+ project_dir: project_dir,
10
10
  )
11
11
  end
12
12
 
13
+ let(:project_dir) { on_windows ? 'C:/opscode/chefdk' : '/opt/chefdk' }
14
+ let(:on_windows) { false }
15
+ let(:msys_bash) { "C:\\opscode\\chefdk\\embedded\\msys\\1.0\\bin\\bash.exe" }
16
+
17
+ def run_build_command
18
+ subject.send(:build_commands)[0].run(subject)
19
+ end
20
+
13
21
  subject { described_class.new(software) }
14
22
 
15
- describe '#command' do
16
- it 'is a DSL method' do
17
- expect(subject).to have_exposed_method(:command)
23
+ before do
24
+ allow(subject).to receive(:windows?).and_return(on_windows)
25
+ allow(subject).to receive(:windows_safe_path) do |*args|
26
+ path = File.join(*args)
27
+ path.gsub!(File::SEPARATOR, '\\') if on_windows
18
28
  end
19
29
  end
20
30
 
21
- describe '#patch' do
31
+ describe '#command' do
22
32
  it 'is a DSL method' do
23
- expect(subject).to have_exposed_method(:patch)
33
+ expect(subject).to have_exposed_method(:command)
24
34
  end
25
35
  end
26
36
 
@@ -108,6 +118,12 @@ module Omnibus
108
118
  end
109
119
  end
110
120
 
121
+ describe '#update_config_guess' do
122
+ it 'is a DSL method' do
123
+ expect(subject).to have_exposed_method(:update_config_guess)
124
+ end
125
+ end
126
+
111
127
  describe '#windows_safe_path' do
112
128
  it 'is a DSL method' do
113
129
  expect(subject).to have_exposed_method(:windows_safe_path)
@@ -131,10 +147,14 @@ module Omnibus
131
147
  allow(subject).to receive(:command)
132
148
  end
133
149
 
150
+ it 'is a DSL method' do
151
+ expect(subject).to have_exposed_method(:make)
152
+ end
153
+
134
154
  context 'when :bin is present' do
135
155
  it 'uses the custom bin' do
136
156
  expect(subject).to receive(:command)
137
- .with('/path/to/make', {})
157
+ .with('/path/to/make', in_msys_bash: true)
138
158
  subject.make(bin: '/path/to/make')
139
159
  end
140
160
  end
@@ -148,7 +168,7 @@ module Omnibus
148
168
 
149
169
  it 'uses gmake and sets MAKE=gmake' do
150
170
  expect(subject).to receive(:command)
151
- .with('gmake', env: { 'MAKE' => 'gmake' })
171
+ .with('gmake', env: { 'MAKE' => 'gmake' }, in_msys_bash: true)
152
172
  subject.make
153
173
  end
154
174
  end
@@ -161,26 +181,138 @@ module Omnibus
161
181
 
162
182
  it 'uses make' do
163
183
  expect(subject).to receive(:command)
164
- .with('make', {})
184
+ .with('make', in_msys_bash: true)
165
185
  subject.make
166
186
  end
167
187
  end
168
188
 
169
189
  it 'accepts 0 options' do
190
+ expect(subject).to receive(:command)
191
+ .with('make', in_msys_bash: true)
170
192
  expect { subject.make }.to_not raise_error
171
193
  end
172
194
 
173
195
  it 'accepts an additional command string' do
196
+ expect(subject).to receive(:command)
197
+ .with('make install', in_msys_bash: true)
174
198
  expect { subject.make('install') }.to_not raise_error
175
199
  end
176
200
 
177
201
  it 'persists given options' do
178
202
  expect(subject).to receive(:command)
179
- .with(anything(), timeout: 3600)
203
+ .with('make', timeout: 3600, in_msys_bash: true)
180
204
  subject.make(timeout: 3600)
181
205
  end
182
206
  end
183
207
 
208
+ describe '#configure' do
209
+ before do
210
+ allow(subject).to receive(:command)
211
+ end
212
+
213
+ it 'is a DSL method' do
214
+ expect(subject).to have_exposed_method(:configure)
215
+ end
216
+
217
+ context 'on 64-bit windows' do
218
+ let(:on_windows) { true }
219
+ let(:windows_i386) { false }
220
+
221
+ before do
222
+ allow(subject).to receive(:windows_arch_i386?)
223
+ .and_return(windows_i386)
224
+ end
225
+
226
+ it 'invokes appends platform host to the options' do
227
+ expect(subject).to receive(:command)
228
+ .with("./configure --host=x86_64-w64-mingw32 --prefix=#{project_dir}/embedded", in_msys_bash: true)
229
+ subject.configure()
230
+ end
231
+ end
232
+
233
+ context 'when :bin is present' do
234
+ it 'uses the custom bin' do
235
+ expect(subject).to receive(:command)
236
+ .with("/path/to/configure --prefix=#{project_dir}/embedded", in_msys_bash: true)
237
+ subject.configure(bin: '/path/to/configure')
238
+ end
239
+ end
240
+
241
+ context 'when :prefix is present' do
242
+ it 'emits non-empty prefix' do
243
+ expect(subject).to receive(:command)
244
+ .with("./configure --prefix=/some/prefix", in_msys_bash: true)
245
+ subject.configure(prefix: '/some/prefix')
246
+ end
247
+
248
+ it 'omits prefix if empty' do
249
+ expect(subject).to receive(:command)
250
+ .with("./configure", in_msys_bash: true)
251
+ subject.configure(prefix: '')
252
+ end
253
+ end
254
+
255
+ it 'accepts 0 options' do
256
+ expect(subject).to receive(:command)
257
+ .with("./configure --prefix=#{project_dir}/embedded", in_msys_bash: true)
258
+ expect { subject.configure }.to_not raise_error
259
+ end
260
+
261
+ it 'accepts an additional command string' do
262
+ expect(subject).to receive(:command)
263
+ .with("./configure --prefix=#{project_dir}/embedded --myopt", in_msys_bash: true)
264
+ expect { subject.configure('--myopt') }.to_not raise_error
265
+ end
266
+
267
+ it 'persists given options' do
268
+ expect(subject).to receive(:command)
269
+ .with("./configure --prefix=#{project_dir}/embedded", timeout: 3600, in_msys_bash: true)
270
+ subject.configure(timeout: 3600)
271
+ end
272
+ end
273
+
274
+ describe '#patch' do
275
+ before do
276
+ allow(subject).to receive(:find_file)
277
+ .with('config/patches', 'good_patch')
278
+ .and_return(
279
+ [ ["#{project_dir}/patch_location1/good_patch", "#{project_dir}/patch_location2/good_patch"],
280
+ "#{project_dir}/patch_location2/good_patch" ])
281
+ end
282
+
283
+ it 'is a DSL method' do
284
+ expect(subject).to have_exposed_method(:patch)
285
+ end
286
+
287
+ it 'invokes patch with patch level 1 unless specified' do
288
+ expect { subject.patch(source: 'good_patch') }.to_not raise_error
289
+ expect(subject).to receive(:shellout!)
290
+ .with("patch -p1 -i #{project_dir}/patch_location2/good_patch", in_msys_bash: true)
291
+ run_build_command
292
+ end
293
+
294
+ it 'invokes patch with patch level provided' do
295
+ expect { subject.patch(source: 'good_patch', plevel: 0) }.to_not raise_error
296
+ expect(subject).to receive(:shellout!)
297
+ .with("patch -p0 -i #{project_dir}/patch_location2/good_patch", in_msys_bash: true)
298
+ run_build_command
299
+ end
300
+
301
+ it 'invokes patch differently if target is provided' do
302
+ expect { subject.patch(source: 'good_patch', target: 'target/path') }.to_not raise_error
303
+ expect(subject).to receive(:shellout!)
304
+ .with("cat #{project_dir}/patch_location2/good_patch | patch -p1 target/path", in_msys_bash: true)
305
+ run_build_command
306
+ end
307
+
308
+ it 'persists other options' do
309
+ expect { subject.patch(source: 'good_patch', timeout:3600) }.to_not raise_error
310
+ expect(subject).to receive(:shellout!)
311
+ .with("patch -p1 -i #{project_dir}/patch_location2/good_patch", timeout: 3600, in_msys_bash: true)
312
+ run_build_command
313
+ end
314
+ end
315
+
184
316
  describe "#shasum" do
185
317
  let(:build_step) do
186
318
  Proc.new {