licensed 3.2.1 → 3.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -1
  3. data/docs/sources/cargo.md +19 -0
  4. data/lib/licensed/commands/cache.rb +4 -2
  5. data/lib/licensed/commands/command.rb +5 -2
  6. data/lib/licensed/sources/bundler/missing_specification.rb +10 -7
  7. data/lib/licensed/sources/bundler.rb +6 -2
  8. data/lib/licensed/sources/cargo.rb +70 -0
  9. data/lib/licensed/sources/manifest.rb +17 -22
  10. data/lib/licensed/sources/npm.rb +17 -3
  11. data/lib/licensed/sources.rb +1 -0
  12. data/lib/licensed/version.rb +1 -1
  13. data/licensed.gemspec +1 -1
  14. metadata +4 -32
  15. data/.github/dependabot.yml +0 -19
  16. data/.github/workflows/release.yml +0 -213
  17. data/.github/workflows/test.yml +0 -528
  18. data/.gitignore +0 -57
  19. data/.licensed.yml +0 -7
  20. data/.rubocop.yml +0 -8
  21. data/.ruby-version +0 -1
  22. data/docker/Dockerfile.build-linux +0 -15
  23. data/script/bootstrap +0 -6
  24. data/script/cibuild +0 -7
  25. data/script/console +0 -15
  26. data/script/package +0 -20
  27. data/script/packages/build +0 -95
  28. data/script/packages/linux +0 -57
  29. data/script/packages/mac +0 -41
  30. data/script/setup +0 -5
  31. data/script/source-setup/bower +0 -17
  32. data/script/source-setup/bundler +0 -20
  33. data/script/source-setup/cabal +0 -19
  34. data/script/source-setup/composer +0 -38
  35. data/script/source-setup/git_submodule +0 -39
  36. data/script/source-setup/go +0 -31
  37. data/script/source-setup/mix +0 -19
  38. data/script/source-setup/npm +0 -34
  39. data/script/source-setup/nuget +0 -17
  40. data/script/source-setup/pip +0 -29
  41. data/script/source-setup/pipenv +0 -21
  42. data/script/source-setup/swift +0 -22
  43. data/script/source-setup/yarn +0 -17
  44. data/script/test +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 157405d5c26fe8026b4c8d521a5753be821bb2727d9713f7732e2601699660e7
4
- data.tar.gz: 1f02c3bf319500352632331f72dfc40cbfaf6a0d00350570223d3b37b2496ca7
3
+ metadata.gz: 204627468559ebbf7283c41b74374a244f5aed5c885c4b9dcfc6fe59a8443c4a
4
+ data.tar.gz: f6db3198bf7bd592e8e1512803e408091dfe6230984c9aa166bbdf7d16edb1df
5
5
  SHA512:
6
- metadata.gz: fa9b3832cfda8a30f99c7718a6e4c9433145e37cb51070c5e1a59009ff5b29269353ddeb68480196bd1f1680bd8c01c4ddd3538bea2f7401fcddcdb542f62ada
7
- data.tar.gz: ee5718fb34a1d23738849101b121db785fdc83d587d0f7750c2cc1e613f0c8a6ece707e427bb18473f04ef67569499db28e75ce80f14f0dde2cd09e18ed14053
6
+ metadata.gz: 5669804505cd5277a292eb51b6d46beda9f9a16e9ede968855ab9df95cdd45bd43564c15fdc45e80a9fe109c190584b93078f45588de78c689f0a93c86278bec
7
+ data.tar.gz: 7c57aa1d0a8bbe39860464a5efcec2d72bf06bd61b6b018c3b856547e7e0a6900e3dba4a440a41fed211b71b368a300d453a811f6fd11b65d82aa612bb7b203a
data/CHANGELOG.md CHANGED
@@ -6,6 +6,47 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 3.3.1
10
+
11
+ 2021-10-07
12
+
13
+ ### Fixed
14
+
15
+ - Fix evaluation of peer dependencies with npm 7 (:tada: @manuelpuyol https://github.com/github/licensed/pull/411)
16
+
17
+ ### Changed
18
+
19
+ - Manifest source evaluation performance improvements (https://github.com/github/licensed/pull/407)
20
+
21
+ ## 3.3.0
22
+
23
+ 2021-09-18
24
+
25
+ ### Added
26
+
27
+ - New cargo source enumerates rust dependencies (https://github.com/github/licensed/pull/404)
28
+
29
+ ### Changed
30
+
31
+ - Removed non-functional files from gem builds (https://github.com/github/licensed/pull/405)
32
+
33
+ ## 3.2.3
34
+
35
+ 2021-09-14
36
+
37
+ ### Fixed
38
+
39
+ - Bundler source will no longer infinitely recurse when enumerating specifications (https://github.com/github/licensed/pull/402)
40
+ - Using the `--sources` command line option will no longer delete skipped sources' cached files (https://github.com/github/licensed/pull/401)
41
+
42
+ ## 3.2.2
43
+
44
+ 2021-09-09
45
+
46
+ ### Fixed
47
+
48
+ - Bundler source works properly again when used outside of `bundle exec` (https://github.com/github/licensed/pull/397)
49
+
9
50
  ## 3.2.1
10
51
 
11
52
  2021-09-06
@@ -480,4 +521,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
480
521
 
481
522
  Initial release :tada:
482
523
 
483
- [Unreleased]: https://github.com/github/licensed/compare/3.2.1...HEAD
524
+ [Unreleased]: https://github.com/github/licensed/compare/3.3.1...HEAD
@@ -0,0 +1,19 @@
1
+ # Cargo
2
+
3
+ The cargo source will detect dependencies when `Cargo.toml` is found at an apps `source_path`. The source uses the `cargo metadata` CLI and reports on all dependencies that are listed in the output in `resolve.nodes`, excluding packages that are listed in `workspace_members`.
4
+
5
+ ## Metadata CLI options
6
+
7
+ Licensed by default runs `cargo metadata --format-version=1`. You can specify additional CLI options by specifying them in your licensed configuration file under `cargo.metadata_options`. The configuration can be set as a string, or as an array of strings for multiple options.
8
+
9
+ ```yml
10
+ cargo:
11
+ metadata_options: '--all-features'
12
+ ```
13
+
14
+ ```yml
15
+ cargo:
16
+ metadata_options:
17
+ - '--all-features'
18
+ - '--filter-platform x86_64-pc-windows-msvc'
19
+ ```
@@ -39,11 +39,13 @@ module Licensed
39
39
  #
40
40
  # Returns whether the command succeeded for the dependency source enumerator
41
41
  def run_source(app, source, report)
42
+ result = super
43
+
42
44
  # add the full cache path to the list of cache paths
43
45
  # that should be cleaned up after the command run
44
- cache_paths << app.cache_path.join(source.class.type)
46
+ cache_paths << app.cache_path.join(source.class.type) unless result == :skipped
45
47
 
46
- super
48
+ result
47
49
  end
48
50
 
49
51
  # Cache dependency record data.
@@ -121,13 +121,16 @@ module Licensed
121
121
  # source - A dependency source enumerator
122
122
  # report - A report object for this source
123
123
  #
124
- # Returns whether the command succeeded for the dependency source enumerator
124
+ # Returns whether the command succeeded, failed, or was skipped for the dependency source enumerator
125
125
  def run_source(app, source, report)
126
126
  reporter.begin_report_source(source, report)
127
127
 
128
128
  if !sources_overrides.empty? && !sources_overrides.include?(source.class.type)
129
129
  report.warnings << "skipped source"
130
- return true
130
+
131
+ # return a symbol to speficy the source was skipped.
132
+ # This is truthy and will result in the source being considered successful
133
+ return :skipped
131
134
  end
132
135
 
133
136
  dependencies = source.dependencies.sort_by { |dependency| dependency.name }
@@ -38,17 +38,20 @@ module Licensed
38
38
  "could not find #{name} (#{version}) in any sources"
39
39
  end
40
40
  end
41
+
42
+ module LazySpecification
43
+ def __materialize__
44
+ spec = super
45
+ return spec if spec
46
+
47
+ Licensed::Bundler::MissingSpecification.new(name: name, version: version, platform: platform, source: source)
48
+ end
49
+ end
41
50
  end
42
51
  end
43
52
 
44
53
  module Bundler
45
54
  class LazySpecification
46
- alias_method :orig_materialize, :__materialize__
47
- def __materialize__
48
- spec = orig_materialize
49
- return spec if spec
50
-
51
- Licensed::Bundler::MissingSpecification.new(name: name, version: version, platform: platform, source: source)
52
- end
55
+ prepend ::Licensed::Bundler::LazySpecification
53
56
  end
54
57
  end
@@ -109,9 +109,11 @@ module Licensed
109
109
 
110
110
  # reset bundler to load from the current app's source path
111
111
  ::Bundler.reset!
112
- ::Bundler.load
113
112
  end
114
113
 
114
+ # ensure the bundler environment is loaded before enumeration
115
+ ::Bundler.load
116
+
115
117
  yield
116
118
  end
117
119
  ensure
@@ -119,8 +121,10 @@ module Licensed
119
121
  # restore bundler configuration
120
122
  ENV.replace(backup)
121
123
  ::Bundler.reset!
122
- ::Bundler.load
123
124
  end
125
+
126
+ # reload the bundler environment after enumeration
127
+ ::Bundler.load
124
128
  end
125
129
 
126
130
  # Returns whether the current licensed execution is running ruby-packer
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Licensed
6
+ module Sources
7
+ class Cargo < Source
8
+ # Source is enabled when the cargo tool and Cargo.toml manifest file are available
9
+ def enabled?
10
+ return false unless Licensed::Shell.tool_available?("cargo")
11
+ config.pwd.join("Cargo.toml").exist?
12
+ end
13
+
14
+ def enumerate_dependencies
15
+ packages.map do |package|
16
+ Dependency.new(
17
+ name: "#{package["name"]}-#{package["version"]}",
18
+ version: package["version"],
19
+ path: File.dirname(package["manifest_path"]),
20
+ metadata: {
21
+ "name" => package["name"],
22
+ "type" => Cargo.type,
23
+ "summary" => package["description"],
24
+ "homepage" => package["homepage"]
25
+ }
26
+ )
27
+ end
28
+ end
29
+
30
+ # Returns the package data for all dependencies used to build the current package
31
+ def packages
32
+ cargo_metadata_resolved_node_ids.map { |id| cargo_metadata_packages[id] }
33
+ end
34
+
35
+ # Returns the ids of all resolved nodes used to build the current package
36
+ def cargo_metadata_resolved_node_ids
37
+ cargo_metadata.dig("resolve", "nodes")
38
+ .map { |node| node["id"] }
39
+ .reject { |id| cargo_metadata_workspace_members.include?(id) }
40
+
41
+ end
42
+
43
+ # Returns a hash of id => package pairs sourced from the "packages" cargo metadata property
44
+ def cargo_metadata_packages
45
+ @cargo_metadata_packages ||= cargo_metadata["packages"].each_with_object({}) do |package, hsh|
46
+ hsh[package["id"]] = package
47
+ end
48
+ end
49
+
50
+ # Returns a set of the ids of packages in the current workspace
51
+ def cargo_metadata_workspace_members
52
+ @cargo_metadata_workspace_members ||= Set.new(Array(cargo_metadata["workspace_members"]))
53
+ end
54
+
55
+ # Returns parsed JSON metadata returned from the cargo CLI
56
+ def cargo_metadata
57
+ @cargo_metadata ||= JSON.parse(cargo_metadata_command)
58
+ rescue JSON::ParserError => e
59
+ message = "Licensed was unable to parse the output from 'cargo metadata'. JSON Error: #{e.message}"
60
+ raise Licensed::Sources::Source::Error, message
61
+ end
62
+
63
+ # Runs a command to get cargo metadata for the current package
64
+ def cargo_metadata_command
65
+ options = Array(config.dig("cargo", "metadata_options")).flat_map(&:split)
66
+ Licensed::Shell.execute("cargo", "metadata", "--format-version=1", *options)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -61,7 +61,7 @@ module Licensed
61
61
  manifest.each_with_object({}) do |(src, package_name), hsh|
62
62
  next if src.nil? || src.empty?
63
63
  hsh[package_name] ||= []
64
- hsh[package_name] << File.join(config.root, src)
64
+ hsh[package_name] << File.absolute_path(src, config.root)
65
65
  end
66
66
  end
67
67
 
@@ -130,19 +130,17 @@ module Licensed
130
130
  @configured_dependencies ||= begin
131
131
  dependencies = config.dig("manifest", "dependencies")&.dup || {}
132
132
 
133
- dependencies.each do |name, patterns|
133
+ dependencies.each_with_object({}) do |(name, patterns), hsh|
134
134
  # map glob pattern(s) listed for the dependency to a listing
135
135
  # of files that match the patterns and are not excluded
136
- dependencies[name] = files_from_pattern_list(patterns) & included_files
136
+ hsh[name] = files_from_pattern_list(patterns) & included_files
137
137
  end
138
-
139
- dependencies
140
138
  end
141
139
  end
142
140
 
143
141
  # Returns the set of project files that are included in dependency evaluation
144
142
  def included_files
145
- @sources ||= all_files - files_from_pattern_list(config.dig("manifest", "exclude"))
143
+ @included_files ||= tracked_files - files_from_pattern_list(config.dig("manifest", "exclude"))
146
144
  end
147
145
 
148
146
  # Finds and returns all files in the project that match
@@ -151,26 +149,23 @@ module Licensed
151
149
  return Set.new if patterns.nil? || patterns.empty?
152
150
 
153
151
  # evaluate all patterns from the project root
154
- Dir.chdir config.root do
155
- Array(patterns).reduce(Set.new) do |files, pattern|
156
- if pattern.start_with?("!")
157
- # if the pattern is an exclusion, remove all matching files
158
- # from the result
159
- files - Dir.glob(pattern[1..-1], File::FNM_DOTMATCH)
160
- else
161
- # if the pattern is an inclusion, add all matching files
162
- # to the result
163
- files + Dir.glob(pattern, File::FNM_DOTMATCH)
164
- end
152
+ Array(patterns).each_with_object(Set.new) do |pattern, files|
153
+ if pattern.start_with?("!")
154
+ # if the pattern is an exclusion, remove all matching files
155
+ # from the result
156
+ files.subtract(Dir.glob(pattern[1..-1], File::FNM_DOTMATCH, base: config.root))
157
+ else
158
+ # if the pattern is an inclusion, add all matching files
159
+ # to the result
160
+ files.merge(Dir.glob(pattern, File::FNM_DOTMATCH, base: config.root))
165
161
  end
166
162
  end
167
163
  end
168
164
 
169
- # Returns all tracked files in the project
170
- def all_files
171
- # remove files if they are tracked but don't exist on the file system
172
- @all_files ||= Set.new(Licensed::Git.files || [])
173
- .delete_if { |f| !File.exist?(File.join(Licensed::Git.repository_root, f)) }
165
+ # Returns all tracked files in the project as the intersection of what git tracks and the files in the project
166
+ def tracked_files
167
+ @tracked_files ||= Set.new(Array(Licensed::Git.files)) &
168
+ Set.new(Dir.glob("**/*", File::FNM_DOTMATCH, base: config.root))
174
169
  end
175
170
 
176
171
  class Dependency < Licensed::Dependency
@@ -66,15 +66,17 @@ module Licensed
66
66
 
67
67
  # Recursively parse dependency JSON data. Returns a hash mapping the
68
68
  # package name to it's metadata
69
- def recursive_dependencies(dependencies, result = {})
69
+ def recursive_dependencies(dependencies, result = {}, parent = nil)
70
70
  dependencies.each do |name, dependency|
71
- next if dependency["peerMissing"]
71
+ next if missing_peer?(parent, dependency, name)
72
72
  next if yarn_lock_present && dependency["missing"]
73
73
  next if dependency["extraneous"] && dependency["missing"]
74
74
 
75
75
  dependency["name"] = name
76
+ dependency["version"] ||= extract_version(parent, name) if dependency["missing"]
77
+
76
78
  (result[name] ||= []) << dependency
77
- recursive_dependencies(dependency["dependencies"] || {}, result)
79
+ recursive_dependencies(dependency["dependencies"] || {}, result, dependency)
78
80
  end
79
81
  result
80
82
  end
@@ -135,6 +137,18 @@ module Licensed
135
137
  def include_non_production?
136
138
  config.dig("npm", "production_only") == false
137
139
  end
140
+
141
+ def missing_peer?(parent, dependency, name)
142
+ dependency["peerMissing"] || (dependency["missing"] && peer_dependency(parent, name))
143
+ end
144
+
145
+ def peer_dependency(parent, name)
146
+ parent&.dig("peerDependencies", name)
147
+ end
148
+
149
+ def extract_version(parent, name)
150
+ parent&.dig("_dependencies", name) || peer_dependency(parent, name)
151
+ end
138
152
  end
139
153
  end
140
154
  end
@@ -5,6 +5,7 @@ module Licensed
5
5
  require "licensed/sources/bower"
6
6
  require "licensed/sources/bundler"
7
7
  require "licensed/sources/cabal"
8
+ require "licensed/sources/cargo"
8
9
  require "licensed/sources/composer"
9
10
  require "licensed/sources/dep"
10
11
  require "licensed/sources/git_submodule"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "3.2.1".freeze
3
+ VERSION = "3.3.1".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
data/licensed.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.homepage = "https://github.com/github/licensed"
17
17
  spec.license = "MIT"
18
18
 
19
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test/|script/|docker/|\..+)}) }
20
20
  spec.bindir = "exe"
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
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: 3.2.1
4
+ version: 3.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-06 00:00:00.000000000 Z
11
+ date: 2021-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee
@@ -238,13 +238,6 @@ executables:
238
238
  extensions: []
239
239
  extra_rdoc_files: []
240
240
  files:
241
- - ".github/dependabot.yml"
242
- - ".github/workflows/release.yml"
243
- - ".github/workflows/test.yml"
244
- - ".gitignore"
245
- - ".licensed.yml"
246
- - ".rubocop.yml"
247
- - ".ruby-version"
248
241
  - CHANGELOG.md
249
242
  - CODE_OF_CONDUCT.md
250
243
  - CONTRIBUTING.md
@@ -252,7 +245,6 @@ files:
252
245
  - LICENSE
253
246
  - README.md
254
247
  - Rakefile
255
- - docker/Dockerfile.build-linux
256
248
  - docs/adding_a_new_source.md
257
249
  - docs/commands/README.md
258
250
  - docs/commands/cache.md
@@ -280,6 +272,7 @@ files:
280
272
  - docs/sources/bower.md
281
273
  - docs/sources/bundler.md
282
274
  - docs/sources/cabal.md
275
+ - docs/sources/cargo.md
283
276
  - docs/sources/composer.md
284
277
  - docs/sources/dep.md
285
278
  - docs/sources/git_submodule.md
@@ -326,6 +319,7 @@ files:
326
319
  - lib/licensed/sources/bundler/definition.rb
327
320
  - lib/licensed/sources/bundler/missing_specification.rb
328
321
  - lib/licensed/sources/cabal.rb
322
+ - lib/licensed/sources/cargo.rb
329
323
  - lib/licensed/sources/composer.rb
330
324
  - lib/licensed/sources/dep.rb
331
325
  - lib/licensed/sources/git_submodule.rb
@@ -344,28 +338,6 @@ files:
344
338
  - lib/licensed/ui/shell.rb
345
339
  - lib/licensed/version.rb
346
340
  - licensed.gemspec
347
- - script/bootstrap
348
- - script/cibuild
349
- - script/console
350
- - script/package
351
- - script/packages/build
352
- - script/packages/linux
353
- - script/packages/mac
354
- - script/setup
355
- - script/source-setup/bower
356
- - script/source-setup/bundler
357
- - script/source-setup/cabal
358
- - script/source-setup/composer
359
- - script/source-setup/git_submodule
360
- - script/source-setup/go
361
- - script/source-setup/mix
362
- - script/source-setup/npm
363
- - script/source-setup/nuget
364
- - script/source-setup/pip
365
- - script/source-setup/pipenv
366
- - script/source-setup/swift
367
- - script/source-setup/yarn
368
- - script/test
369
341
  homepage: https://github.com/github/licensed
370
342
  licenses:
371
343
  - MIT
@@ -1,19 +0,0 @@
1
- # To get started with Dependabot version updates, you'll need to specify which
2
- # package ecosystems to update and where the package manifests are located.
3
- # Please see the documentation for all configuration options:
4
- # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
-
6
- version: 2
7
- updates:
8
- - package-ecosystem: github-actions
9
- directory: /
10
- schedule:
11
- interval: daily
12
- - package-ecosystem: bundler
13
- directory: /
14
- schedule:
15
- interval: weekly
16
- - package-ecosystem: docker
17
- directory: docker
18
- schedule:
19
- interval: weekly