licensed 3.0.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
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