omnibus 5.0.0 → 5.1.0

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.
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 {