licensed 4.0.4 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4862d2463055e895e3aac366c32821ee047360646946860d0cd6eb86ef9701f
4
- data.tar.gz: b75cf3b200090387ef2f104295bb90fc8874668bd895797335f02a23c9357296
3
+ metadata.gz: 7606d0b5e5f3755ee329a1963cda970c021deab08680c619731ed6fb3ba547da
4
+ data.tar.gz: 668a2d87d8019284b6ce02bccdda851ad186f03cc7d389fbdd659473affc08cf
5
5
  SHA512:
6
- metadata.gz: 766f5196aea9b41034c0a76e11ebe7e7272ce1554661d552ad88895dd45cc43544cb737f7c36173ab612fc71f352d14ac30d2449f7414f8b7813174e294828c5
7
- data.tar.gz: 0c6a31ae81db6abe8744d4a64b07e695b86b18536ce7308f7757c0c69183684e6d39d91082c87edd5a693617f30884a6c322ec3aa0e017a87bc137bf1e0793b7
6
+ metadata.gz: '064129baadae7345b5c05e2635cc1850b8ce8321f1e2df803b5fc6d6704556a1337c7d1561024775801cf5cb4158b6c25657b06a0a9baf5ccac7a7453f35fa53'
7
+ data.tar.gz: b3c6ba7179d7b777665f29b5cace4536181a428a5995c5e7d1d168b4ba6012fd333d191eb6ce23ab7b971a9cb8231dbfb999743c72bf91a1efe78ddec78223b7
data/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 4.1.0
10
+
11
+ ### Added
12
+
13
+ - Custom license terms can be added to dependencies via new configuration options (https://github.com/github/licensed/pull/624)
14
+ - Licensed is now integrated with pnpm to enumerate dependencies (https://github.com/github/licensed/pull/626)
15
+
9
16
  ## 4.0.4
10
17
 
11
18
  ### Changed
@@ -706,4 +713,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
706
713
 
707
714
  Initial release :tada:
708
715
 
709
- [Unreleased]: https://github.com/github/licensed/compare/4.0.4...HEAD
716
+ [Unreleased]: https://github.com/github/licensed/compare/4.1.0...HEAD
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- licensed (4.0.4)
4
+ licensed (4.1.0)
5
5
  json (~> 2.6)
6
6
  licensee (~> 9.16)
7
7
  parallel (~> 1.22)
@@ -9,3 +9,4 @@
9
9
  1. [Allowed licenses](./allowed_licenses.md)
10
10
  1. [Ignoring dependencies](./ignoring_dependencies.md)
11
11
  1. [Reviewing dependencies](./reviewing_dependencies.md)
12
+ 1. [Additional license terms](./additional_terms.md)
@@ -0,0 +1,41 @@
1
+ # Additional terms
2
+
3
+ The `additional_terms` configuration option is used to specify paths to files containing extra licensing terms that do not ship with the dependency package. All files specified are expected to be plain text.
4
+
5
+ Files containing additional content can be located anywhere on disk that is accessible to licensed. File paths can be specified as a string or array and can contain glob values to simplify configuration inputs. All file paths are evaluated from the [configuration root](./configuration_root.md).
6
+
7
+ ## Examples
8
+
9
+ **Note** The examples below specify paths to additional files under the `.licenses` folder. This is a logical place to store files containing license terms, but be careful not to store files under paths managed by licensed like `.licenses/<source type>/...`. Running `licensed cache` in the future will delete any files under licensed managed paths that licensed did not create. This is why the below examples use paths like `.licenses/amendments/bundler/...` instead of not `.licenses/bundler/amendments/...`.
10
+
11
+ ### With a string
12
+
13
+ ```yaml
14
+ additional_terms:
15
+ # specify the type of dependency
16
+ bundler:
17
+ # specify the dependency name and path to an additional file
18
+ <gem-name>: .licenses/amendments/bundler/<gem-name>/terms.txt
19
+ ```
20
+
21
+ ### With a glob string
22
+
23
+ ```yaml
24
+ additional_terms:
25
+ # specify the type of dependency
26
+ bundler:
27
+ # specify the dependency name and one or more additional files with a glob pattern
28
+ <gem-name>: .licenses/amendments/bundler/<gem-name>/*.txt
29
+ ```
30
+
31
+ ### With an array of strings
32
+
33
+ ```yaml
34
+ additional_terms:
35
+ # specify the type of dependency
36
+ bundler:
37
+ # specify the dependency name and array of paths to additional files
38
+ <gem-name>:
39
+ - .licenses/amendments/bundler/<gem-name>/terms-1.txt
40
+ - .licenses/amendments/bundler/<gem-name>/terms-2.txt
41
+ ```
@@ -67,6 +67,13 @@ reviewed:
67
67
  - classlist # public domain
68
68
  - octicons
69
69
 
70
+ # Specify additional license terms that have been obtained from a dependency's owner
71
+ # which apply to the dependency's license
72
+ additional_terms:
73
+ bundler:
74
+ bcrypt-ruby:
75
+ - .licenses/amendments/bundler/bcrypt-ruby/amendment.txt
76
+
70
77
  # A single configuration file can be used to enumerate dependencies for multiple
71
78
  # projects. Each configuration is referred to as an "application" and must include
72
79
  # a source path, at a minimum
@@ -0,0 +1,18 @@
1
+ # pnpm
2
+
3
+ The npm source will detect dependencies when `pnpm-lock.yaml` is found at an apps `source_path`. It uses `pnpm licenses list` to enumerate dependencies and metadata.
4
+
5
+ **NOTE** [pnpm licenses list](https://pnpm.io/cli/licenses) is an experimental CLI command and subject to change. If changes to pnpm result in unexpected or broken behavior in licensed please open an [issue](https://github.com/github/licensed/issues/new).
6
+
7
+ ## Including development dependencies
8
+
9
+ By default, the npm source will exclude all development dependencies. To include development or test dependencies, set `production_only: false` in the licensed configuration.
10
+
11
+ ```yml
12
+ pnpm:
13
+ production_only: false
14
+ ```
15
+
16
+ ## Using licensed with pnpm workspaces
17
+
18
+ Licensed will locate all dependencies from all pnpm workspaces and cannot enumerate dependencies from individual project workspaces. This is a limitation from the pnpm CLI.
@@ -109,6 +109,12 @@ module Licensed
109
109
  self["allowed"] << license
110
110
  end
111
111
 
112
+ # Returns an array of paths to files containing additional license terms.
113
+ def additional_terms_for_dependency(dependency)
114
+ amendment_paths = Array(self.dig("additional_terms", dependency["type"], dependency["name"]))
115
+ amendment_paths.flat_map { |path| Dir.glob(self.root.join(path)) }
116
+ end
117
+
112
118
  private
113
119
 
114
120
  def any_list_pattern_matched?(list, dependency, match_version: false)
@@ -9,6 +9,7 @@ module Licensed
9
9
  attr_reader :version
10
10
  attr_reader :errors
11
11
  attr_reader :path
12
+ attr_reader :additional_terms
12
13
 
13
14
  # Create a new project dependency
14
15
  #
@@ -28,6 +29,7 @@ module Licensed
28
29
  @errors = errors
29
30
  path = path.to_s
30
31
  @path = path
32
+ @additional_terms = []
31
33
 
32
34
  # enforcing absolute paths makes life much easier when determining
33
35
  # an absolute file path in #notices
@@ -80,6 +82,13 @@ module Licensed
80
82
  files.compact
81
83
  end
82
84
 
85
+
86
+ # Override the behavior of Licensee::Projects::FSProject#project_files to include
87
+ # additional license terms
88
+ def project_files
89
+ super + additional_license_terms_files
90
+ end
91
+
83
92
  # Returns legal notices found at the dependency path
84
93
  def notice_contents
85
94
  Dir.glob(dir_path.join("*"))
@@ -102,6 +111,7 @@ module Licensed
102
111
  def license_content_sources(files)
103
112
  paths = Array(files).map do |file|
104
113
  next file[:uri] if file[:uri]
114
+ next file[:source] if file[:source]
105
115
 
106
116
  path = dir_path.join(file[:dir], file[:name])
107
117
  normalize_source_path(path)
@@ -157,5 +167,22 @@ module Licensed
157
167
  "text" => text
158
168
  }
159
169
  end
170
+
171
+ # Returns an array of Licensee::ProjectFiles::LicenseFile created from
172
+ # this dependency's additional license terms
173
+ def additional_license_terms_files
174
+ @additional_license_terms_files ||= begin
175
+ files = additional_terms.map do |path|
176
+ next unless File.file?(path)
177
+
178
+ metadata = { dir: File.dirname(path), name: File.basename(path) }
179
+ Licensee::ProjectFiles::LicenseFile.new(
180
+ load_file(metadata),
181
+ { source: "License terms loaded from #{metadata[:name]}" }
182
+ )
183
+ end
184
+ files.compact
185
+ end
186
+ end
160
187
  end
161
188
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ require "json"
3
+
4
+ module Licensed
5
+ module Sources
6
+ class PNPM < Source
7
+ # Returns true when pnpm is installed and a pnpm-lock.yaml file is found,
8
+ # otherwise false
9
+ def enabled?
10
+ return false unless Licensed::Shell.tool_available?("pnpm")
11
+ File.exist?(File.join(config.pwd, "pnpm-lock.yaml"))
12
+ end
13
+
14
+ def enumerate_dependencies
15
+ packages.map do |package|
16
+ name_with_version = "#{package["name"]}@#{package["version"]}"
17
+ Dependency.new(
18
+ name: name_with_version,
19
+ version: package["version"],
20
+ path: package["path"],
21
+ metadata: {
22
+ "type" => PNPM.type,
23
+ "name" => package["name"],
24
+ "summary" => package["description"],
25
+ "homepage" => package["homepage"]
26
+ }
27
+ )
28
+ end
29
+ end
30
+
31
+ # Returns package metadata returned from `pnpm licensed list`
32
+ def packages
33
+ JSON.parse(package_metadata_command).values.flatten
34
+ rescue JSON::ParserError => e
35
+ message = "Licensed was unable to parse the output from 'pnpm licenses list'. JSON Error: #{e.message}"
36
+ raise Licensed::Sources::Source::Error, message
37
+ end
38
+
39
+ # Returns the output from running `pnpm licenses list` to get package metadata
40
+ def package_metadata_command
41
+ args = %w(--json --long)
42
+ args << "--prod" unless include_non_production?
43
+ Licensed::Shell.execute("pnpm", "licenses", "list", *args, allow_failure: true)
44
+ end
45
+
46
+ # Returns whether to include non production dependencies based on the licensed configuration settings
47
+ def include_non_production?
48
+ config.dig("pnpm", "production_only") == false
49
+ end
50
+ end
51
+ end
52
+ end
@@ -69,7 +69,9 @@ module Licensed
69
69
  # Returns all dependencies that should be evaluated.
70
70
  # Excludes ignored dependencies.
71
71
  def dependencies
72
- cached_dependencies.reject { |d| ignored?(d) }
72
+ cached_dependencies
73
+ .reject { |d| ignored?(d) }
74
+ .each { |d| add_additional_terms_from_configuration(d) }
73
75
  end
74
76
 
75
77
  # Enumerate all source dependencies. Must be implemented by each source class.
@@ -88,6 +90,11 @@ module Licensed
88
90
  def cached_dependencies
89
91
  @dependencies ||= enumerate_dependencies.compact
90
92
  end
93
+
94
+ # Add any additional_terms for this dependency that have been added to the configuration
95
+ def add_additional_terms_from_configuration(dependency)
96
+ dependency.additional_terms.concat config.additional_terms_for_dependency("type" => self.class.type, "name" => dependency.name)
97
+ end
91
98
  end
92
99
  end
93
100
  end
@@ -6,19 +6,20 @@ module Licensed
6
6
  require "licensed/sources/bundler"
7
7
  require "licensed/sources/cabal"
8
8
  require "licensed/sources/cargo"
9
+ require "licensed/sources/cocoapods"
9
10
  require "licensed/sources/composer"
10
11
  require "licensed/sources/dep"
11
12
  require "licensed/sources/git_submodule"
12
13
  require "licensed/sources/go"
14
+ require "licensed/sources/gradle"
13
15
  require "licensed/sources/manifest"
16
+ require "licensed/sources/mix"
14
17
  require "licensed/sources/npm"
15
18
  require "licensed/sources/nuget"
16
19
  require "licensed/sources/pip"
17
20
  require "licensed/sources/pipenv"
21
+ require "licensed/sources/pnpm"
18
22
  require "licensed/sources/swift"
19
- require "licensed/sources/gradle"
20
- require "licensed/sources/mix"
21
23
  require "licensed/sources/yarn"
22
- require "licensed/sources/cocoapods"
23
24
  end
24
25
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "4.0.4".freeze
3
+ VERSION = "4.1.0".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
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: 4.0.4
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-26 00:00:00.000000000 Z
11
+ date: 2023-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee
@@ -219,6 +219,7 @@ files:
219
219
  - docs/commands/version.md
220
220
  - docs/configuration.md
221
221
  - docs/configuration/README.md
222
+ - docs/configuration/additional_terms.md
222
223
  - docs/configuration/allowed_licenses.md
223
224
  - docs/configuration/application_name.md
224
225
  - docs/configuration/application_source.md
@@ -249,6 +250,7 @@ files:
249
250
  - docs/sources/nuget.md
250
251
  - docs/sources/pip.md
251
252
  - docs/sources/pipenv.md
253
+ - docs/sources/pnpm.md
252
254
  - docs/sources/stack.md
253
255
  - docs/sources/swift.md
254
256
  - docs/sources/yarn.md
@@ -298,6 +300,7 @@ files:
298
300
  - lib/licensed/sources/nuget.rb
299
301
  - lib/licensed/sources/pip.rb
300
302
  - lib/licensed/sources/pipenv.rb
303
+ - lib/licensed/sources/pnpm.rb
301
304
  - lib/licensed/sources/source.rb
302
305
  - lib/licensed/sources/swift.rb
303
306
  - lib/licensed/sources/yarn.rb