From 3085908ea1743ec04a4e5c64148b23eb1b97fd43 Mon Sep 17 00:00:00 2001 From: Jon Ruskin Date: Sat, 12 Nov 2022 15:49:53 -0700 Subject: [PATCH 1/4] allow generating notice file from live data --- lib/licensed/cli.rb | 6 +++-- lib/licensed/commands/notices.rb | 31 +++++++++++++++++++--- lib/licensed/reporters/notices_reporter.rb | 10 +++---- test/commands/notices_test.rb | 31 ++++++++++++++++++---- 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/lib/licensed/cli.rb b/lib/licensed/cli.rb index 75712460..2c338c93 100644 --- a/lib/licensed/cli.rb +++ b/lib/licensed/cli.rb @@ -46,13 +46,15 @@ def list run Licensed::Commands::List.new(config: config), sources: options[:sources], reporter: options[:format], licenses: options[:licenses] end - desc "notices", "Generate a NOTICE file from cached records" + desc "notices", "Generate a NOTICE file with dependency data" method_option :config, aliases: "-c", type: :string, desc: "Path to licensed configuration file" method_option :sources, aliases: "-s", type: :array, desc: "Individual source(s) to evaluate. Must also be enabled via configuration." + method_option :computed, aliases: "-l", type: :boolean, + desc: "Whether to generate a NOTICE file using computed data or cached records" def notices - run Licensed::Commands::Notices.new(config: config), sources: options[:sources] + run Licensed::Commands::Notices.new(config: config), sources: options[:sources], computed: options[:computed] end map "-v" => :version diff --git a/lib/licensed/commands/notices.rb b/lib/licensed/commands/notices.rb index ad7f0b33..18d85e0c 100644 --- a/lib/licensed/commands/notices.rb +++ b/lib/licensed/commands/notices.rb @@ -13,7 +13,7 @@ def default_reporter(options) protected - # Load stored dependency record data to add to the notices report. + # Load a dependency record data and add it to the notices report. # # app - The application configuration for the dependency # source - The dependency source enumerator for the dependency @@ -22,13 +22,36 @@ def default_reporter(options) # # Returns true. def evaluate_dependency(app, source, dependency, report) + report["record"] = + if load_dependency_record_from_files + load_cached_dependency_record(app, source, dependency, report) + else + dependency.record + end + + true + end + + # Loads a dependency record from a cached file. + # + # app - The application configuration for the dependency + # source - The dependency source enumerator for the dependency + # dependency - An application dependency + # report - A report hash for the command to provide extra data for the report output. + # + # Returns a dependency record or nil if one doesn't exist + def load_cached_dependency_record(app, source, dependency, report) filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}") - report["cached_record"] = Licensed::DependencyRecord.read(filename) - if !report["cached_record"] + record = Licensed::DependencyRecord.read(filename) + if !record report.warnings << "expected cached record not found at #{filename}" end - true + record + end + + def load_dependency_record_from_files + !options.fetch(:computed, false) end end end diff --git a/lib/licensed/reporters/notices_reporter.rb b/lib/licensed/reporters/notices_reporter.rb index 023f2e11..861984b2 100644 --- a/lib/licensed/reporters/notices_reporter.rb +++ b/lib/licensed/reporters/notices_reporter.rb @@ -54,11 +54,11 @@ def end_report_dependency(dependency, report) def notices(report) return unless report.target.is_a?(Licensed::Dependency) - cached_record = report["cached_record"] - return unless cached_record + record = report["record"] + return unless record - texts = cached_record.licenses.map(&:text) - cached_record.notices.each do |notice| + texts = record.licenses.map(&:text) + record.notices.each do |notice| case notice when Hash texts << notice["text"] @@ -70,7 +70,7 @@ def notices(report) end <<~NOTICE - #{cached_record["name"]}@#{cached_record["version"]} + #{record["name"]}@#{record["version"]} #{texts.map(&:strip).reject(&:empty?).compact.join(TEXT_SEPARATOR)} NOTICE diff --git a/test/commands/notices_test.rb b/test/commands/notices_test.rb index 294b7841..f9027cb5 100644 --- a/test/commands/notices_test.rb +++ b/test/commands/notices_test.rb @@ -40,15 +40,36 @@ def dependency_report(app, source, dependency_name = "dependency") source.dependencies.each do |dependency| report = dependency_report(app, source, dependency.name) assert report - assert_equal dependency.record["name"], report["cached_record"]["name"] - assert_equal dependency.record["version"], report["cached_record"]["version"] - assert_equal dependency.record.content, report["cached_record"].content + assert_equal dependency.record["name"], report["record"]["name"] + assert_equal dependency.record["version"], report["record"]["version"] + assert_equal dependency.record.content, report["record"].content end end end end - it "reports a warning on missing cached records" do + it "reports computed records found for dependencies" do + # delete all cached files for dependencies + config.apps.each do |app| + FileUtils.rm_rf app.cache_path + end + + run_command(computed: true) + + config.apps.each do |app| + app.sources.each do |source| + source.dependencies.each do |dependency| + report = dependency_report(app, source, dependency.name) + assert report + assert_equal dependency.record["name"], report["record"]["name"] + assert_equal dependency.record["version"], report["record"]["version"] + assert_equal dependency.record.content, report["record"].content + end + end + end + end + + it "reports a warning on missing records" do config.apps.each { |app| FileUtils.rm_rf app.cache_path } run_command @@ -57,7 +78,7 @@ def dependency_report(app, source, dependency_name = "dependency") source.dependencies.each do |dependency| report = dependency_report(app, source, dependency.name) assert report - assert_nil report["cached_record"] + assert_nil report["record"] path = app.cache_path.join(source.class.type, "#{dependency.name}.#{Licensed::DependencyRecord::EXTENSION}") assert_equal ["expected cached record not found at #{path}"], report.warnings From 66335192c6513161225962184ed70bb02d2cef8e Mon Sep 17 00:00:00 2001 From: licensed-ci Date: Sat, 12 Nov 2022 22:57:50 +0000 Subject: [PATCH 2/4] Auto-update license files --- .licenses/bundler/bundler.dep.yml | 2 +- .licenses/bundler/faraday-net_http.dep.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.licenses/bundler/bundler.dep.yml b/.licenses/bundler/bundler.dep.yml index ee9f98c5..7be7e953 100644 --- a/.licenses/bundler/bundler.dep.yml +++ b/.licenses/bundler/bundler.dep.yml @@ -1,6 +1,6 @@ --- name: bundler -version: 2.3.24 +version: 2.3.25 type: bundler summary: The best way to manage your application's dependencies homepage: https://bundler.io diff --git a/.licenses/bundler/faraday-net_http.dep.yml b/.licenses/bundler/faraday-net_http.dep.yml index a126a3f2..1531c469 100644 --- a/.licenses/bundler/faraday-net_http.dep.yml +++ b/.licenses/bundler/faraday-net_http.dep.yml @@ -1,6 +1,6 @@ --- name: faraday-net_http -version: 3.0.1 +version: 3.0.2 type: bundler summary: Faraday adapter for Net::HTTP homepage: https://github.com/lostisland/faraday-net_http From c103b2ff8108c05f5bc79e1eae3527dfde20293e Mon Sep 17 00:00:00 2001 From: Jon Ruskin Date: Sat, 12 Nov 2022 16:15:04 -0700 Subject: [PATCH 3/4] Update notices_reporter_test.rb --- test/reporters/notices_reporter_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/reporters/notices_reporter_test.rb b/test/reporters/notices_reporter_test.rb index 2a1f0c0f..972f78fb 100644 --- a/test/reporters/notices_reporter_test.rb +++ b/test/reporters/notices_reporter_test.rb @@ -39,7 +39,7 @@ end it "prints a warning if dependency notice contents can't be parsed" do - dependency_report["cached_record"] = Licensed::DependencyRecord.new( + dependency_report["record"] = Licensed::DependencyRecord.new( licenses: [], notices: [1] ) @@ -54,7 +54,7 @@ end it "writes dependencies' licenses and notices to a NOTICE file" do - dependency_report["cached_record"] = Licensed::DependencyRecord.new( + dependency_report["record"] = Licensed::DependencyRecord.new( licenses: [ { "sources" => "LICENSE1", "text" => "license1" }, { "sources" => "LICENSE2", "text" => "license2" } @@ -77,7 +77,7 @@ it "writes dependencies' licenses and notices to a NOTICE. file in a shared cache" do app["shared_cache"] = true - dependency_report["cached_record"] = Licensed::DependencyRecord.new( + dependency_report["record"] = Licensed::DependencyRecord.new( licenses: [ { "sources" => "LICENSE1", "text" => "license1" }, { "sources" => "LICENSE2", "text" => "license2" } From 2e9c0f4e5354128c5bc6d4efb306c71d9b83e386 Mon Sep 17 00:00:00 2001 From: Jon Ruskin Date: Sun, 13 Nov 2022 11:24:59 -0700 Subject: [PATCH 4/4] docs updates --- docs/commands/notices.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/commands/notices.md b/docs/commands/notices.md index 97b4970d..e4cfa3e7 100644 --- a/docs/commands/notices.md +++ b/docs/commands/notices.md @@ -2,7 +2,7 @@ Outputs license and notice text for all dependencies in each app into a `NOTICE` file in the app's `cache_path`. If an app uses a shared cache path, the file name will contain the app name as well, e.g. `NOTICE.my_app`. -`NOTICE` file contents are retrieved from cached records, with the assumption that cached records have already been reviewed in a compliance workflow. +`NOTICE` file contents are retrieved from cached records when the `--computed`/`-l` option is not set, with the assumption that cached records have already been reviewed in a compliance workflow. When the `--computed`/`-l` option is set and a dependency's license is not found, that dependency's license text will be empty in the `NOTICE` file. ## Options @@ -10,3 +10,5 @@ Outputs license and notice text for all dependencies in each app into a `NOTICE` - default value: `./.licensed.yml` - `--sources`/`-s`: runtime filter on which dependency sources are run. Sources must also be enabled in the licensed configuration file. - default value: not set, all configured sources +- `--computed`/`-l`: use live computed when generating a `NOTICE` file + - default value: not set, `NOTICE` file generated from cached records