omnibus 6.1.7 → 8.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -4
  3. data/README.md +54 -12
  4. data/Rakefile +1 -1
  5. data/bin/omnibus +1 -1
  6. data/lib/omnibus.rb +2 -2
  7. data/lib/omnibus/build_version.rb +1 -1
  8. data/lib/omnibus/build_version_dsl.rb +6 -7
  9. data/lib/omnibus/builder.rb +10 -9
  10. data/lib/omnibus/changelog_printer.rb +7 -4
  11. data/lib/omnibus/cleaner.rb +4 -1
  12. data/lib/omnibus/cli.rb +2 -2
  13. data/lib/omnibus/cli/changelog.rb +25 -25
  14. data/lib/omnibus/compressor.rb +2 -2
  15. data/lib/omnibus/compressors/base.rb +2 -2
  16. data/lib/omnibus/compressors/dmg.rb +8 -6
  17. data/lib/omnibus/compressors/tgz.rb +2 -2
  18. data/lib/omnibus/config.rb +13 -3
  19. data/lib/omnibus/core_extensions/open_uri.rb +1 -1
  20. data/lib/omnibus/digestable.rb +2 -2
  21. data/lib/omnibus/download_helpers.rb +6 -2
  22. data/lib/omnibus/fetchers/file_fetcher.rb +1 -1
  23. data/lib/omnibus/fetchers/git_fetcher.rb +1 -0
  24. data/lib/omnibus/fetchers/net_fetcher.rb +3 -4
  25. data/lib/omnibus/fetchers/path_fetcher.rb +1 -1
  26. data/lib/omnibus/file_syncer.rb +1 -1
  27. data/lib/omnibus/generator.rb +2 -2
  28. data/lib/omnibus/generator_files/README.md.erb +20 -16
  29. data/lib/omnibus/generator_files/config/software/preparation.rb.erb +1 -1
  30. data/lib/omnibus/generator_files/omnibus.rb.erb +5 -4
  31. data/lib/omnibus/git_cache.rb +2 -2
  32. data/lib/omnibus/health_check.rb +3 -1
  33. data/lib/omnibus/licensing.rb +5 -6
  34. data/lib/omnibus/logger.rb +3 -2
  35. data/lib/omnibus/manifest.rb +2 -2
  36. data/lib/omnibus/metadata.rb +2 -2
  37. data/lib/omnibus/ohai.rb +1 -1
  38. data/lib/omnibus/package.rb +1 -1
  39. data/lib/omnibus/packager.rb +6 -14
  40. data/lib/omnibus/packagers/appx.rb +1 -2
  41. data/lib/omnibus/packagers/base.rb +2 -1
  42. data/lib/omnibus/packagers/bff.rb +6 -8
  43. data/lib/omnibus/packagers/deb.rb +7 -10
  44. data/lib/omnibus/packagers/ips.rb +3 -6
  45. data/lib/omnibus/packagers/makeself.rb +1 -2
  46. data/lib/omnibus/packagers/msi.rb +13 -12
  47. data/lib/omnibus/packagers/pkg.rb +125 -9
  48. data/lib/omnibus/packagers/rpm.rb +11 -12
  49. data/lib/omnibus/packagers/solaris.rb +5 -5
  50. data/lib/omnibus/packagers/windows_base.rb +7 -6
  51. data/lib/omnibus/project.rb +3 -2
  52. data/lib/omnibus/publisher.rb +2 -2
  53. data/lib/omnibus/publishers/artifactory_publisher.rb +2 -2
  54. data/lib/omnibus/publishers/s3_publisher.rb +6 -4
  55. data/lib/omnibus/s3_cache.rb +4 -2
  56. data/lib/omnibus/s3_helpers.rb +7 -7
  57. data/lib/omnibus/software.rb +68 -43
  58. data/lib/omnibus/sugarable.rb +5 -14
  59. data/lib/omnibus/templating.rb +2 -2
  60. data/lib/omnibus/thread_pool.rb +0 -2
  61. data/lib/omnibus/util.rb +4 -3
  62. data/lib/omnibus/version.rb +1 -1
  63. data/lib/omnibus/whitelist.rb +24 -1
  64. data/omnibus.gemspec +8 -9
  65. data/resources/ips/doc-transform.erb +1 -0
  66. data/resources/msi/CustomActionFastMsi.CA.dll +0 -0
  67. data/resources/msi/source.wxs.erb +2 -10
  68. data/resources/rpm/signing.erb +7 -10
  69. data/spec/functional/builder_spec.rb +2 -1
  70. data/spec/functional/fetchers/file_fetcher_spec.rb +4 -4
  71. data/spec/functional/fetchers/git_fetcher_spec.rb +4 -4
  72. data/spec/functional/fetchers/net_fetcher_spec.rb +5 -6
  73. data/spec/functional/fetchers/path_fetcher_spec.rb +4 -4
  74. data/spec/functional/licensing_spec.rb +5 -5
  75. data/spec/support/examples.rb +3 -4
  76. data/spec/support/path_helpers.rb +2 -2
  77. data/spec/unit/builder_spec.rb +9 -9
  78. data/spec/unit/changelogprinter_spec.rb +8 -6
  79. data/spec/unit/compressor_spec.rb +4 -4
  80. data/spec/unit/compressors/dmg_spec.rb +5 -2
  81. data/spec/unit/fetchers/net_fetcher_spec.rb +16 -17
  82. data/spec/unit/health_check_spec.rb +2 -6
  83. data/spec/unit/library_spec.rb +2 -1
  84. data/spec/unit/manifest_diff_spec.rb +2 -2
  85. data/spec/unit/manifest_spec.rb +1 -1
  86. data/spec/unit/metadata_spec.rb +14 -17
  87. data/spec/unit/omnibus_spec.rb +1 -1
  88. data/spec/unit/packager_spec.rb +6 -13
  89. data/spec/unit/packagers/bff_spec.rb +2 -2
  90. data/spec/unit/packagers/ips_spec.rb +1 -0
  91. data/spec/unit/packagers/msi_spec.rb +2 -2
  92. data/spec/unit/packagers/pkg_spec.rb +354 -0
  93. data/spec/unit/packagers/pkgsrc_spec.rb +1 -1
  94. data/spec/unit/packagers/rpm_spec.rb +5 -5
  95. data/spec/unit/packagers/solaris_spec.rb +7 -7
  96. data/spec/unit/project_spec.rb +7 -7
  97. data/spec/unit/publisher_spec.rb +1 -2
  98. data/spec/unit/publishers/artifactory_publisher_spec.rb +2 -4
  99. data/spec/unit/publishers/s3_publisher_spec.rb +2 -4
  100. data/spec/unit/s3_cacher_spec.rb +19 -6
  101. data/spec/unit/s3_helpers_spec.rb +22 -3
  102. data/spec/unit/software_spec.rb +59 -120
  103. data/spec/unit/util_spec.rb +1 -2
  104. metadata +21 -21
@@ -16,16 +16,18 @@ module Omnibus
16
16
 
17
17
  let(:changelog) do
18
18
  double(ChangeLog,
19
- changelog_entries: %w{entry1 entry2},
20
- authors: %w{alice bob}) end
19
+ changelog_entries: %w{entry1 entry2},
20
+ authors: %w{alice bob})
21
+ end
21
22
  let(:git_changelog) do
22
23
  double(ChangeLog,
23
- changelog_entries:
24
- %w{sub-entry1 sub-entry2}) end
24
+ changelog_entries:
25
+ %w{sub-entry1 sub-entry2})
26
+ end
25
27
  let(:now) { double(Time) }
26
28
  let(:emptydiff) { EmptyManifestDiff.new }
27
29
  let(:old_manifest) do
28
- m = Manifest.new()
30
+ m = Manifest.new
29
31
  m.add("updated-comp", manifest_entry_for("updated-comp", "v9", "v9"))
30
32
  m.add("updated-comp-2", manifest_entry_for("updated-comp-2", "someref0", "someref0", :git))
31
33
  m.add("removed-comp", manifest_entry_for("removed-comp", "v9", "v9"))
@@ -33,7 +35,7 @@ module Omnibus
33
35
  m
34
36
  end
35
37
  let(:new_manifest) do
36
- m = Manifest.new()
38
+ m = Manifest.new
37
39
  m.add("updated-comp", manifest_entry_for("updated-comp", "v10", "v10"))
38
40
  m.add("updated-comp-2", manifest_entry_for("updated-comp-2", "someotherref", "someotherref", :git))
39
41
  m.add("added-comp", manifest_entry_for("added-comp", "v100", "v100"))
@@ -4,17 +4,17 @@ module Omnibus
4
4
  describe Compressor do
5
5
  describe ".for_current_system" do
6
6
  context "on Mac OS X" do
7
- before { stub_ohai(platform: "mac_os_x", version: "10.12") }
7
+ before { stub_ohai(platform: "mac_os_x", version: "10.15") }
8
8
 
9
9
  context "when :dmg is activated" do
10
10
  it "prefers dmg" do
11
- expect(described_class.for_current_system([:tgz, :dmg])).to eq(Compressor::DMG)
11
+ expect(described_class.for_current_system(%i{tgz dmg})).to eq(Compressor::DMG)
12
12
  end
13
13
  end
14
14
 
15
15
  context "when :dmg is not activated" do
16
16
  it "prefers tgz" do
17
- expect(described_class.for_current_system([:tgz, :foo])).to eq(Compressor::TGZ)
17
+ expect(described_class.for_current_system(%i{tgz foo})).to eq(Compressor::TGZ)
18
18
  end
19
19
  end
20
20
 
@@ -30,7 +30,7 @@ module Omnibus
30
30
 
31
31
  context "when :tgz activated" do
32
32
  it "prefers tgz" do
33
- expect(described_class.for_current_system([:tgz, :foo])).to eq(Compressor::TGZ)
33
+ expect(described_class.for_current_system(%i{tgz foo})).to eq(Compressor::TGZ)
34
34
  end
35
35
  end
36
36
 
@@ -219,8 +219,11 @@ module Omnibus
219
219
  sync
220
220
  hdiutil unmount "#{device}"
221
221
  # Give some time to the system so unmount dmg
222
- sleep 5
223
- hdiutil detach "#{device}" &&\
222
+ ATTEMPTS=0
223
+ until [ $ATTEMPTS -eq 5 ] || hdiutil detach "/dev/sda1"; do
224
+ sleep 10
225
+ echo Attempt number $(( ATTEMPTS++ ))
226
+ done
224
227
  hdiutil convert \\
225
228
  "#{staging_dir}/project-writable.dmg" \\
226
229
  -format UDZO \\
@@ -11,10 +11,10 @@ module Omnibus
11
11
 
12
12
  let(:manifest_entry) do
13
13
  double(Omnibus::ManifestEntry,
14
- name: "file",
15
- locked_version: "1.2.3",
16
- described_version: "1.2.3",
17
- locked_source: source)
14
+ name: "file",
15
+ locked_version: "1.2.3",
16
+ described_version: "1.2.3",
17
+ locked_source: source)
18
18
  end
19
19
 
20
20
  let(:cache_dir) { "/cache" }
@@ -331,11 +331,10 @@ module Omnibus
331
331
  context "when the file is a .#{extension}" do
332
332
  let(:manifest_entry) do
333
333
  double(Omnibus::ManifestEntry,
334
- name: "file",
335
- locked_version: "1.2.3",
336
- described_version: "1.2.3",
337
- locked_source: { url: "https://get.example.com/file.#{extension}", md5: "abcd1234" }.merge(source_options)
338
- )
334
+ name: "file",
335
+ locked_version: "1.2.3",
336
+ described_version: "1.2.3",
337
+ locked_source: { url: "https://get.example.com/file.#{extension}", md5: "abcd1234" }.merge(source_options))
339
338
  end
340
339
 
341
340
  subject { described_class.new(manifest_entry, project_dir, build_dir) }
@@ -361,10 +360,10 @@ module Omnibus
361
360
  context "when the downloaded file is a folder" do
362
361
  let(:manifest_entry) do
363
362
  double(Omnibus::ManifestEntry,
364
- name: "file",
365
- locked_version: "1.2.3",
366
- described_version: "1.2.3",
367
- locked_source: { url: "https://get.example.com/folder", md5: "abcd1234" })
363
+ name: "file",
364
+ locked_version: "1.2.3",
365
+ described_version: "1.2.3",
366
+ locked_source: { url: "https://get.example.com/folder", md5: "abcd1234" })
368
367
  end
369
368
 
370
369
  subject { described_class.new(manifest_entry, project_dir, build_dir) }
@@ -382,10 +381,10 @@ module Omnibus
382
381
  context "when the downloaded file is a regular file" do
383
382
  let(:manifest_entry) do
384
383
  double(Omnibus::ManifestEntry,
385
- name: "file",
386
- locked_version: "1.2.3",
387
- described_version: "1.2.3",
388
- locked_source: { url: "https://get.example.com/file", md5: "abcd1234" })
384
+ name: "file",
385
+ locked_version: "1.2.3",
386
+ described_version: "1.2.3",
387
+ locked_source: { url: "https://get.example.com/file", md5: "abcd1234" })
389
388
  end
390
389
 
391
390
  subject { described_class.new(manifest_entry, project_dir, build_dir) }
@@ -8,9 +8,7 @@ module Omnibus
8
8
  name: "chefdk",
9
9
  install_dir: "/opt/chefdk",
10
10
  library: double(Library,
11
- components: []
12
- )
13
- )
11
+ components: []))
14
12
  end
15
13
 
16
14
  def mkdump(base, size, x64 = false)
@@ -19,9 +17,7 @@ module Omnibus
19
17
  x64?: x64,
20
18
  ioh: double(x64 ? PEdump::IMAGE_OPTIONAL_HEADER64 : PEdump::IMAGE_OPTIONAL_HEADER32,
21
19
  ImageBase: base,
22
- SizeOfImage: size
23
- )
24
- )
20
+ SizeOfImage: size))
25
21
  expect(dump).to receive(:pe).and_return(pe)
26
22
  dump
27
23
  end
@@ -125,7 +125,8 @@ module Omnibus
125
125
  erchef, # project dep
126
126
  chef, # project dep
127
127
  chefdk, # project dep
128
- ])
128
+ ]
129
+ )
129
130
  end
130
131
  end
131
132
  end
@@ -12,7 +12,7 @@ module Omnibus
12
12
  end
13
13
 
14
14
  let(:manifest_one) do
15
- m = Omnibus::Manifest.new()
15
+ m = Omnibus::Manifest.new
16
16
  m.add("foo", manifest_entry_for("foo", "1.2.4", "deadbeef"))
17
17
  m.add("bar", manifest_entry_for("bar", "1.2.4", "deadbeef"))
18
18
  m.add("baz", manifest_entry_for("baz", "1.2.4", "deadbeef"))
@@ -20,7 +20,7 @@ module Omnibus
20
20
  end
21
21
 
22
22
  let(:manifest_two) do
23
- m = Omnibus::Manifest.new()
23
+ m = Omnibus::Manifest.new
24
24
  m.add("foo", manifest_entry_for("foo", "1.2.5", "deadbea0"))
25
25
  m.add("baz", manifest_entry_for("baz", "1.2.4", "deadbeef"))
26
26
  m.add("quux", manifest_entry_for("quux", "1.2.4", "deadbeef"))
@@ -45,7 +45,7 @@ module Omnibus
45
45
  second = ManifestEntry.new("wombat", {})
46
46
  subject.add("foobar", first)
47
47
  subject.add("wombat", second)
48
- expect(subject.entry_names).to eq([:foobar, :wombat])
48
+ expect(subject.entry_names).to eq(%i{foobar wombat})
49
49
  end
50
50
  end
51
51
 
@@ -16,8 +16,7 @@ module Omnibus
16
16
  md5: "abc123",
17
17
  sha1: "abc123",
18
18
  sha256: "abcd1234",
19
- sha512: "abcdef123456"
20
- )
19
+ sha512: "abcdef123456")
21
20
  end
22
21
 
23
22
  let(:project) do
@@ -29,15 +28,13 @@ module Omnibus
29
28
  build_iteration: "1",
30
29
  license: "Apache-2.0",
31
30
  built_manifest: double(Manifest,
32
- to_hash: {
33
- manifest_format: 2,
34
- build_version: "1.2.3",
35
- build_git_revision: "SHA",
36
- license: "Apache-2.0",
37
- }
38
- ),
39
- license_file_path: license_path
40
- )
31
+ to_hash: {
32
+ manifest_format: 2,
33
+ build_version: "1.2.3",
34
+ build_git_revision: "SHA",
35
+ license: "Apache-2.0",
36
+ }),
37
+ license_file_path: license_path)
41
38
  end
42
39
 
43
40
  let(:data) { { foo: "bar" } }
@@ -180,17 +177,17 @@ module Omnibus
180
177
 
181
178
  describe ".platform_shortname" do
182
179
  it "returns el on rhel" do
183
- stub_ohai(platform: "redhat", version: "6.9")
180
+ stub_ohai(platform: "redhat", version: "6")
184
181
  expect(described_class.platform_shortname).to eq("el")
185
182
  end
186
183
 
187
184
  it "returns sles on suse" do
188
- stub_ohai(platform: "suse", version: "12.2")
185
+ stub_ohai(platform: "suse", version: "12")
189
186
  expect(described_class.platform_shortname).to eq("sles")
190
187
  end
191
188
 
192
189
  it "returns .platform on all other systems" do
193
- stub_ohai(platform: "ubuntu", version: "16.04")
190
+ stub_ohai(platform: "ubuntu", version: "20.04")
194
191
  expect(described_class.platform_shortname).to eq("ubuntu")
195
192
  end
196
193
  end
@@ -199,7 +196,7 @@ module Omnibus
199
196
  shared_examples "a version manipulator" do |platform_shortname, version, expected|
200
197
  context "on #{platform_shortname}-#{version}" do
201
198
  it "returns the correct value" do
202
- stub_ohai(platform: "ubuntu", version: "16.04") do |data|
199
+ stub_ohai(platform: "ubuntu", version: "20.04") do |data|
203
200
  data["platform"] = platform_shortname
204
201
  data["platform_version"] = version
205
202
  end
@@ -248,7 +245,7 @@ module Omnibus
248
245
 
249
246
  context "given an unknown platform" do
250
247
  before do
251
- stub_ohai(platform: "ubuntu", version: "16.04") do |data|
248
+ stub_ohai(platform: "ubuntu", version: "20.04") do |data|
252
249
  data["platform"] = "bacon"
253
250
  data["platform_version"] = "1.crispy"
254
251
  end
@@ -262,7 +259,7 @@ module Omnibus
262
259
 
263
260
  context "given an unknown windows platform version" do
264
261
  before do
265
- stub_ohai(platform: "ubuntu", version: "16.04") do |data|
262
+ stub_ohai(platform: "ubuntu", version: "20.04") do |data|
266
263
  data["platform"] = "windows"
267
264
  data["platform_version"] = "1.2.3"
268
265
  end
@@ -15,7 +15,7 @@ describe Omnibus do
15
15
 
16
16
  Omnibus::Config.project_root(File.join(tmp_path, "/foo/bar"))
17
17
  Omnibus::Config.local_software_dirs([File.join(tmp_path, "/local"), File.join(tmp_path, "/other")])
18
- Omnibus::Config.software_gems(["omnibus-software", "custom-omnibus-software"])
18
+ Omnibus::Config.software_gems(%w{omnibus-software custom-omnibus-software})
19
19
  end
20
20
 
21
21
  describe "#which" do
@@ -4,26 +4,19 @@ module Omnibus
4
4
  describe Packager do
5
5
  describe ".for_current_system" do
6
6
  context "on Mac OS X" do
7
- before { stub_ohai(platform: "mac_os_x", version: "10.13") }
7
+ before { stub_ohai(platform: "mac_os_x", version: "10.15") }
8
8
  it "prefers PKG" do
9
9
  expect(described_class.for_current_system).to eq([Packager::PKG])
10
10
  end
11
11
  end
12
12
 
13
- context "on Windows 2012 R2" do
13
+ context "on Windows" do
14
14
  before { stub_ohai(platform: "windows", version: "2012R2") }
15
15
  it "prefers MSI and APPX" do
16
16
  expect(described_class.for_current_system).to eq([Packager::MSI, Packager::APPX])
17
17
  end
18
18
  end
19
19
 
20
- context "on Windows 2008 R2" do
21
- before { stub_ohai(platform: "windows", version: "2008R2") }
22
- it "prefers MSI only" do
23
- expect(described_class.for_current_system).to eq([Packager::MSI])
24
- end
25
- end
26
-
27
20
  context "on Solaris 11" do
28
21
  before { stub_ohai(platform: "solaris2", version: "5.11") }
29
22
  it "prefers IPS" do
@@ -32,14 +25,14 @@ module Omnibus
32
25
  end
33
26
 
34
27
  context "on AIX" do
35
- before { stub_ohai(platform: "aix", version: "7.1") }
28
+ before { stub_ohai(platform: "aix", version: "7") }
36
29
  it "prefers BFF" do
37
30
  expect(described_class.for_current_system).to eq([Packager::BFF])
38
31
  end
39
32
  end
40
33
 
41
34
  context "on Fedora" do
42
- before { stub_ohai(platform: "fedora", version: "28") }
35
+ before { stub_ohai(platform: "fedora", version: "31") }
43
36
  it "prefers RPM" do
44
37
  expect(described_class.for_current_system).to eq([Packager::RPM])
45
38
  end
@@ -53,14 +46,14 @@ module Omnibus
53
46
  end
54
47
 
55
48
  context "on Debian" do
56
- before { stub_ohai(platform: "debian", version: "8.11") }
49
+ before { stub_ohai(platform: "debian", version: "10") }
57
50
  it "prefers RPM" do
58
51
  expect(described_class.for_current_system).to eq([Packager::DEB])
59
52
  end
60
53
  end
61
54
 
62
55
  context "on SLES" do
63
- before { stub_ohai(platform: "suse", version: "12.3") }
56
+ before { stub_ohai(platform: "suse", version: "15") }
64
57
  it "prefers RPM" do
65
58
  expect(described_class.for_current_system).to eq([Packager::RPM])
66
59
  end
@@ -301,7 +301,7 @@ module Omnibus
301
301
  # A note - the /opt/ here is essentially project.install_dir one level up.
302
302
  # There is nothing magical about 'opt' as a directory.
303
303
  expect(subject).to receive(:shellout!)
304
- .with(/chown -Rh 0:0 #{staging_dir}\/opt$/)
304
+ .with(%r{chown -Rh 0:0 #{staging_dir}/opt$})
305
305
  subject.create_bff_file
306
306
  end
307
307
 
@@ -312,7 +312,7 @@ module Omnibus
312
312
 
313
313
  it "uses the correct command" do
314
314
  expect(subject).to receive(:shellout!)
315
- .with(/\/usr\/sbin\/mkinstallp -d/)
315
+ .with(%r{/usr/sbin/mkinstallp -d})
316
316
  subject.create_bff_file
317
317
  end
318
318
 
@@ -155,6 +155,7 @@ module Omnibus
155
155
  expect(transform_file_contents).to include("<transform file depend -> edit pkg.debug.depend.file ruby env>")
156
156
  expect(transform_file_contents).to include("<transform file depend -> edit pkg.debug.depend.file make env>")
157
157
  expect(transform_file_contents).to include("<transform file depend -> edit pkg.debug.depend.file perl env>")
158
+ expect(transform_file_contents).to include("<transform file depend -> edit pkg.debug.depend.path usr/local/bin usr/bin>")
158
159
  end
159
160
  end
160
161
 
@@ -419,7 +419,7 @@ module Omnibus
419
419
  end
420
420
 
421
421
  it "outputs a source.wxs file to the staging directory" do
422
- expect(subject.candle_command).to include("#{subject.windows_safe_path(staging_dir, 'source.wxs')}")
422
+ expect(subject.candle_command).to include("#{subject.windows_safe_path(staging_dir, "source.wxs")}")
423
423
  end
424
424
  end
425
425
 
@@ -433,7 +433,7 @@ module Omnibus
433
433
  end
434
434
 
435
435
  it "outputs a bundle.wxs file to the staging directory" do
436
- expect(subject.candle_command(is_bundle: true)).to include("#{subject.windows_safe_path(staging_dir, 'bundle.wxs')}")
436
+ expect(subject.candle_command(is_bundle: true)).to include("#{subject.windows_safe_path(staging_dir, "bundle.wxs")}")
437
437
  end
438
438
  end
439
439
  end
@@ -109,6 +109,158 @@ module Omnibus
109
109
  end
110
110
  end
111
111
 
112
+ describe "#sign_software_libs_and_bins" do
113
+ context "when pkg signing is disabled" do
114
+ it "does not sign anything" do
115
+ expect(subject).not_to receive(:sign_binary)
116
+ expect(subject).not_to receive(:sign_library)
117
+ subject.sign_software_libs_and_bins
118
+ end
119
+
120
+ it "returns an empty set" do
121
+ expect(subject.sign_software_libs_and_bins).to be_nil
122
+ end
123
+ end
124
+
125
+ context "when pkg signing is enabled" do
126
+ before do
127
+ subject.signing_identity("My Special Identity")
128
+ end
129
+
130
+ context "without software" do
131
+ it "does not sign anything" do
132
+ expect(subject).not_to receive(:sign_binary)
133
+ expect(subject).not_to receive(:sign_library)
134
+ subject.sign_software_libs_and_bins
135
+ end
136
+
137
+ it "returns an empty set" do
138
+ expect(subject.sign_software_libs_and_bins).to eq(Set.new)
139
+ end
140
+ end
141
+
142
+ context "project with software" do
143
+ let(:software) do
144
+ Software.new(project).tap do |software|
145
+ software.name("software-full-name")
146
+ end
147
+ end
148
+
149
+ before do
150
+ allow(project).to receive(:softwares).and_return([software])
151
+ end
152
+
153
+ context "with empty bin_dirs and lib_dirs" do
154
+ before do
155
+ allow(software).to receive(:lib_dirs).and_return([])
156
+ allow(software).to receive(:bin_dirs).and_return([])
157
+ end
158
+
159
+ it "does not sign anything" do
160
+ expect(subject).not_to receive(:sign_binary)
161
+ expect(subject).not_to receive(:sign_library)
162
+ subject.sign_software_libs_and_bins
163
+ end
164
+
165
+ it "returns an empty set" do
166
+ expect(subject.sign_software_libs_and_bins).to eq(Set.new)
167
+ end
168
+ end
169
+
170
+ context "with default bin_dirs and lib_dirs" do
171
+ context "with binaries" do
172
+ let(:bin) { "/opt/#{project.name}/bin/test_bin" }
173
+ let(:embedded_bin) { "/opt/#{project.name}/embedded/bin/test_bin" }
174
+ before do
175
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/bin/*").and_return([bin])
176
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/embedded/bin/*").and_return([embedded_bin])
177
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/embedded/lib/*").and_return([])
178
+ allow(subject).to receive(:is_binary?).with(bin).and_return(true)
179
+ allow(subject).to receive(:is_binary?).with(embedded_bin).and_return(true)
180
+ allow(subject).to receive(:find_linked_libs).with(bin).and_return([])
181
+ allow(subject).to receive(:find_linked_libs).with(embedded_bin).and_return([])
182
+ allow(subject).to receive(:sign_binary).with(bin, true)
183
+ allow(subject).to receive(:sign_binary).with(embedded_bin, true)
184
+ end
185
+
186
+ it "signs the binaries" do
187
+ expect(subject).to receive(:sign_binary).with(bin, true)
188
+ expect(subject).to receive(:sign_binary).with(embedded_bin, true)
189
+ subject.sign_software_libs_and_bins
190
+ end
191
+
192
+ it "returns a set with the signed binaries" do
193
+ expect(subject.sign_software_libs_and_bins).to eq(Set.new [bin, embedded_bin])
194
+ end
195
+ end
196
+
197
+ context "with library" do
198
+ let(:lib) { "/opt/#{project.name}/embedded/lib/test_lib" }
199
+ before do
200
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/bin/*").and_return([])
201
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/embedded/bin/*").and_return([])
202
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/embedded/lib/*").and_return([lib])
203
+ allow(subject).to receive(:is_macho?).with(lib).and_return(true)
204
+ allow(subject).to receive(:find_linked_libs).with(lib).and_return([])
205
+ allow(subject).to receive(:sign_library).with(lib)
206
+ end
207
+
208
+ it "signs the library" do
209
+ expect(subject).to receive(:sign_library).with(lib)
210
+ subject.sign_software_libs_and_bins
211
+ end
212
+ end
213
+
214
+ context "with binaries and libraries with linked libs" do
215
+ let(:bin) { "/opt/#{project.name}/bin/test_bin" }
216
+ let(:bin2) { "/opt/#{project.name}/bin/test_bin2" }
217
+ let(:embedded_bin) { "/opt/#{project.name}/embedded/bin/test_bin" }
218
+ let(:lib) { "/opt/#{project.name}/embedded/lib/test_lib" }
219
+ let(:lib2) { "/opt/#{project.name}/embedded/lib/test_lib2" }
220
+ before do
221
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/bin/*").and_return([bin, bin2])
222
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/embedded/bin/*").and_return([embedded_bin])
223
+ allow(Dir).to receive(:[]).with("/opt/#{project.name}/embedded/lib/*").and_return([lib])
224
+ allow(subject).to receive(:is_binary?).with(bin).and_return(true)
225
+ allow(subject).to receive(:is_binary?).with(bin2).and_return(true)
226
+ allow(subject).to receive(:is_binary?).with(embedded_bin).and_return(true)
227
+ allow(subject).to receive(:is_macho?).with(lib).and_return(true)
228
+ allow(subject).to receive(:is_macho?).with(lib2).and_return(true)
229
+ allow(subject).to receive(:find_linked_libs).with(bin).and_return([lib2])
230
+ allow(subject).to receive(:find_linked_libs).with(bin2).and_return([])
231
+ allow(subject).to receive(:find_linked_libs).with(embedded_bin).and_return([])
232
+ allow(subject).to receive(:find_linked_libs).with(lib).and_return([])
233
+ allow(subject).to receive(:find_linked_libs).with(lib2).and_return([])
234
+ allow(subject).to receive(:sign_binary).with(bin, true)
235
+ allow(subject).to receive(:sign_binary).with(bin2, true)
236
+ allow(subject).to receive(:sign_binary).with(embedded_bin, true)
237
+ allow(subject).to receive(:sign_library).with(lib)
238
+ allow(subject).to receive(:sign_library).with(lib2)
239
+ allow(Digest::SHA256).to receive(:file).with(bin).and_return(Digest::SHA256.new.update(bin))
240
+ allow(Digest::SHA256).to receive(:file).with(bin2).and_return(Digest::SHA256.new.update(bin2))
241
+ allow(Digest::SHA256).to receive(:file).with(embedded_bin).and_return(Digest::SHA256.new.update(embedded_bin))
242
+ allow(Digest::SHA256).to receive(:file).with(lib).and_return(Digest::SHA256.new.update(lib))
243
+ allow(Digest::SHA256).to receive(:file).with(lib2).and_return(Digest::SHA256.new.update(lib2))
244
+ end
245
+
246
+ it "signs the binaries" do
247
+ expect(subject).to receive(:sign_binary).with(bin, true)
248
+ expect(subject).to receive(:sign_binary).with(bin2, true)
249
+ expect(subject).to receive(:sign_binary).with(embedded_bin, true)
250
+ subject.sign_software_libs_and_bins
251
+ end
252
+
253
+ it "signs the libraries" do
254
+ expect(subject).to receive(:sign_library).with(lib)
255
+ expect(subject).to receive(:sign_library).with(lib2)
256
+ subject.sign_software_libs_and_bins
257
+ end
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end
263
+
112
264
  describe "#build_component_pkg" do
113
265
  it "executes the pkgbuild command" do
114
266
  expect(subject).to receive(:shellout!).with <<-EOH.gsub(/^ {10}/, "")
@@ -118,6 +270,7 @@ module Omnibus
118
270
  --scripts "#{staging_dir}/Scripts" \\
119
271
  --root "/opt/project-full-name" \\
120
272
  --install-location "/opt/project-full-name" \\
273
+ --preserve-xattr \\
121
274
  "project-full-name-core.pkg"
122
275
  EOH
123
276
 
@@ -267,5 +420,206 @@ module Omnibus
267
420
  end
268
421
  end
269
422
  end
423
+
424
+ describe "#find_linked_libs" do
425
+ context "with linked libs" do
426
+ let(:file) { "/opt/#{project.name}/embedded/bin/test_bin" }
427
+ let(:stdout) do
428
+ <<~EOH
429
+ /opt/#{project.name}/embedded/bin/test_bin:
430
+ /opt/#{project.name}/embedded/lib/lib.dylib (compatibility version 7.0.0, current version 7.4.0)
431
+ /opt/#{project.name}/embedded/lib/lib.6.dylib (compatibility version 7.0.0, current version 7.4.0)
432
+ /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
433
+ EOH
434
+ end
435
+ let(:shellout) { Mixlib::ShellOut.new }
436
+
437
+ before do
438
+ allow(shellout).to receive(:run_command)
439
+ allow(shellout).to receive(:stdout)
440
+ .and_return(stdout)
441
+ allow(subject).to receive(:shellout!)
442
+ .with("otool -L #{file}")
443
+ .and_return(shellout)
444
+ end
445
+
446
+ it "returns empty array" do
447
+ expect(subject.find_linked_libs(file)).to eq([
448
+ "/opt/#{project.name}/embedded/lib/lib.dylib",
449
+ "/opt/#{project.name}/embedded/lib/lib.6.dylib",
450
+ ])
451
+ end
452
+ end
453
+
454
+ context "with only system linked libs" do
455
+ let(:file) { "/opt/#{project.name}/embedded/lib/lib.dylib" }
456
+ let(:stdout) do
457
+ <<~EOH
458
+ /opt/#{project.name}/embedded/lib/lib.dylib:
459
+ /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
460
+ EOH
461
+ end
462
+ let(:shellout) { Mixlib::ShellOut.new }
463
+ before do
464
+ allow(shellout).to receive(:run_command)
465
+ allow(shellout).to receive(:stdout)
466
+ .and_return(stdout)
467
+ allow(subject).to receive(:shellout!)
468
+ .with("otool -L #{file}")
469
+ .and_return(shellout)
470
+ end
471
+
472
+ it "returns empty array" do
473
+ expect(subject.find_linked_libs(file)).to eq([])
474
+ end
475
+ end
476
+
477
+ context "file is just a file" do
478
+ let(:file) { "/opt/#{project.name}/embedded/lib/file.rb" }
479
+ let(:shellout) { Mixlib::ShellOut.new }
480
+ before do
481
+ allow(shellout).to receive(:run_command)
482
+ allow(shellout).to receive(:stdout)
483
+ .and_return("#{file}: is not an object file")
484
+ allow(subject).to receive(:shellout!)
485
+ .with("otool -L #{file}")
486
+ .and_return(shellout)
487
+ end
488
+
489
+ it "returns empty array" do
490
+ expect(subject.find_linked_libs(file)).to eq([])
491
+ end
492
+ end
493
+ end
494
+
495
+ describe "#is_binary?" do
496
+ context "when is a file, executable, and not a symlink" do
497
+ before do
498
+ allow(File).to receive(:file?).with("file").and_return(true)
499
+ allow(File).to receive(:executable?).with("file").and_return(true)
500
+ allow(File).to receive(:symlink?).with("file").and_return(false)
501
+ end
502
+
503
+ it "returns true" do
504
+ expect(subject.is_binary?("file")).to be true
505
+ end
506
+ end
507
+
508
+ context "when not a file" do
509
+ before do
510
+ allow(File).to receive(:file?).with("file").and_return(false)
511
+ allow(File).to receive(:executable?).with("file").and_return(true)
512
+ allow(File).to receive(:symlink?).with("file").and_return(false)
513
+ end
514
+
515
+ it "returns false" do
516
+ expect(subject.is_binary?("file")).to be false
517
+ end
518
+ end
519
+
520
+ context "when not an executable" do
521
+ it "returns false" do
522
+ allow(File).to receive(:file?).with("file").and_return(true)
523
+ allow(File).to receive(:executable?).with("file").and_return(false)
524
+ allow(File).to receive(:symlink?).with("file").and_return(false)
525
+ expect(subject.is_binary?("file")).to be false
526
+ end
527
+ end
528
+
529
+ context "when is symlink" do
530
+ it "returns false" do
531
+ allow(File).to receive(:file?).with("file").and_return(true)
532
+ allow(File).to receive(:executable?).with("file").and_return(true)
533
+ allow(File).to receive(:symlink?).with("file").and_return(true)
534
+ expect(subject.is_binary?("file")).to be false
535
+ end
536
+ end
537
+ end
538
+
539
+ describe "#is_macho?" do
540
+ let(:shellout) { Mixlib::ShellOut.new }
541
+
542
+ context "when is a Mach-O library" do
543
+ before do
544
+ allow(subject).to receive(:is_binary?).with("file").and_return(true)
545
+ expect(subject).to receive(:shellout!).with("file file").and_return(shellout)
546
+ allow(shellout).to receive(:stdout)
547
+ .and_return("file: Mach-O 64-bit dynamically linked shared library x86_64")
548
+ end
549
+
550
+ it "returns true" do
551
+ expect(subject.is_macho?("file")).to be true
552
+ end
553
+ end
554
+
555
+ context "when is a Mach-O Bundle" do
556
+ before do
557
+ allow(subject).to receive(:is_binary?).with("file").and_return(true)
558
+ expect(subject).to receive(:shellout!).with("file file").and_return(shellout)
559
+ allow(shellout).to receive(:stdout)
560
+ .and_return("file: Mach-O 64-bit bundle x86_64")
561
+ end
562
+
563
+ it "returns true" do
564
+ expect(subject.is_macho?("file")).to be true
565
+ end
566
+ end
567
+
568
+ context "when is not a Mach-O Bundle or Mach-O library" do
569
+ before do
570
+ allow(subject).to receive(:is_binary?).with("file").and_return(true)
571
+ expect(subject).to receive(:shellout!).with("file file").and_return(shellout)
572
+ allow(shellout).to receive(:stdout)
573
+ .and_return("file: ASCII text")
574
+ end
575
+
576
+ it "returns true" do
577
+ expect(subject.is_macho?("file")).to be false
578
+ end
579
+ end
580
+ end
581
+
582
+ describe "#sign_library" do
583
+ before do
584
+ subject.signing_identity("My Special Identity")
585
+ end
586
+
587
+ it "calls sign_binary without hardened runtime" do
588
+ expect(subject).to receive(:sign_binary).with("file")
589
+ subject.sign_library("file")
590
+ end
591
+ end
592
+
593
+ describe "#sign_binary" do
594
+ before do
595
+ subject.signing_identity("My Special Identity")
596
+ end
597
+
598
+ it "it signs the binary without hardened runtime" do
599
+ expect(subject).to receive(:shellout!)
600
+ .with("codesign -s '#{subject.signing_identity}' 'file' --force\n")
601
+ subject.sign_binary("file")
602
+ end
603
+
604
+ context "with hardened runtime" do
605
+ it "it signs the binary with hardened runtime" do
606
+ expect(subject).to receive(:shellout!)
607
+ .with("codesign -s '#{subject.signing_identity}' 'file' --options=runtime --force\n")
608
+ subject.sign_binary("file", true)
609
+ end
610
+
611
+ context "with entitlements" do
612
+ let(:entitlements_file) { File.join(tmp_path, "project-full-name/resources/project-full-name/pkg/entitlements.plist") }
613
+
614
+ it "it signs the binary with the entitlements" do
615
+ allow(subject).to receive(:resource_path).with("entitlements.plist").and_return(entitlements_file)
616
+ allow(File).to receive(:exist?).with(entitlements_file).and_return(true)
617
+ expect(subject).to receive(:shellout!)
618
+ .with("codesign -s '#{subject.signing_identity}' 'file' --options=runtime --entitlements #{entitlements_file} --force\n")
619
+ subject.sign_binary("file", true)
620
+ end
621
+ end
622
+ end
623
+ end
270
624
  end
271
625
  end