licensed 2.10.0 → 2.11.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.gitignore +2 -0
- data/CHANGELOG.md +12 -2
- data/README.md +7 -5
- data/docs/commands.md +6 -0
- data/lib/licensed/cli.rb +7 -0
- data/lib/licensed/commands.rb +1 -0
- data/lib/licensed/commands/notices.rb +35 -0
- data/lib/licensed/dependency.rb +1 -1
- data/lib/licensed/reporters.rb +1 -0
- data/lib/licensed/reporters/cache_reporter.rb +10 -10
- data/lib/licensed/reporters/list_reporter.rb +5 -5
- data/lib/licensed/reporters/notices_reporter.rb +68 -0
- data/lib/licensed/reporters/status_reporter.rb +7 -7
- data/lib/licensed/sources/cabal.rb +2 -2
- data/lib/licensed/sources/go.rb +1 -1
- data/lib/licensed/sources/nuget.rb +14 -8
- data/lib/licensed/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9cb9d80097e4329d3aa276faf53b72cac7fed2c2f4c09edc500bc627fb8d942b
|
4
|
+
data.tar.gz: f2ba113cfac5f807980f44a7d60a40dd6c946c85a351bf8161854b72d715d625
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcdc95e2d512dbf8f9e84f76409f4d94b93ae3bdf95d17fa4b668f04e996cdcda340c5e7f09dd499c509b122e92cfc90d58838f33df24d690fd4ae1b759550b0
|
7
|
+
data.tar.gz: bba8ba26db299965d6fc7e2d783060d827e5f45cd7f1a287414f63c39298b39dfb6739beebe46d152e6619830705a8abf822a33ce01d94335fc195596a65e6cb
|
data/.github/workflows/test.yml
CHANGED
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## 2.11.0
|
10
|
+
2020-06-02
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- `notices` command to create a `NOTICE` file for each configured app (https://github.com/github/licensed/pull/277)
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
- NuGet source no longer crashes on a non-existent dependency path (https://github.com/github/licensed/pull/280)
|
17
|
+
- Go source no longer crashes on a non-existent dependency package path (https://github.com/github/licensed/pull/274)
|
18
|
+
|
9
19
|
## 2.10.0
|
10
20
|
2020-05-15
|
11
21
|
|
@@ -13,7 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
13
23
|
- NPM source ignores missing peer dependencies (https://github.com/github/licensed/pull/267)
|
14
24
|
|
15
25
|
### Added
|
16
|
-
-
|
26
|
+
- NuGet source (:tada: @zarenner https://github.com/github/licensed/pull/261)
|
17
27
|
- Multiple apps can share a single cache location (https://github.com/github/licensed/pull/263)
|
18
28
|
|
19
29
|
## 2.9.2
|
@@ -302,4 +312,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
302
312
|
|
303
313
|
Initial release :tada:
|
304
314
|
|
305
|
-
[Unreleased]: https://github.com/github/licensed/compare/2.
|
315
|
+
[Unreleased]: https://github.com/github/licensed/compare/2.11.0...HEAD
|
data/README.md
CHANGED
@@ -24,13 +24,13 @@ See the [migration documentation](./docs/migrating_to_newer_versions.md) for mor
|
|
24
24
|
### Dependencies
|
25
25
|
|
26
26
|
Licensed uses the `libgit2` bindings for Ruby provided by `rugged`. `rugged` requires `cmake` and `pkg-config` which you may need to install before you can install Licensed.
|
27
|
-
|
27
|
+
|
28
28
|
> Ubuntu
|
29
|
-
|
29
|
+
|
30
30
|
sudo apt-get install cmake pkg-config
|
31
|
-
|
31
|
+
|
32
32
|
> OS X
|
33
|
-
|
33
|
+
|
34
34
|
brew install cmake pkg-config
|
35
35
|
|
36
36
|
### With a Gemfile
|
@@ -64,8 +64,10 @@ For system wide usage, install licensed to a location on `$PATH`, e.g. `/usr/loc
|
|
64
64
|
|
65
65
|
- `licensed list`: Output enumerated dependencies only.
|
66
66
|
- `licensed cache`: Cache licenses and metadata.
|
67
|
-
- `licensed status`: Check status of dependencies' cached licenses.
|
67
|
+
- `licensed status`: Check status of dependencies' cached licenses.
|
68
|
+
- `licensed notices`: Write a `NOTICE` file for each application configuration.
|
68
69
|
- `licensed version`: Show current installed version of Licensed. Aliases: `-v|--version`
|
70
|
+
- `licensed env`: Output environment information from the licensed configuration.
|
69
71
|
|
70
72
|
See the [commands documentation](./docs/commands.md) for additional documentation, or run `licensed -h` to see all of the current available commands.
|
71
73
|
|
data/docs/commands.md
CHANGED
@@ -31,6 +31,12 @@ A dependency will fail the status checks if:
|
|
31
31
|
5. The cached record is flagged for re-review.
|
32
32
|
- This occurs when the record's license text has changed since the record was reviewed.
|
33
33
|
|
34
|
+
## `notices`
|
35
|
+
|
36
|
+
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`.
|
37
|
+
|
38
|
+
The `NOTICE` file contents are retrieved from cached records, with the assumption that cached records have already been reviewed in a compliance workflow.
|
39
|
+
|
34
40
|
## `env`
|
35
41
|
|
36
42
|
Prints the runtime environment used by licensed after loading a configuration file. By default the output is in YAML format, but can be output in JSON using the `--json` flag.
|
data/lib/licensed/cli.rb
CHANGED
@@ -28,6 +28,13 @@ module Licensed
|
|
28
28
|
run Licensed::Commands::List.new(config: config)
|
29
29
|
end
|
30
30
|
|
31
|
+
desc "notices", "Generate a NOTICE file from cached records"
|
32
|
+
method_option :config, aliases: "-c", type: :string,
|
33
|
+
desc: "Path to licensed configuration file"
|
34
|
+
def notices
|
35
|
+
run Licensed::Commands::Notices.new(config: config)
|
36
|
+
end
|
37
|
+
|
31
38
|
map "-v" => :version
|
32
39
|
map "--version" => :version
|
33
40
|
desc "version", "Show Installed Version of Licensed, [-v, --version]"
|
data/lib/licensed/commands.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Licensed
|
3
|
+
module Commands
|
4
|
+
class Notices < Command
|
5
|
+
# Create a reporter to use during a command run
|
6
|
+
#
|
7
|
+
# options - The options the command was run with
|
8
|
+
#
|
9
|
+
# Raises a Licensed::Reporters::CacheReporter
|
10
|
+
def create_reporter(options)
|
11
|
+
Licensed::Reporters::NoticesReporter.new
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
# Load stored dependency record data to add to the notices report.
|
17
|
+
#
|
18
|
+
# app - The application configuration for the dependency
|
19
|
+
# source - The dependency source enumerator for the dependency
|
20
|
+
# dependency - An application dependency
|
21
|
+
# report - A report hash for the command to provide extra data for the report output.
|
22
|
+
#
|
23
|
+
# Returns true.
|
24
|
+
def evaluate_dependency(app, source, dependency, report)
|
25
|
+
filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}")
|
26
|
+
report["cached_record"] = Licensed::DependencyRecord.read(filename)
|
27
|
+
if !report["cached_record"]
|
28
|
+
report["warning"] = "expected cached record not found at #{filename}"
|
29
|
+
end
|
30
|
+
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/licensed/dependency.rb
CHANGED
@@ -74,7 +74,7 @@ module Licensed
|
|
74
74
|
def license_contents
|
75
75
|
files = matched_files.reject { |f| f == package_file }
|
76
76
|
.group_by(&:content)
|
77
|
-
.map { |content,
|
77
|
+
.map { |content, sources| { "sources" => license_content_sources(sources), "text" => content } }
|
78
78
|
|
79
79
|
files << generated_license_contents if files.empty?
|
80
80
|
files.compact
|
data/lib/licensed/reporters.rb
CHANGED
@@ -27,32 +27,32 @@ module Licensed
|
|
27
27
|
shell.info " #{source.class.type}"
|
28
28
|
result = yield report
|
29
29
|
|
30
|
-
warning_reports = report.all_reports.select { |
|
30
|
+
warning_reports = report.all_reports.select { |r| r.warnings.any? }.to_a
|
31
31
|
if warning_reports.any?
|
32
32
|
shell.newline
|
33
33
|
shell.warn " * Warnings:"
|
34
|
-
warning_reports.each do |
|
35
|
-
display_metadata =
|
34
|
+
warning_reports.each do |r|
|
35
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
36
36
|
|
37
|
-
shell.warn " * #{
|
37
|
+
shell.warn " * #{r.name}"
|
38
38
|
shell.warn " #{display_metadata}" unless display_metadata.empty?
|
39
|
-
|
39
|
+
r.warnings.each do |warning|
|
40
40
|
shell.warn " - #{warning}"
|
41
41
|
end
|
42
42
|
shell.newline
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
errored_reports = report.all_reports.select { |
|
46
|
+
errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
|
47
47
|
if errored_reports.any?
|
48
48
|
shell.newline
|
49
49
|
shell.error " * Errors:"
|
50
|
-
errored_reports.each do |
|
51
|
-
display_metadata =
|
50
|
+
errored_reports.each do |r|
|
51
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
52
52
|
|
53
|
-
shell.error " * #{
|
53
|
+
shell.error " * #{r.name}"
|
54
54
|
shell.error " #{display_metadata}" unless display_metadata.empty?
|
55
|
-
|
55
|
+
r.errors.each do |error|
|
56
56
|
shell.error " - #{error}"
|
57
57
|
end
|
58
58
|
shell.newline
|
@@ -28,16 +28,16 @@ module Licensed
|
|
28
28
|
shell.info " #{source.class.type}"
|
29
29
|
result = yield report
|
30
30
|
|
31
|
-
errored_reports = report.all_reports.select { |
|
31
|
+
errored_reports = report.all_reports.select { |r| r.errors.any? }.to_a
|
32
32
|
if errored_reports.any?
|
33
33
|
shell.newline
|
34
34
|
shell.error " * Errors:"
|
35
|
-
errored_reports.each do |
|
36
|
-
display_metadata =
|
35
|
+
errored_reports.each do |r|
|
36
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
37
37
|
|
38
|
-
shell.error " * #{
|
38
|
+
shell.error " * #{r.name}"
|
39
39
|
shell.error " #{display_metadata}" unless display_metadata.empty?
|
40
|
-
|
40
|
+
r.errors.each do |error|
|
41
41
|
shell.error " - #{error}"
|
42
42
|
end
|
43
43
|
shell.newline
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Licensed
|
4
|
+
module Reporters
|
5
|
+
class NoticesReporter < Reporter
|
6
|
+
TEXT_SEPARATOR = "\n\n#{("-" * 5)}\n\n".freeze
|
7
|
+
LICENSE_SEPARATOR = "\n#{("*" * 5)}\n".freeze
|
8
|
+
|
9
|
+
# Reports on an application configuration in a notices command run
|
10
|
+
#
|
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
|
31
|
+
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Reports on a dependency in a notices command run.
|
37
|
+
#
|
38
|
+
# dependency - An application dependency
|
39
|
+
#
|
40
|
+
# Returns the result of the yielded method
|
41
|
+
# Note - must be called from inside the `report_run` scope
|
42
|
+
def report_dependency(dependency)
|
43
|
+
super do |report|
|
44
|
+
result = yield report
|
45
|
+
shell.warn "* #{report["warning"]}" if report["warning"]
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns notices information for a dependency report
|
51
|
+
def notices(report)
|
52
|
+
return unless report.target.is_a?(Licensed::Dependency)
|
53
|
+
|
54
|
+
cached_record = report["cached_record"]
|
55
|
+
return unless cached_record
|
56
|
+
|
57
|
+
texts = cached_record.licenses.map(&:text)
|
58
|
+
texts.concat(cached_record.notices)
|
59
|
+
|
60
|
+
<<~NOTICE
|
61
|
+
#{cached_record["name"]}@#{cached_record["version"]}
|
62
|
+
|
63
|
+
#{texts.map(&:strip).reject(&:empty?).compact.join(TEXT_SEPARATOR)}
|
64
|
+
NOTICE
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -15,20 +15,20 @@ module Licensed
|
|
15
15
|
result = yield report
|
16
16
|
|
17
17
|
all_reports = report.all_reports
|
18
|
-
errored_reports = all_reports.select { |
|
18
|
+
errored_reports = all_reports.select { |r| r.errors.any? }.to_a
|
19
19
|
|
20
|
-
dependency_count = all_reports.select { |
|
21
|
-
error_count = errored_reports.sum { |
|
20
|
+
dependency_count = all_reports.select { |r| r.target.is_a?(Licensed::Dependency) }.size
|
21
|
+
error_count = errored_reports.sum { |r| r.errors.size }
|
22
22
|
|
23
23
|
if error_count > 0
|
24
24
|
shell.newline
|
25
25
|
shell.error "Errors:"
|
26
|
-
errored_reports.each do |
|
27
|
-
display_metadata =
|
26
|
+
errored_reports.each do |r|
|
27
|
+
display_metadata = r.map { |k, v| "#{k}: #{v}" }.join(", ")
|
28
28
|
|
29
|
-
shell.error "* #{
|
29
|
+
shell.error "* #{r.name}"
|
30
30
|
shell.error " #{display_metadata}" unless display_metadata.empty?
|
31
|
-
|
31
|
+
r.errors.each do |error|
|
32
32
|
shell.error " - #{error}"
|
33
33
|
end
|
34
34
|
shell.newline
|
@@ -111,11 +111,11 @@ module Licensed
|
|
111
111
|
info = package_info_command(id).strip
|
112
112
|
return missing_package(id) if info.empty?
|
113
113
|
|
114
|
-
info.lines.each_with_object({}) do |line,
|
114
|
+
info.lines.each_with_object({}) do |line, hsh|
|
115
115
|
key, value = line.split(":", 2).map(&:strip)
|
116
116
|
next unless key && value
|
117
117
|
|
118
|
-
|
118
|
+
hsh[key] = value
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
data/lib/licensed/sources/go.rb
CHANGED
@@ -120,7 +120,7 @@ module Licensed
|
|
120
120
|
return go_mod["Version"] if go_mod
|
121
121
|
|
122
122
|
package_directory = package["Dir"]
|
123
|
-
return unless package_directory
|
123
|
+
return unless package_directory && File.exist?(package_directory)
|
124
124
|
|
125
125
|
# find most recent git SHA for a package, or nil if SHA is
|
126
126
|
# not available
|
@@ -17,10 +17,13 @@ module Licensed
|
|
17
17
|
PROJECT_URL_REGEX = /<projectUrl>\s*(.*)\s*<\/projectUrl>/ix.freeze
|
18
18
|
PROJECT_DESC_REGEX = /<description>\s*(.*)\s*<\/description>/ix.freeze
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
# Returns the metadata that represents this dependency. This metadata
|
21
|
+
# is written to YAML in the dependencys cached text file
|
22
|
+
def license_metadata
|
23
|
+
super.tap do |record_metadata|
|
24
|
+
record_metadata["homepage"] = project_url if project_url
|
25
|
+
record_metadata["summary"] = description if description
|
26
|
+
end
|
24
27
|
end
|
25
28
|
|
26
29
|
def nuspec_path
|
@@ -29,14 +32,17 @@ module Licensed
|
|
29
32
|
end
|
30
33
|
|
31
34
|
def nuspec_contents
|
32
|
-
return
|
33
|
-
@nuspec_contents
|
35
|
+
return @nuspec_contents if defined?(@nuspec_contents)
|
36
|
+
@nuspec_contents = begin
|
37
|
+
return unless nuspec_path && File.exist?(nuspec_path)
|
38
|
+
File.read(nuspec_path)
|
39
|
+
end
|
34
40
|
end
|
35
41
|
|
36
42
|
def project_url
|
37
43
|
return @project_url if defined?(@project_url)
|
38
|
-
return unless nuspec_contents
|
39
44
|
@project_url = begin
|
45
|
+
return unless nuspec_contents
|
40
46
|
match = nuspec_contents.match PROJECT_URL_REGEX
|
41
47
|
match[1] if match && match[1]
|
42
48
|
end
|
@@ -44,8 +50,8 @@ module Licensed
|
|
44
50
|
|
45
51
|
def description
|
46
52
|
return @description if defined?(@description)
|
47
|
-
return unless nuspec_contents
|
48
53
|
@description = begin
|
54
|
+
return unless nuspec_contents
|
49
55
|
match = nuspec_contents.match PROJECT_DESC_REGEX
|
50
56
|
match[1] if match && match[1]
|
51
57
|
end
|
data/lib/licensed/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: licensed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: licensee
|
@@ -284,6 +284,7 @@ files:
|
|
284
284
|
- lib/licensed/commands/command.rb
|
285
285
|
- lib/licensed/commands/environment.rb
|
286
286
|
- lib/licensed/commands/list.rb
|
287
|
+
- lib/licensed/commands/notices.rb
|
287
288
|
- lib/licensed/commands/status.rb
|
288
289
|
- lib/licensed/configuration.rb
|
289
290
|
- lib/licensed/dependency.rb
|
@@ -295,6 +296,7 @@ files:
|
|
295
296
|
- lib/licensed/reporters/cache_reporter.rb
|
296
297
|
- lib/licensed/reporters/json_reporter.rb
|
297
298
|
- lib/licensed/reporters/list_reporter.rb
|
299
|
+
- lib/licensed/reporters/notices_reporter.rb
|
298
300
|
- lib/licensed/reporters/reporter.rb
|
299
301
|
- lib/licensed/reporters/status_reporter.rb
|
300
302
|
- lib/licensed/reporters/yaml_reporter.rb
|