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