omnibus 5.4.0 → 5.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -3
- data/CHANGELOG.md +21 -0
- data/Gemfile +8 -5
- data/README.md +3 -1
- data/Rakefile +20 -13
- data/appveyor.yml +4 -3
- data/bin/omnibus +3 -3
- data/features/commands/manifest.feature +19 -5
- data/features/step_definitions/generator_steps.rb +5 -6
- data/features/support/env.rb +4 -4
- data/lib/omnibus/build_version.rb +14 -14
- data/lib/omnibus/build_version_dsl.rb +3 -3
- data/lib/omnibus/builder.rb +50 -61
- data/lib/omnibus/changelog.rb +2 -2
- data/lib/omnibus/changelog_printer.rb +4 -4
- data/lib/omnibus/cleaner.rb +4 -4
- data/lib/omnibus/cli/base.rb +15 -15
- data/lib/omnibus/cli/cache.rb +13 -13
- data/lib/omnibus/cli/changelog.rb +8 -9
- data/lib/omnibus/cli/publish.rb +12 -13
- data/lib/omnibus/cli.rb +26 -27
- data/lib/omnibus/compressor.rb +6 -6
- data/lib/omnibus/compressors/base.rb +7 -2
- data/lib/omnibus/compressors/dmg.rb +12 -12
- data/lib/omnibus/compressors/null.rb +1 -1
- data/lib/omnibus/compressors/tgz.rb +8 -8
- data/lib/omnibus/config.rb +37 -26
- data/lib/omnibus/core_extensions/open_uri.rb +3 -3
- data/lib/omnibus/core_extensions.rb +1 -1
- data/lib/omnibus/digestable.rb +5 -4
- data/lib/omnibus/download_helpers.rb +7 -6
- data/lib/omnibus/exceptions.rb +29 -13
- data/lib/omnibus/fetcher.rb +0 -1
- data/lib/omnibus/fetchers/git_fetcher.rb +7 -7
- data/lib/omnibus/fetchers/net_fetcher.rb +19 -19
- data/lib/omnibus/fetchers/path_fetcher.rb +1 -1
- data/lib/omnibus/file_syncer.rb +3 -3
- data/lib/omnibus/generator.rb +60 -47
- data/lib/omnibus/git_cache.rb +33 -22
- data/lib/omnibus/git_repository.rb +5 -5
- data/lib/omnibus/health_check.rb +122 -119
- data/lib/omnibus/instrumentation.rb +1 -1
- data/lib/omnibus/licensing.rb +348 -60
- data/lib/omnibus/logger.rb +12 -9
- data/lib/omnibus/logging.rb +1 -1
- data/lib/omnibus/manifest.rb +4 -4
- data/lib/omnibus/manifest_diff.rb +6 -7
- data/lib/omnibus/manifest_entry.rb +1 -1
- data/lib/omnibus/metadata.rb +36 -36
- data/lib/omnibus/ohai.rb +6 -7
- data/lib/omnibus/package.rb +1 -1
- data/lib/omnibus/packager.rb +37 -28
- data/lib/omnibus/packagers/appx.rb +86 -0
- data/lib/omnibus/packagers/base.rb +21 -18
- data/lib/omnibus/packagers/bff.rb +22 -24
- data/lib/omnibus/packagers/deb.rb +20 -20
- data/lib/omnibus/packagers/ips.rb +18 -17
- data/lib/omnibus/packagers/makeself.rb +7 -7
- data/lib/omnibus/packagers/msi.rb +38 -193
- data/lib/omnibus/packagers/pkg.rb +16 -16
- data/lib/omnibus/packagers/rpm.rb +53 -54
- data/lib/omnibus/packagers/solaris.rb +14 -14
- data/lib/omnibus/packagers/windows_base.rb +192 -0
- data/lib/omnibus/project.rb +45 -43
- data/lib/omnibus/publisher.rb +3 -3
- data/lib/omnibus/publishers/artifactory_publisher.rb +39 -39
- data/lib/omnibus/publishers/s3_publisher.rb +7 -7
- data/lib/omnibus/reports.rb +10 -10
- data/lib/omnibus/s3_cache.rb +7 -7
- data/lib/omnibus/s3_helpers.rb +8 -7
- data/lib/omnibus/semantic_version.rb +1 -1
- data/lib/omnibus/software.rb +131 -81
- data/lib/omnibus/sugarable.rb +10 -10
- data/lib/omnibus/templating.rb +5 -5
- data/lib/omnibus/thread_pool.rb +1 -1
- data/lib/omnibus/util.rb +5 -5
- data/lib/omnibus/version.rb +1 -1
- data/lib/omnibus.rb +65 -65
- data/omnibus.gemspec +34 -32
- data/resources/appx/AppxManifest.xml.erb +18 -0
- data/resources/appx/assets/clear.png +0 -0
- data/spec/fixtures/licensing/license_scout/snoopy/ruby_bundler-bundler-audit-0.5.0-COPYING.txt +674 -0
- data/spec/fixtures/licensing/license_scout/snoopy/ruby_bundler-inifile-3.0.0-README.md +215 -0
- data/spec/fixtures/licensing/license_scout/snoopy/snoopy-dependency-licenses.json +24 -0
- data/spec/fixtures/licensing/license_scout/zlib/ruby_bundler-inifile-3.0.0-README.md +215 -0
- data/spec/fixtures/licensing/license_scout/zlib/ruby_bundler-mime-types-3.1-Licence.rdoc +25 -0
- data/spec/fixtures/licensing/license_scout/zlib/ruby_bundler-mini_portile2-2.1.0-LICENSE.txt +20 -0
- data/spec/fixtures/licensing/license_scout/zlib/zlib-dependency-licenses.json +32 -0
- data/spec/functional/builder_spec.rb +149 -150
- data/spec/functional/fetchers/git_fetcher_spec.rb +69 -71
- data/spec/functional/fetchers/net_fetcher_spec.rb +79 -79
- data/spec/functional/fetchers/path_fetcher_spec.rb +19 -20
- data/spec/functional/file_syncer_spec.rb +74 -74
- data/spec/functional/licensing_spec.rb +344 -35
- data/spec/functional/templating_spec.rb +17 -17
- data/spec/spec_helper.rb +20 -20
- data/spec/support/examples.rb +21 -15
- data/spec/support/file_helpers.rb +1 -1
- data/spec/support/git_helpers.rb +37 -37
- data/spec/support/matchers.rb +3 -3
- data/spec/support/ohai_helpers.rb +4 -4
- data/spec/support/path_helpers.rb +2 -2
- data/spec/support/shell_helpers.rb +2 -2
- data/spec/unit/build_version_dsl_spec.rb +5 -5
- data/spec/unit/build_version_spec.rb +63 -63
- data/spec/unit/builder_spec.rb +86 -70
- data/spec/unit/changelog_spec.rb +4 -4
- data/spec/unit/changelogprinter_spec.rb +130 -0
- data/spec/unit/cleanroom_spec.rb +11 -11
- data/spec/unit/compressor_spec.rb +16 -16
- data/spec/unit/compressors/base_spec.rb +6 -6
- data/spec/unit/compressors/dmg_spec.rb +76 -76
- data/spec/unit/compressors/null_spec.rb +4 -4
- data/spec/unit/compressors/tgz_spec.rb +20 -20
- data/spec/unit/config_spec.rb +44 -43
- data/spec/unit/digestable_spec.rb +13 -13
- data/spec/unit/fetcher_spec.rb +11 -12
- data/spec/unit/fetchers/git_fetcher_spec.rb +31 -31
- data/spec/unit/fetchers/net_fetcher_spec.rb +172 -173
- data/spec/unit/fetchers/path_fetcher_spec.rb +18 -18
- data/spec/unit/generator_spec.rb +38 -38
- data/spec/unit/git_cache_spec.rb +56 -54
- data/spec/unit/git_repository_spec.rb +2 -2
- data/spec/unit/health_check_spec.rb +40 -40
- data/spec/unit/library_spec.rb +35 -35
- data/spec/unit/manifest_diff_spec.rb +10 -11
- data/spec/unit/manifest_spec.rb +17 -17
- data/spec/unit/metadata_spec.rb +152 -152
- data/spec/unit/ohai_spec.rb +5 -5
- data/spec/unit/omnibus_spec.rb +31 -31
- data/spec/unit/package_spec.rb +20 -20
- data/spec/unit/packager_spec.rb +48 -42
- data/spec/unit/packagers/appx_spec.rb +165 -0
- data/spec/unit/packagers/base_spec.rb +34 -34
- data/spec/unit/packagers/bff_spec.rb +60 -60
- data/spec/unit/packagers/deb_spec.rb +71 -71
- data/spec/unit/packagers/ips_spec.rb +45 -45
- data/spec/unit/packagers/makeself_spec.rb +22 -22
- data/spec/unit/packagers/msi_spec.rb +141 -147
- data/spec/unit/packagers/pkg_spec.rb +59 -60
- data/spec/unit/packagers/rpm_spec.rb +125 -126
- data/spec/unit/packagers/solaris_spec.rb +52 -52
- data/spec/unit/project_spec.rb +137 -135
- data/spec/unit/publisher_spec.rb +70 -70
- data/spec/unit/publishers/artifactory_publisher_spec.rb +85 -85
- data/spec/unit/publishers/s3_publisher_spec.rb +36 -36
- data/spec/unit/s3_cacher_spec.rb +34 -34
- data/spec/unit/s3_helpers_spec.rb +6 -6
- data/spec/unit/semantic_version_spec.rb +2 -2
- data/spec/unit/software_spec.rb +346 -384
- data/spec/unit/sugarable_spec.rb +10 -10
- data/spec/unit/util_spec.rb +60 -60
- metadata +54 -6
- data/.rubocop.yml +0 -48
data/lib/omnibus/licensing.rb
CHANGED
@@ -14,21 +14,56 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
17
|
+
require "uri"
|
18
|
+
require "fileutils"
|
19
|
+
require "omnibus/download_helpers"
|
20
|
+
require "license_scout/collector"
|
21
|
+
require "license_scout/options"
|
20
22
|
|
21
23
|
module Omnibus
|
22
24
|
class Licensing
|
23
25
|
include Logging
|
24
26
|
include DownloadHelpers
|
27
|
+
include Sugarable
|
25
28
|
|
26
29
|
OUTPUT_DIRECTORY = "LICENSES".freeze
|
30
|
+
CACHE_DIRECTORY = "license-cache".freeze
|
27
31
|
|
28
32
|
class << self
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
|
34
|
+
# Creates a new instance of Licensing, executes preparation steps, then
|
35
|
+
# yields control to a given block, and then creates a summary of the
|
36
|
+
# included licenses.
|
37
|
+
#
|
38
|
+
# @example Building a project:
|
39
|
+
#
|
40
|
+
# Licensing.create_incrementally(self) do |license_collector|
|
41
|
+
# softwares.each do |software|
|
42
|
+
# software.build_me([license_collector])
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# @param [Project] project
|
47
|
+
# The project being built.
|
48
|
+
#
|
49
|
+
# @yieldparam [Licensing] license_collector
|
50
|
+
# Yields an instance of Licensing. Call #execute_post_build to copy the
|
51
|
+
# license files for a Software definition.
|
52
|
+
#
|
53
|
+
# @return [Licensing]
|
54
|
+
#
|
55
|
+
def create_incrementally(project)
|
56
|
+
new(project).tap do |license_collector|
|
57
|
+
|
58
|
+
license_collector.prepare
|
59
|
+
license_collector.validate_license_info
|
60
|
+
|
61
|
+
yield license_collector
|
62
|
+
|
63
|
+
license_collector.process_transitive_dependency_licensing_info
|
64
|
+
license_collector.create_project_license_file
|
65
|
+
license_collector.raise_if_warnings_fatal!
|
66
|
+
end
|
32
67
|
end
|
33
68
|
end
|
34
69
|
|
@@ -39,35 +74,80 @@ module Omnibus
|
|
39
74
|
#
|
40
75
|
attr_reader :project
|
41
76
|
|
77
|
+
#
|
78
|
+
# The warnings encountered while preparing the licensing information
|
79
|
+
#
|
80
|
+
# @return [Array<String>]
|
81
|
+
#
|
82
|
+
attr_reader :licensing_warnings
|
83
|
+
|
84
|
+
#
|
85
|
+
# The warnings encountered while preparing the licensing information for
|
86
|
+
# transitive dependencies.
|
87
|
+
#
|
88
|
+
# @return [Array<String>]
|
89
|
+
#
|
90
|
+
attr_reader :transitive_dependency_licensing_warnings
|
91
|
+
|
92
|
+
#
|
93
|
+
# Manifest data of transitive dependency licensing information
|
94
|
+
#
|
95
|
+
# @return Hash
|
96
|
+
#
|
97
|
+
attr_reader :dep_license_map
|
98
|
+
|
42
99
|
#
|
43
100
|
# @param [Project] project
|
44
101
|
# the project to create licenses for.
|
45
102
|
#
|
46
103
|
def initialize(project)
|
47
104
|
@project = project
|
105
|
+
@licensing_warnings = []
|
106
|
+
@transitive_dependency_licensing_warnings = []
|
107
|
+
@dep_license_map = {}
|
48
108
|
end
|
49
109
|
|
50
110
|
#
|
51
|
-
# Creates the
|
52
|
-
# It is assumed that the project has already been built.
|
111
|
+
# Creates the required directories for licenses.
|
53
112
|
#
|
54
113
|
# @return [void]
|
55
114
|
#
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
115
|
+
def prepare
|
116
|
+
FileUtils.rm_rf(output_dir)
|
117
|
+
FileUtils.mkdir_p(output_dir)
|
118
|
+
FileUtils.touch(output_dir_gitkeep_file)
|
119
|
+
FileUtils.rm_rf(cache_dir)
|
120
|
+
FileUtils.mkdir_p(cache_dir)
|
121
|
+
FileUtils.touch(cache_dir_gitkeep_file)
|
61
122
|
end
|
62
123
|
|
124
|
+
# Required callback to use instances of this class as a build wrapper for
|
125
|
+
# Software#build_me. Licensing doesn't need to do anything pre-build, so
|
126
|
+
# this does nothing.
|
63
127
|
#
|
64
|
-
#
|
128
|
+
# @param [Software] software
|
65
129
|
#
|
66
130
|
# @return [void]
|
67
131
|
#
|
68
|
-
def
|
69
|
-
|
70
|
-
|
132
|
+
def execute_pre_build(software)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Callback that gets called by Software#build_me after the build is done.
|
136
|
+
# Invokes license copying for the given software. This ensures that
|
137
|
+
# licenses are copied before a git cache snapshot is taken, so that the
|
138
|
+
# license files are correctly restored when a build is skipped due to a
|
139
|
+
# cache hit.
|
140
|
+
#
|
141
|
+
# @param [Software] software
|
142
|
+
#
|
143
|
+
# @return [void]
|
144
|
+
#
|
145
|
+
def execute_post_build(software)
|
146
|
+
collect_licenses_for(software)
|
147
|
+
|
148
|
+
unless software.skip_transitive_dependency_licensing
|
149
|
+
collect_transitive_dependency_licenses_for(software)
|
150
|
+
end
|
71
151
|
end
|
72
152
|
|
73
153
|
#
|
@@ -91,7 +171,7 @@ module Omnibus
|
|
91
171
|
|
92
172
|
# Check used license is a standard license
|
93
173
|
if project.license != "Unspecified" && !STANDARD_LICENSES.include?(project.license)
|
94
|
-
|
174
|
+
licensing_info("Project '#{project.name}' is using '#{project.license}' which is not one of the standard licenses identified in https://opensource.org/licenses/alphabetical. Consider using one of the standard licenses.")
|
95
175
|
end
|
96
176
|
|
97
177
|
# Now let's check the licensing info for software components
|
@@ -108,7 +188,7 @@ module Omnibus
|
|
108
188
|
|
109
189
|
# Check if the software license is one of the standard licenses
|
110
190
|
if license_info[:license] != "Unspecified" && !STANDARD_LICENSES.include?(license_info[:license])
|
111
|
-
|
191
|
+
licensing_info("Software '#{software_name}' uses license '#{license_info[:license]}' which is not one of the standard licenses identified in https://opensource.org/licenses/alphabetical. Consider using one of the standard licenses.")
|
112
192
|
end
|
113
193
|
end
|
114
194
|
end
|
@@ -123,50 +203,14 @@ module Omnibus
|
|
123
203
|
# @return [void]
|
124
204
|
#
|
125
205
|
def create_project_license_file
|
126
|
-
File.open(project.license_file_path,
|
206
|
+
File.open(project.license_file_path, "w") do |f|
|
127
207
|
f.puts "#{project.name} #{project.build_version} license: \"#{project.license}\""
|
128
208
|
f.puts ""
|
129
209
|
f.puts project_license_content
|
130
210
|
f.puts ""
|
131
211
|
f.puts components_license_summary
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
# Copies the license files specified by the software components into the
|
137
|
-
# output directory.
|
138
|
-
#
|
139
|
-
# @return [void]
|
140
|
-
#
|
141
|
-
def create_software_license_files
|
142
|
-
license_map.each do |name, values|
|
143
|
-
license_files = values[:license_files]
|
144
|
-
|
145
|
-
license_files.each do |license_file|
|
146
|
-
if license_file
|
147
|
-
output_file = license_package_location(name, license_file)
|
148
|
-
|
149
|
-
if local?(license_file)
|
150
|
-
input_file = File.expand_path(license_file, values[:project_dir])
|
151
|
-
if File.exist?(input_file)
|
152
|
-
FileUtils.cp(input_file, output_file)
|
153
|
-
else
|
154
|
-
licensing_warning("License file '#{input_file}' does not exist for software '#{name}'.")
|
155
|
-
end
|
156
|
-
else
|
157
|
-
begin
|
158
|
-
download_file!(license_file, output_file, enable_progress_bar: false)
|
159
|
-
rescue SocketError,
|
160
|
-
Errno::ECONNREFUSED,
|
161
|
-
Errno::ECONNRESET,
|
162
|
-
Errno::ENETUNREACH,
|
163
|
-
Timeout::Error,
|
164
|
-
OpenURI::HTTPError
|
165
|
-
licensing_warning("Can not download license file '#{license_file}' for software '#{name}'.")
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
212
|
+
f.puts ""
|
213
|
+
f.puts dependencies_license_summary
|
170
214
|
end
|
171
215
|
end
|
172
216
|
|
@@ -176,7 +220,7 @@ module Omnibus
|
|
176
220
|
# @return [String]
|
177
221
|
#
|
178
222
|
def project_license_content
|
179
|
-
project.license_file.nil? ? "" : IO.read(File.join(Config.project_root,project.license_file))
|
223
|
+
project.license_file.nil? ? "" : IO.read(File.join(Config.project_root, project.license_file))
|
180
224
|
end
|
181
225
|
|
182
226
|
#
|
@@ -213,6 +257,41 @@ module Omnibus
|
|
213
257
|
out
|
214
258
|
end
|
215
259
|
|
260
|
+
#
|
261
|
+
# Summary of the licenses of the transitive dependencies of the project.
|
262
|
+
# It is in the form of:
|
263
|
+
# ...
|
264
|
+
# This product includes inifile 3.0.0
|
265
|
+
# which is a 'ruby_bundler' dependency of 'chef',
|
266
|
+
# and which is available under a 'MIT' License.
|
267
|
+
# For details, see:
|
268
|
+
# /opt/opscode/LICENSES/ruby_bundler-inifile-3.0.0-README.md
|
269
|
+
# ...
|
270
|
+
#
|
271
|
+
# @return [String]
|
272
|
+
#
|
273
|
+
def dependencies_license_summary
|
274
|
+
out = "\n\n"
|
275
|
+
|
276
|
+
dep_license_map.each do |dep_mgr_name, data|
|
277
|
+
data.each do |dep_name, data|
|
278
|
+
data.each do |dep_version, dep_data|
|
279
|
+
projects = dep_data["dependency_of"].sort.map { |p| "'#{p}'" }.join(", ")
|
280
|
+
files = dep_data["license_files"].map { |f| File.join(output_dir, f) }
|
281
|
+
|
282
|
+
out << "This product includes #{dep_name} #{dep_version}\n"
|
283
|
+
out << "which is a '#{dep_mgr_name}' dependency of #{projects},\n"
|
284
|
+
out << "and which is available under a '#{dep_data["license"]}' License.\n"
|
285
|
+
out << "For details, see:\n"
|
286
|
+
out << files.join("\n")
|
287
|
+
out << "\n\n"
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
out
|
293
|
+
end
|
294
|
+
|
216
295
|
#
|
217
296
|
# Map that collects information about the licenses of the softwares
|
218
297
|
# included in the project.
|
@@ -279,6 +358,34 @@ module Omnibus
|
|
279
358
|
File.expand_path(OUTPUT_DIRECTORY, project.install_dir)
|
280
359
|
end
|
281
360
|
|
361
|
+
#
|
362
|
+
# Path to a .gitkeep file we create in the output dir so git caching
|
363
|
+
# doesn't delete the directory.
|
364
|
+
#
|
365
|
+
# @return [String]
|
366
|
+
#
|
367
|
+
def output_dir_gitkeep_file
|
368
|
+
File.join(output_dir, ".gitkeep")
|
369
|
+
end
|
370
|
+
|
371
|
+
# Cache directory where transitive dependency licenses will be collected in.
|
372
|
+
#
|
373
|
+
# @return [String]
|
374
|
+
#
|
375
|
+
def cache_dir
|
376
|
+
File.expand_path(CACHE_DIRECTORY, project.install_dir)
|
377
|
+
end
|
378
|
+
|
379
|
+
#
|
380
|
+
# Path to a .gitkeep file we create in the cache dir so git caching
|
381
|
+
# doesn't delete the directory.
|
382
|
+
#
|
383
|
+
# @return [String]
|
384
|
+
#
|
385
|
+
def cache_dir_gitkeep_file
|
386
|
+
File.join(cache_dir, ".gitkeep")
|
387
|
+
end
|
388
|
+
|
282
389
|
#
|
283
390
|
# Returns if the given path to a license is local or a remote url.
|
284
391
|
#
|
@@ -290,14 +397,194 @@ module Omnibus
|
|
290
397
|
end
|
291
398
|
|
292
399
|
#
|
293
|
-
# Logs the given message as
|
400
|
+
# Logs the given message as info.
|
401
|
+
#
|
402
|
+
# This method should only be used for detecting in a license is known or not.
|
403
|
+
# In the future, we will introduce a configurable way to whitelist or blacklist
|
404
|
+
# the allowed licenses. Once we implement that we need to stop using this method.
|
405
|
+
#
|
406
|
+
# @param [String] message
|
407
|
+
# message to log as warning
|
408
|
+
def licensing_info(message)
|
409
|
+
log.info(log_key) { message }
|
410
|
+
end
|
411
|
+
|
412
|
+
#
|
413
|
+
# Logs the given message as warning or fails the build depending on the
|
414
|
+
# :fatal_licensing_warnings configuration setting.
|
294
415
|
#
|
295
416
|
# @param [String] message
|
296
417
|
# message to log as warning
|
297
418
|
def licensing_warning(message)
|
419
|
+
licensing_warnings << message
|
420
|
+
log.warn(log_key) { message }
|
421
|
+
end
|
422
|
+
|
423
|
+
#
|
424
|
+
# Logs the given message as warning or fails the build depending on the
|
425
|
+
# :fatal_transitive_dependency_licensing_warnings configuration setting.
|
426
|
+
#
|
427
|
+
# @param [String] message
|
428
|
+
# message to log as warning
|
429
|
+
def transitive_dependency_licensing_warning(message)
|
430
|
+
transitive_dependency_licensing_warnings << message
|
298
431
|
log.warn(log_key) { message }
|
299
432
|
end
|
300
433
|
|
434
|
+
def raise_if_warnings_fatal!
|
435
|
+
warnings_to_raise = []
|
436
|
+
if Config.fatal_licensing_warnings && !licensing_warnings.empty?
|
437
|
+
warnings_to_raise << licensing_warnings
|
438
|
+
end
|
439
|
+
|
440
|
+
if Config.fatal_transitive_dependency_licensing_warnings && !transitive_dependency_licensing_warnings.empty?
|
441
|
+
warnings_to_raise << transitive_dependency_licensing_warnings
|
442
|
+
end
|
443
|
+
|
444
|
+
warnings_to_raise.flatten!
|
445
|
+
raise LicensingError.new(warnings_to_raise) unless warnings_to_raise.empty?
|
446
|
+
end
|
447
|
+
|
448
|
+
# 1. Parse all the licensing information for all software from 'cache_dir'
|
449
|
+
# 2. Merge and drop the duplicates
|
450
|
+
# 3. Add these licenses to the main manifest, to be merged with the main
|
451
|
+
# licensing information from software definitions.
|
452
|
+
def process_transitive_dependency_licensing_info
|
453
|
+
Dir.glob("#{cache_dir}/*/*-dependency-licenses.json").each do |license_manifest_path|
|
454
|
+
license_manifest_data = FFI_Yajl::Parser.parse(File.read(license_manifest_path))
|
455
|
+
project_name = license_manifest_data["project_name"]
|
456
|
+
dependency_license_dir = File.dirname(license_manifest_path)
|
457
|
+
|
458
|
+
license_manifest_data["dependency_managers"].each do |dep_mgr_name, dependencies|
|
459
|
+
dep_license_map[dep_mgr_name] ||= {}
|
460
|
+
|
461
|
+
dependencies.each do |dependency|
|
462
|
+
# Copy dependency files
|
463
|
+
dependency["license_files"].each do |f|
|
464
|
+
license_path = File.join(dependency_license_dir, f)
|
465
|
+
output_path = File.join(output_dir, f)
|
466
|
+
FileUtils.cp(license_path, output_path)
|
467
|
+
end
|
468
|
+
|
469
|
+
dep_name = dependency["name"]
|
470
|
+
dep_version = dependency["version"]
|
471
|
+
|
472
|
+
# If we already have this dependency we do not need to add it again.
|
473
|
+
if dep_license_map[dep_mgr_name][dep_name] && dep_license_map[dep_mgr_name][dep_name][dep_version]
|
474
|
+
dep_license_map[dep_mgr_name][dep_name][dep_version]["dependency_of"] << project_name
|
475
|
+
else
|
476
|
+
dep_license_map[dep_mgr_name][dep_name] ||= {}
|
477
|
+
dep_license_map[dep_mgr_name][dep_name][dep_version] = {
|
478
|
+
"license" => dependency["license"],
|
479
|
+
"license_files" => dependency["license_files"],
|
480
|
+
"dependency_of" => [ project_name ],
|
481
|
+
}
|
482
|
+
end
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
FileUtils.rm_rf(cache_dir)
|
488
|
+
end
|
489
|
+
|
490
|
+
private
|
491
|
+
|
492
|
+
# Uses license_scout to collect the licenses for transitive dependencies
|
493
|
+
# into #{output_dir}/license-cache/#{software.name}
|
494
|
+
def collect_transitive_dependency_licenses_for(software)
|
495
|
+
# We collect the licenses of the transitive dependencies of this software
|
496
|
+
# with LicenseScout. We place these files under
|
497
|
+
# /opt/project-name/license-cache for them to be cached in git_cache. Once
|
498
|
+
# the build completes we will process these license files but we need to
|
499
|
+
# perform this step after build, before git_cache to be able to operate
|
500
|
+
# correctly with the git_cache.
|
501
|
+
license_output_dir = File.join(cache_dir, software.name)
|
502
|
+
|
503
|
+
collector = LicenseScout::Collector.new(
|
504
|
+
software.project.name,
|
505
|
+
software.project_dir,
|
506
|
+
license_output_dir,
|
507
|
+
LicenseScout::Options.new(
|
508
|
+
environment: software.with_embedded_path,
|
509
|
+
ruby_bin: software.embedded_bin("ruby")
|
510
|
+
)
|
511
|
+
)
|
512
|
+
|
513
|
+
begin
|
514
|
+
collector.run
|
515
|
+
collector.issue_report.each { |i| transitive_dependency_licensing_warning(i) }
|
516
|
+
rescue LicenseScout::Exceptions::UnsupportedProjectType => e
|
517
|
+
# Looks like this project is not supported by LicenseScout. Either the
|
518
|
+
# language and the dependency manager used by the project is not
|
519
|
+
# supported, or the software definition does not have any transitive
|
520
|
+
# dependencies. In the latter case software definition should set
|
521
|
+
# 'skip_transitive_dependency_licensing' to 'true' to correct this
|
522
|
+
# error.
|
523
|
+
transitive_dependency_licensing_warning(<<-EOH)
|
524
|
+
Software '#{software.name}' is not supported project type for transitive \
|
525
|
+
dependency license collection. See https://github.com/chef/license_scout for \
|
526
|
+
the list of supported languages and dependency managers. If this project does \
|
527
|
+
not have any transitive dependencies, consider setting \
|
528
|
+
'skip_transitive_dependency_licensing' to 'true' in order to correct this error.
|
529
|
+
EOH
|
530
|
+
rescue LicenseScout::Exceptions::Error => e
|
531
|
+
transitive_dependency_licensing_warning(<<-EOH)
|
532
|
+
Can not automatically detect licensing information for '#{software.name}' using \
|
533
|
+
license_scout. Error is: '#{e}'
|
534
|
+
EOH
|
535
|
+
rescue Exception => e
|
536
|
+
transitive_dependency_licensing_warning(<<-EOH)
|
537
|
+
Unexpected error while running license_scout for '#{software.name}': '#{e}'
|
538
|
+
EOH
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
# Collect the license files for the software.
|
543
|
+
def collect_licenses_for(software)
|
544
|
+
return nil if software.license == :project_license
|
545
|
+
|
546
|
+
software_name = software.name
|
547
|
+
license_data = license_map[software_name]
|
548
|
+
license_files = license_data[:license_files]
|
549
|
+
|
550
|
+
license_files.each do |license_file|
|
551
|
+
if license_file
|
552
|
+
output_file = license_package_location(software_name, license_file)
|
553
|
+
|
554
|
+
if local?(license_file)
|
555
|
+
input_file = File.expand_path(license_file, license_data[:project_dir])
|
556
|
+
if File.exist?(input_file)
|
557
|
+
FileUtils.cp(input_file, output_file)
|
558
|
+
File.chmod 0644, output_file unless windows?
|
559
|
+
else
|
560
|
+
licensing_warning("License file '#{input_file}' does not exist for software '#{software_name}'.")
|
561
|
+
# If we got here, we need to fail now so we don't take a git
|
562
|
+
# cache snapshot, or else the software build could be restored
|
563
|
+
# from cache without fixing the license issue.
|
564
|
+
raise_if_warnings_fatal!
|
565
|
+
end
|
566
|
+
else
|
567
|
+
begin
|
568
|
+
download_file!(license_file, output_file, enable_progress_bar: false)
|
569
|
+
File.chmod 0644, output_file unless windows?
|
570
|
+
rescue SocketError,
|
571
|
+
Errno::ECONNREFUSED,
|
572
|
+
Errno::ECONNRESET,
|
573
|
+
Errno::ENETUNREACH,
|
574
|
+
Timeout::Error,
|
575
|
+
OpenURI::HTTPError,
|
576
|
+
OpenSSL::SSL::SSLError
|
577
|
+
licensing_warning("Can not download license file '#{license_file}' for software '#{software_name}'.")
|
578
|
+
# If we got here, we need to fail now so we don't take a git
|
579
|
+
# cache snapshot, or else the software build could be restored
|
580
|
+
# from cache without fixing the license issue.
|
581
|
+
raise_if_warnings_fatal!
|
582
|
+
end
|
583
|
+
end
|
584
|
+
end
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
301
588
|
STANDARD_LICENSES = [
|
302
589
|
#
|
303
590
|
# Below licenses are compiled based on https://opensource.org/licenses/alphabetical
|
@@ -392,4 +679,5 @@ module Omnibus
|
|
392
679
|
"Chef-MLSA", # https://www.chef.io/online-master-agreement/
|
393
680
|
].freeze
|
394
681
|
end
|
682
|
+
|
395
683
|
end
|
data/lib/omnibus/logger.rb
CHANGED
@@ -16,19 +16,22 @@
|
|
16
16
|
|
17
17
|
module Omnibus
|
18
18
|
class Logger
|
19
|
+
|
20
|
+
require "time"
|
21
|
+
|
19
22
|
#
|
20
23
|
# The amount of padding on the left column.
|
21
24
|
#
|
22
25
|
# @return [Fixnum]
|
23
26
|
#
|
24
|
-
LEFT =
|
27
|
+
LEFT = 30
|
25
28
|
|
26
29
|
#
|
27
30
|
# Our custom log levels, in order of severity
|
28
31
|
#
|
29
32
|
# @return [Array]
|
30
33
|
#
|
31
|
-
LEVELS = %w
|
34
|
+
LEVELS = %w{UNKNOWN INTERNAL DEBUG INFO WARN ERROR FATAL NOTHING}.freeze
|
32
35
|
|
33
36
|
#
|
34
37
|
# The mutex lock for synchronizing IO writing.
|
@@ -48,7 +51,7 @@ module Omnibus
|
|
48
51
|
#
|
49
52
|
def initialize(io = $stdout)
|
50
53
|
@io = io
|
51
|
-
@level = LEVELS.index(
|
54
|
+
@level = LEVELS.index("WARN")
|
52
55
|
end
|
53
56
|
|
54
57
|
LEVELS.each.with_index do |level, index|
|
@@ -66,8 +69,8 @@ module Omnibus
|
|
66
69
|
# @see (Logger#add)
|
67
70
|
#
|
68
71
|
def deprecated(progname, &block)
|
69
|
-
meta = Proc.new { "DEPRECATED: #{
|
70
|
-
add(LEVELS.index(
|
72
|
+
meta = Proc.new { "DEPRECATED: #{yield}" }
|
73
|
+
add(LEVELS.index("WARN"), progname, &meta)
|
71
74
|
end
|
72
75
|
|
73
76
|
#
|
@@ -135,7 +138,7 @@ module Omnibus
|
|
135
138
|
else
|
136
139
|
left = "#{format_severity(severity)} | "
|
137
140
|
end
|
138
|
-
"#{left.rjust(LEFT)}#{message}\n"
|
141
|
+
"#{left.rjust(LEFT)}#{Time.now.iso8601()} | #{message}\n"
|
139
142
|
end
|
140
143
|
|
141
144
|
#
|
@@ -145,9 +148,9 @@ module Omnibus
|
|
145
148
|
#
|
146
149
|
def format_severity(severity)
|
147
150
|
if severity == 0
|
148
|
-
|
151
|
+
"_"
|
149
152
|
else
|
150
|
-
(LEVELS[severity] ||
|
153
|
+
(LEVELS[severity] || "?")[0]
|
151
154
|
end
|
152
155
|
end
|
153
156
|
|
@@ -167,7 +170,7 @@ module Omnibus
|
|
167
170
|
def initialize(log, level = :debug)
|
168
171
|
@log = log
|
169
172
|
@level = level
|
170
|
-
@buffer =
|
173
|
+
@buffer = ""
|
171
174
|
end
|
172
175
|
|
173
176
|
#
|
data/lib/omnibus/logging.rb
CHANGED
data/lib/omnibus/manifest.rb
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
require
|
17
|
+
require "ffi_yajl"
|
18
18
|
|
19
19
|
module Omnibus
|
20
20
|
class Manifest
|
@@ -27,7 +27,7 @@ module Omnibus
|
|
27
27
|
LATEST_MANIFEST_FORMAT = 2
|
28
28
|
|
29
29
|
attr_reader :build_version, :build_git_revision, :license
|
30
|
-
def initialize(version=nil, git_rev=nil, license="Unspecified")
|
30
|
+
def initialize(version = nil, git_rev = nil, license = "Unspecified")
|
31
31
|
@data = {}
|
32
32
|
@build_version = version
|
33
33
|
@build_git_revision = git_rev
|
@@ -68,13 +68,13 @@ module Omnibus
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def to_hash
|
71
|
-
software_hash = @data.inject({}) do |memo, (k,v)|
|
71
|
+
software_hash = @data.inject({}) do |memo, (k, v)|
|
72
72
|
memo[k] = v.to_hash
|
73
73
|
memo
|
74
74
|
end
|
75
75
|
ret = {
|
76
76
|
manifest_format: LATEST_MANIFEST_FORMAT,
|
77
|
-
software: software_hash
|
77
|
+
software: software_hash,
|
78
78
|
}
|
79
79
|
ret[:build_version] = build_version if build_version
|
80
80
|
ret[:build_git_revision] = build_git_revision if build_git_revision
|
@@ -27,8 +27,8 @@ module Omnibus
|
|
27
27
|
@updated ||=
|
28
28
|
begin
|
29
29
|
(first.entry_names & second.entry_names).collect do |name|
|
30
|
-
|
31
|
-
|
30
|
+
diff(first.entry_for(name), second.entry_for(name))
|
31
|
+
end.compact
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -36,8 +36,8 @@ module Omnibus
|
|
36
36
|
@removed ||=
|
37
37
|
begin
|
38
38
|
(first.entry_names - second.entry_names).collect do |name|
|
39
|
-
|
40
|
-
|
39
|
+
removed_entry(first.entry_for(name))
|
40
|
+
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -45,8 +45,8 @@ module Omnibus
|
|
45
45
|
@added ||=
|
46
46
|
begin
|
47
47
|
(second.entry_names - first.entry_names).collect do |name|
|
48
|
-
|
49
|
-
|
48
|
+
new_entry(second.entry_for(name))
|
49
|
+
end
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -65,7 +65,6 @@ module Omnibus
|
|
65
65
|
source: entry.locked_source }
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
68
|
def removed_entry(entry)
|
70
69
|
{ name: entry.name,
|
71
70
|
old_version: entry.locked_version,
|