licensed 3.0.0 → 3.2.1

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +19 -0
  3. data/.github/workflows/release.yml +4 -4
  4. data/.github/workflows/test.yml +180 -47
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +60 -1
  7. data/README.md +25 -79
  8. data/docker/Dockerfile.build-linux +1 -1
  9. data/docs/adding_a_new_source.md +11 -8
  10. data/docs/commands/README.md +59 -0
  11. data/docs/commands/cache.md +35 -0
  12. data/docs/commands/env.md +10 -0
  13. data/docs/commands/list.md +23 -0
  14. data/docs/commands/migrate.md +10 -0
  15. data/docs/commands/notices.md +12 -0
  16. data/docs/commands/status.md +74 -0
  17. data/docs/commands/version.md +3 -0
  18. data/docs/configuration/README.md +11 -0
  19. data/docs/configuration/allowed_licenses.md +17 -0
  20. data/docs/configuration/application_name.md +63 -0
  21. data/docs/configuration/application_source.md +64 -0
  22. data/docs/configuration/configuration_root.md +27 -0
  23. data/docs/configuration/configuring_multiple_apps.md +58 -0
  24. data/docs/configuration/dependency_source_enumerators.md +28 -0
  25. data/docs/configuration/ignoring_dependencies.md +19 -0
  26. data/docs/configuration/metadata_cache.md +106 -0
  27. data/docs/configuration/reviewing_dependencies.md +18 -0
  28. data/docs/configuration.md +9 -161
  29. data/docs/sources/swift.md +4 -0
  30. data/lib/licensed/cli.rb +2 -2
  31. data/lib/licensed/commands/cache.rb +19 -20
  32. data/lib/licensed/commands/command.rb +104 -72
  33. data/lib/licensed/commands/environment.rb +12 -11
  34. data/lib/licensed/commands/list.rb +0 -19
  35. data/lib/licensed/commands/notices.rb +0 -19
  36. data/lib/licensed/commands/status.rb +13 -15
  37. data/lib/licensed/configuration.rb +105 -12
  38. data/lib/licensed/report.rb +44 -0
  39. data/lib/licensed/reporters/cache_reporter.rb +48 -64
  40. data/lib/licensed/reporters/json_reporter.rb +19 -21
  41. data/lib/licensed/reporters/list_reporter.rb +45 -58
  42. data/lib/licensed/reporters/notices_reporter.rb +33 -46
  43. data/lib/licensed/reporters/reporter.rb +37 -104
  44. data/lib/licensed/reporters/status_reporter.rb +58 -56
  45. data/lib/licensed/reporters/yaml_reporter.rb +19 -21
  46. data/lib/licensed/sources/bundler/definition.rb +36 -0
  47. data/lib/licensed/sources/bundler/missing_specification.rb +1 -1
  48. data/lib/licensed/sources/bundler.rb +38 -86
  49. data/lib/licensed/sources/dep.rb +2 -2
  50. data/lib/licensed/sources/go.rb +3 -3
  51. data/lib/licensed/sources/gradle.rb +2 -2
  52. data/lib/licensed/sources/helpers/content_versioning.rb +2 -1
  53. data/lib/licensed/sources/npm.rb +4 -3
  54. data/lib/licensed/sources/nuget.rb +56 -27
  55. data/lib/licensed/sources/swift.rb +69 -0
  56. data/lib/licensed/sources.rb +1 -0
  57. data/lib/licensed/version.rb +1 -1
  58. data/lib/licensed.rb +1 -0
  59. data/licensed.gemspec +4 -4
  60. data/script/source-setup/go +1 -1
  61. data/script/source-setup/swift +22 -0
  62. metadata +48 -13
  63. data/docs/commands.md +0 -95
@@ -4,31 +4,29 @@ require "json"
4
4
  module Licensed
5
5
  module Reporters
6
6
  class JsonReporter < Reporter
7
- def report_run(command)
8
- super do |report|
9
- result = yield report
10
-
11
- report["apps"] = report.reports.map(&:to_h) if report.reports.any?
12
- shell.info JSON.pretty_generate(report.to_h)
13
-
14
- result
15
- end
7
+ # Report all information from the command run to the shell as a JSON object
8
+ #
9
+ # command - The command being run
10
+ # report - A report object containing information about the command run
11
+ def end_report_command(command, report)
12
+ report["apps"] = report.reports.map(&:to_h) if report.reports.any?
13
+ shell.info JSON.pretty_generate(report.to_h)
16
14
  end
17
15
 
18
- def report_app(app)
19
- super do |report|
20
- result = yield report
21
- report["sources"] = report.reports.map(&:to_h) if report.reports.any?
22
- result
23
- end
16
+ # Add source report information to the app report hash
17
+ #
18
+ # app - An application configuration
19
+ # report - A report object containing information about the app evaluation
20
+ def end_report_app(app, report)
21
+ report["sources"] = report.reports.map(&:to_h) if report.reports.any?
24
22
  end
25
23
 
26
- def report_source(source)
27
- super do |report|
28
- result = yield report
29
- report["dependencies"] = report.reports.map(&:to_h) if report.reports.any?
30
- result
31
- end
24
+ # Add dependency report information to the source report hash
25
+ #
26
+ # source - A dependency source enumerator
27
+ # report - A report object containing information about the source evaluation
28
+ def end_report_source(source, report)
29
+ report["dependencies"] = report.reports.map(&:to_h) if report.reports.any?
32
30
  end
33
31
  end
34
32
  end
@@ -3,84 +3,71 @@
3
3
  module Licensed
4
4
  module Reporters
5
5
  class ListReporter < Reporter
6
- # Reports on an application configuration in a list command run
6
+ # Reports the start of application configuration in a list command run
7
7
  #
8
8
  # app - An application configuration
9
- #
10
- # Returns the result of the yielded method
11
- # Note - must be called from inside the `report_run` scope
12
- def report_app(app)
13
- super do |report|
14
- shell.info "Listing dependencies for #{app["name"]}"
15
- yield report
16
- end
9
+ # report - A report object containing information about the app evaluation
10
+ def begin_report_app(app, report)
11
+ shell.info "Listing dependencies for #{app["name"]}"
17
12
  end
18
13
 
19
- # Reports on a dependency source enumerator in a list command run.
20
- # Shows the type and count of dependencies found by the source.
14
+ # Reports the start of a source evaluation
21
15
  #
22
16
  # source - A dependency source enumerator
23
- #
24
- # Returns the result of the yielded method
25
- # Note - must be called from inside the `report_run` scope
26
- def report_source(source)
27
- super do |report|
28
- shell.info " #{source.class.type}"
29
- result = yield report
17
+ # report - A report object containing information about the source evaluation
18
+ def begin_report_source(source, report)
19
+ shell.info " #{source.class.type}"
20
+ end
30
21
 
31
- warning_reports = report.all_reports.select { |r| r.warnings.any? }.to_a
32
- if warning_reports.any?
33
- shell.newline
34
- shell.warn " * Warnings:"
35
- warning_reports.each do |r|
36
- display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
22
+ # Report the type and count of dependencies found by the source,
23
+ # along with any warnings and errors
24
+ #
25
+ # source - A dependency source enumerator
26
+ # report - A report object containing information about the source evaluation
27
+ def end_report_source(source, report)
28
+ warning_reports = report.all_reports.select { |r| r.warnings.any? }.to_a
29
+ if warning_reports.any?
30
+ shell.newline
31
+ shell.warn " * Warnings:"
32
+ warning_reports.each do |r|
33
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
37
34
 
38
- shell.warn " * #{r.name}"
39
- shell.warn " #{display_metadata}" unless display_metadata.empty?
40
- r.warnings.each do |warning|
41
- shell.warn " - #{warning}"
42
- end
43
- shell.newline
35
+ shell.warn " * #{r.name}"
36
+ shell.warn " #{display_metadata}" unless display_metadata.empty?
37
+ r.warnings.each do |warning|
38
+ shell.warn " - #{warning}"
44
39
  end
40
+ shell.newline
45
41
  end
42
+ end
46
43
 
47
- errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
48
- if errored_reports.any?
49
- shell.newline
50
- shell.error " * Errors:"
51
- errored_reports.each do |r|
52
- display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
44
+ errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
45
+ if errored_reports.any?
46
+ shell.newline
47
+ shell.error " * Errors:"
48
+ errored_reports.each do |r|
49
+ display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
53
50
 
54
- shell.error " * #{r.name}"
55
- shell.error " #{display_metadata}" unless display_metadata.empty?
56
- r.errors.each do |error|
57
- shell.error " - #{error}"
58
- end
59
- shell.newline
51
+ shell.error " * #{r.name}"
52
+ shell.error " #{display_metadata}" unless display_metadata.empty?
53
+ r.errors.each do |error|
54
+ shell.error " - #{error}"
60
55
  end
61
- else
62
- shell.confirm " * #{report.reports.size} #{source.class.type} dependencies"
56
+ shell.newline
63
57
  end
64
-
65
- result
58
+ else
59
+ shell.confirm " * #{report.reports.size} #{source.class.type} dependencies"
66
60
  end
67
61
  end
68
62
 
69
63
  # Reports on a dependency in a list command run.
70
64
  #
71
65
  # dependency - An application dependency
72
- #
73
- # Returns the result of the yielded method
74
- # Note - must be called from inside the `report_run` scope
75
- def report_dependency(dependency)
76
- super do |report|
77
- result = yield report
78
- info = "#{dependency.name} (#{dependency.version})"
79
- info = "#{info}: #{report["license"]}" if report["license"]
80
- shell.info " #{info}"
81
-
82
- result
83
- end
66
+ # report - A report object containing information about the dependency evaluation
67
+ def end_report_dependency(dependency, report)
68
+ info = "#{dependency.name} (#{dependency.version})"
69
+ info = "#{info}: #{report["license"]}" if report["license"]
70
+ shell.info " #{info}"
84
71
  end
85
72
  end
86
73
  end
@@ -6,66 +6,47 @@ module Licensed
6
6
  TEXT_SEPARATOR = "\n\n#{("-" * 5)}\n\n".freeze
7
7
  LICENSE_SEPARATOR = "\n#{("*" * 5)}\n".freeze
8
8
 
9
- # Reports on an application configuration in a notices command run
9
+ # Reports the start of an application evaluation in a notices command run
10
10
  #
11
11
  # app - An application configuration
12
- #
13
- # Returns the result of the yielded method
14
- # Note - must be called from inside the `report_run` scope
15
- def report_app(app)
16
- super do |report|
17
- filename = app["shared_cache"] ? "NOTICE.#{app["name"]}" : "NOTICE"
18
- path = app.cache_path.join(filename)
19
- shell.info "Writing notices for #{app["name"]} to #{path}"
20
-
21
- result = yield report
22
-
23
- File.open(path, "w") do |file|
24
- file << "THIRD PARTY NOTICES\n"
25
- file << LICENSE_SEPARATOR
26
- file << report.all_reports
27
- .map { |r| notices(r) }
28
- .compact
29
- .join(LICENSE_SEPARATOR)
30
- end
12
+ # report - A report object containing information about the app evaluation
13
+ def begin_report_app(app, report)
14
+ shell.info "Writing notices for #{app["name"]} to #{app_notices_path(app)}"
15
+ end
31
16
 
32
- result
17
+ # Writes the licensing information gathered during the application evaluation
18
+ # to a notices file
19
+ #
20
+ # app - An application configuration
21
+ # report - A report object containing information about the app evaluation
22
+ def end_report_app(app, report)
23
+ File.open(app_notices_path(app), "w") do |file|
24
+ file << "THIRD PARTY NOTICES\n"
25
+ file << LICENSE_SEPARATOR
26
+ file << report.all_reports
27
+ .map { |r| notices(r) }
28
+ .compact
29
+ .join(LICENSE_SEPARATOR)
33
30
  end
34
31
  end
35
32
 
36
-
37
- # Reports on a dependency source enumerator in a notices command run.
38
- # Shows warnings encountered during the run.
33
+ # Reports any warnings encountered during the run.
39
34
  #
40
35
  # source - A dependency source enumerator
41
- #
42
- # Returns the result of the yielded method
43
- # Note - must be called from inside the `report_run` scope
44
- def report_source(source)
45
- super do |report|
46
- result = yield report
47
-
48
- report.warnings.each do |warning|
49
- shell.warn "* #{report.name}: #{warning}"
50
- end
51
-
52
- result
36
+ # report - A report object containing information about the source evaluation
37
+ def end_report_source(source, report)
38
+ report.warnings.each do |warning|
39
+ shell.warn "* #{report.name}: #{warning}"
53
40
  end
54
41
  end
55
42
 
56
43
  # Reports on a dependency in a notices command run.
57
44
  #
58
45
  # dependency - An application dependency
59
- #
60
- # Returns the result of the yielded method
61
- # Note - must be called from inside the `report_run` scope
62
- def report_dependency(dependency)
63
- super do |report|
64
- result = yield report
65
- report.warnings.each do |warning|
66
- shell.warn "* #{report.name}: #{warning}"
67
- end
68
- result
46
+ # report - A report object containing information about the dependency evaluation
47
+ def end_report_dependency(dependency, report)
48
+ report.warnings.each do |warning|
49
+ shell.warn "* #{report.name}: #{warning}"
69
50
  end
70
51
  end
71
52
 
@@ -94,6 +75,12 @@ module Licensed
94
75
  #{texts.map(&:strip).reject(&:empty?).compact.join(TEXT_SEPARATOR)}
95
76
  NOTICE
96
77
  end
78
+
79
+ # Returns the path to an applications notices file
80
+ def app_notices_path(app)
81
+ filename = app["shared_cache"] ? "NOTICE.#{app["name"]}" : "NOTICE"
82
+ app.cache_path.join(filename)
83
+ end
97
84
  end
98
85
  end
99
86
  end
@@ -2,133 +2,66 @@
2
2
  module Licensed
3
3
  module Reporters
4
4
  class Reporter
5
- class Report < Hash
6
- attr_reader :name
7
- attr_reader :target
8
- def initialize(name:, target:)
9
- super()
10
- @name = name
11
- @target = target
12
- end
13
-
14
- def reports
15
- @reports ||= []
16
- end
17
-
18
- def errors
19
- @errors ||= []
20
- end
21
-
22
- def warnings
23
- @warnings ||= []
24
- end
25
-
26
- def all_reports
27
- result = []
28
- result << self
29
- result.push(*reports.flat_map(&:all_reports))
30
- end
31
-
32
- # Returns the data from the report as a hash
33
- def to_h
34
- # add name, errors and warnings if they have real data
35
- output = {}
36
- output["name"] = name unless name.to_s.empty?
37
- output["errors"] = errors.dup if errors.any?
38
- output["warnings"] = warnings.dup if warnings.any?
39
-
40
- # merge the hash data from the report. command-specified data always
41
- # overwrites local data
42
- output.merge(super)
43
- end
44
- end
45
-
46
5
  class ReportingError < StandardError; end;
47
6
 
48
7
  def initialize(shell = Licensed::UI::Shell.new)
49
8
  @shell = shell
50
- @run_report = nil
51
- @app_report = nil
52
- @source_report = nil
53
9
  end
54
10
 
55
- # Generate a report for a licensed command execution
56
- # Yields a report object which can be used to view or add
57
- # data generated for this run
11
+ # Report the beginning of a command evaluation
58
12
  #
59
- # Returns the result of the yielded method
60
- def report_run(command)
61
- result = nil
62
- @run_report = Report.new(name: nil, target: command)
63
- begin
64
- result = yield @run_report
65
- ensure
66
- @run_report = nil
67
- end
13
+ # command - The command being run
14
+ # report - A report object containing information about the command run
15
+ def begin_report_command(command, report)
16
+ end
68
17
 
69
- result
18
+ # Report the end of a command evaluation
19
+ #
20
+ # command - The command being run
21
+ # report - A report object containing information about the command run
22
+ def end_report_command(command, report)
70
23
  end
71
24
 
72
- # Generate a report for a licensed app configuration
73
- # Yields a report object which can be used to view or add
74
- # data generated for this app
25
+ # Report the beginning of an app evaluation
75
26
  #
76
27
  # app - An application configuration
77
- #
78
- # Returns the result of the yielded method
79
- # Note - must be called from inside the `report_run` scope
80
- def report_app(app)
81
- raise ReportingError.new("Cannot call report_app with active app context") unless @app_report.nil?
82
- raise ReportingError.new("Call report_run before report_app") if @run_report.nil?
83
- result = nil
84
- @app_report = Report.new(name: app["name"], target: app)
85
- begin
86
- result = yield @app_report
87
- ensure
88
- @run_report.reports << @app_report
89
- @app_report = nil
90
- end
28
+ # report - A report object containing information about the app evaluation
29
+ def begin_report_app(app, report)
30
+ end
91
31
 
92
- result
32
+ # Report the end of an app evaluation
33
+ #
34
+ # app - An application configuration
35
+ # report - A report object containing information about the app evaluation
36
+ def end_report_app(app, report)
93
37
  end
94
38
 
95
- # Generate a report for a licensed dependency source enumerator
96
- # Yields a report object which can be used to view or add
97
- # data generated for this dependency source
39
+ # Report the beginning of a source evaluation
98
40
  #
99
41
  # source - A dependency source enumerator
100
- #
101
- # Returns the result of the yielded method
102
- # Note - must be called from inside the `report_app` scope
103
- def report_source(source)
104
- raise ReportingError.new("Cannot call report_source with active source context") unless @source_report.nil?
105
- raise ReportingError.new("Call report_app before report_source") if @app_report.nil?
106
- result = nil
107
- @source_report = Report.new(name: [@app_report.name, source.class.type].join("."), target: source)
108
- begin
109
- result = yield @source_report
110
- ensure
111
- @app_report.reports << @source_report
112
- @source_report = nil
113
- end
42
+ # report - A report object containing information about the source evaluation
43
+ def begin_report_source(source, report)
44
+ end
114
45
 
115
- result
46
+ # Report the end of a source evaluation
47
+ #
48
+ # source - A dependency source enumerator
49
+ # report - A report object containing information about the source evaluation
50
+ def end_report_source(source, report)
116
51
  end
117
52
 
118
- # Generate a report for a licensed dependency
119
- # Yields a report object which can be used to view or add
120
- # data generated for this dependency
53
+ # Report the beginning of a dependency evaluation
121
54
  #
122
55
  # dependency - An application dependency
123
- #
124
- # Returns the result of the yielded method
125
- # Note - must be called from inside the `report_source` scope
126
- def report_dependency(dependency)
127
- raise ReportingError.new("Call report_source before report_dependency") if @source_report.nil?
56
+ # source - A report object containing information about the dependency evaluation
57
+ def begin_report_dependency(dependency, report)
58
+ end
128
59
 
129
- dependency_report = Report.new(name: [@source_report.name, dependency.name].join("."), target: dependency)
130
- @source_report.reports << dependency_report
131
- yield dependency_report
60
+ # Report the end of a dependency evaluation
61
+ #
62
+ # dependency - An application dependency
63
+ # source - A report object containing information about the dependency evaluation
64
+ def end_report_dependency(dependency, report)
132
65
  end
133
66
 
134
67
  protected