licensed 4.3.0 → 4.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fbd6fc2c6122a9b41d7ac258d08861114f6425df01f7e6fd0f482e03a9d3efb
4
- data.tar.gz: 292fce45466f23cc690e3ffd8db6464928b80581c0cc99ab54dedf1e130b0adb
3
+ metadata.gz: 0aa51288268aeff291057d44b430bd4e8b03a1d396eaa1073f2f5401a69a75d5
4
+ data.tar.gz: 340dcf2edab467791df510d35abcf8a48f14239d5edb7d1f09b5df9cf04b40df
5
5
  SHA512:
6
- metadata.gz: 3b462f9f482e65519349ad62b8c8cb53cbadd693dd8a0449e730c6aad63bf5484c78e39b5a67d61aa68169e5bcd65ef3131a591a0bd5965d8fcb0962d382e609
7
- data.tar.gz: 399c6ff21a5a02c849e122365ccf4f8e5813bc7be628236fd5402894d012677501c9dd729cfbb597566f9fb4425f36360df59de8177b5cc0cb456c116e318916
6
+ metadata.gz: 23f1ac2d64039e0942ebd6e39dca3d8fd17d4143308cf0d5d03b9d7b7d6efda6ca7ea998af78caf8f00755631f63960d640c75deeb15fb1f76512895d1f5611a
7
+ data.tar.gz: a7f32b2517e130a2f645678b775c7a0a6b8ae4ce64514a9763fe0d3f174f8f4a28afb79d6c88b49b5e47a225d837ad2cff943142bcc0c00cec80b508827035fd
data/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 4.4.0
10
+
11
+ ### Added
12
+
13
+ - Licensed status command will alert on stale cached dependency records (https://github.com/github/licensed/pull/657)
14
+
15
+ ## 4.3.1
16
+
17
+ ### Changed
18
+
19
+ - Bump nokogiri to resolve vulnerabilities (https://github.com/github/licensed/pull/648)
20
+
9
21
  ## 4.3.0
10
22
 
11
23
  ### Added
@@ -729,4 +741,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
729
741
 
730
742
  Initial release :tada:
731
743
 
732
- [Unreleased]: https://github.com/github/licensed/compare/4.3.0...HEAD
744
+ [Unreleased]: https://github.com/github/licensed/compare/4.4.0...HEAD
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- licensed (4.3.0)
4
+ licensed (4.4.0)
5
5
  json (~> 2.6)
6
6
  licensee (~> 9.16)
7
7
  parallel (~> 1.22)
@@ -44,13 +44,13 @@ GEM
44
44
  minitest (> 5.3)
45
45
  mocha (2.0.2)
46
46
  ruby2_keywords (>= 0.0.5)
47
- nokogiri (1.14.2)
47
+ nokogiri (1.14.3)
48
48
  mini_portile2 (~> 2.8.0)
49
49
  racc (~> 1.4)
50
50
  octokit (6.1.0)
51
51
  faraday (>= 1, < 3)
52
52
  sawyer (~> 0.9)
53
- parallel (1.22.1)
53
+ parallel (1.23.0)
54
54
  parser (3.2.0.0)
55
55
  ast (~> 2.4.1)
56
56
  pathname-common_prefix (0.0.1)
@@ -93,7 +93,7 @@ GEM
93
93
  sawyer (0.9.2)
94
94
  addressable (>= 2.3.5)
95
95
  faraday (>= 0.17.3, < 3)
96
- thor (1.2.1)
96
+ thor (1.2.2)
97
97
  tomlrb (2.0.3)
98
98
  tzinfo (2.0.6)
99
99
  concurrent-ruby (~> 1.0)
@@ -31,6 +31,21 @@ A dependency will fail the status checks if:
31
31
  - If `license: other` is specified and all of the `licenses` entries match an `allowed` license a failure will not be logged
32
32
  - A `reviewed` entry must reference a specific version of the depdency, e.g. `<name>@<version>`. The version identifier must specify a specific dependency version, ranges are not allowed.
33
33
 
34
+ ## Detect and alert on stale cached metadata files
35
+
36
+ Licensed can alert on any metadata files that don't correlate to a currently used dependency when `licensed status` is run. To configure this behavior, set a root-level `stale_records_action` value in your [licensed configuration file](./../configuration.md).
37
+
38
+ Available values are:
39
+
40
+ 1. `'error'`: Treat stale cached records as errors. Licensed will output errors for any stale metadata files and will cause `licensed status` to fail.
41
+ 1. `'warn'`, `''`, or unset (default): Treat stale cached records as warnings. Licensed will output warnings for any stale metadata files but will not cause `licensed status` to fail.
42
+ 1. `'ignore'`, any other value: Ignore stale cached records. Licensed will not output any notifications about stale metadata files.
43
+
44
+ ```yaml
45
+ # in the licensed configuration file
46
+ stale_records_action: 'warn'
47
+ ```
48
+
34
49
  ## Options
35
50
 
36
51
  - `--config`/`-c`: the path to the licensed configuration file
@@ -26,6 +26,15 @@ cache_path: 'relative/path/to/cache'
26
26
  # Defaults to current directory when running `licensed`
27
27
  source_path: 'relative/path/to/source'
28
28
 
29
+ # Whether to take any action when records are detected in the cache paths that don't map to evaluated
30
+ # dependencies.
31
+ # Available values are:
32
+ # - 'error': treat stale cached records as errors. Notify the user and fail status checks
33
+ # - 'warn', '', unset: treat stale cached records as warnings. Notify the user but do not fail status checks
34
+ # - 'ignore': Ignore stale cached records. Do not notify the user and do not fail status checks
35
+ # Optional, when not set this defaults to 'warn' behavior
36
+ stale_records_action: 'warn'
37
+
29
38
  # Sources of metadata
30
39
  sources:
31
40
  bower: true
@@ -23,6 +23,7 @@ module Licensed
23
23
  def run_command(report)
24
24
  super do |result|
25
25
  clear_stale_cached_records if result
26
+ result
26
27
  end
27
28
  ensure
28
29
  cache_paths.clear
@@ -69,7 +69,7 @@ module Licensed
69
69
 
70
70
  result = results.all?
71
71
 
72
- yield(result) if block_given?
72
+ result = yield(result) if block_given?
73
73
 
74
74
  result
75
75
  ensure
@@ -103,7 +103,7 @@ module Licensed
103
103
 
104
104
  result = results.all?
105
105
 
106
- yield(result) if block_given?
106
+ result = yield(result) if block_given?
107
107
 
108
108
  result
109
109
  end
@@ -142,7 +142,7 @@ module Licensed
142
142
 
143
143
  result = results.all?
144
144
 
145
- yield(result) if block_given?
145
+ result = yield(result) if block_given?
146
146
 
147
147
  result
148
148
  rescue Licensed::Shell::Error => err
@@ -175,7 +175,7 @@ module Licensed
175
175
 
176
176
  result = evaluate_dependency(app, source, dependency, report)
177
177
 
178
- yield(result) if block_given?
178
+ result = yield(result) if block_given?
179
179
 
180
180
  result
181
181
  rescue Licensed::DependencyRecord::Error, Licensed::Shell::Error => err
@@ -23,10 +23,48 @@ module Licensed
23
23
  # Returns whether the command succeeded based on the call to super
24
24
  def run_command(report)
25
25
  super do |result|
26
- next if result
26
+ stale_records = stale_cached_records
27
+ if stale_records.any?
28
+ messages = stale_records.map { |f| "Stale dependency record found: #{f}" }
29
+ messages << "Please run the licensed cache command to clean up stale records"
30
+
31
+ case config["stale_records_action"].to_s
32
+ when "error"
33
+ report.errors.concat messages
34
+ result = false
35
+ when "warn", ""
36
+ report.warnings.concat messages
37
+ end
38
+ end
39
+
40
+ next result if result
27
41
 
28
42
  report.errors << "Licensed found errors during source enumeration. Please see https://github.com/github/licensed/tree/master/docs/commands/status.md#status-errors-and-resolutions for possible resolutions."
43
+
44
+ result
29
45
  end
46
+ ensure
47
+ cache_paths.clear
48
+ files.clear
49
+ end
50
+
51
+ # Run the command for all enumerated dependencies found in a dependency source,
52
+ # recording results in a report.
53
+ # Enumerating dependencies in the source is skipped if a :sources option
54
+ # is provided and the evaluated `source.class.type` is not in the :sources values
55
+ #
56
+ # app - The application configuration for the source
57
+ # source - A dependency source enumerator
58
+ #
59
+ # Returns whether the command succeeded for the dependency source enumerator
60
+ def run_source(app, source, report)
61
+ result = super
62
+
63
+ # add the full cache path to the list of cache paths
64
+ # that should be checked for extra files after the command run
65
+ cache_paths << app.cache_path.join(source.class.type) unless result == :skipped
66
+
67
+ result
30
68
  end
31
69
 
32
70
  # Evaluates a dependency for any compliance errors.
@@ -49,6 +87,9 @@ module Licensed
49
87
  filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}")
50
88
  report["filename"] = filename
51
89
  record = cached_record(filename)
90
+
91
+ # add the absolute dependency file path to the list of files seen during this licensed run
92
+ files << filename.to_s
52
93
  end
53
94
 
54
95
  if record.nil?
@@ -133,6 +174,26 @@ module Licensed
133
174
 
134
175
  licenses.sort_by { |license| license != "other" ? 0 : 1 }.first
135
176
  end
177
+
178
+ # Check for cached files that don't match current dependencies
179
+ #
180
+ # Returns an array of any cached records that do not match a currently used dependency
181
+ def stale_cached_records
182
+ cache_paths.flat_map do |cache_path|
183
+ record_search_glob_pattern = cache_path.join("**/*.#{DependencyRecord::EXTENSION}")
184
+ Dir.glob(record_search_glob_pattern).select { |file| !files.include?(file) }
185
+ end.uniq
186
+ end
187
+
188
+ # Set of unique cache paths that are evaluted during the run
189
+ def cache_paths
190
+ @cache_paths ||= Set.new
191
+ end
192
+
193
+ # Set of unique absolute file paths of cached records evaluted during the run
194
+ def files
195
+ @files ||= Set.new
196
+ end
136
197
  end
137
198
  end
138
199
  end
@@ -274,6 +274,7 @@ module Licensed
274
274
  end
275
275
 
276
276
  def initialize(options = {})
277
+ @options = options
277
278
  apps = options.delete("apps") || []
278
279
  apps << default_options.merge(options) if apps.empty?
279
280
 
@@ -285,6 +286,10 @@ module Licensed
285
286
  @apps = apps.map { |app| AppConfiguration.new(app, options) }
286
287
  end
287
288
 
289
+ def [](key)
290
+ @options&.fetch(key, nil)
291
+ end
292
+
288
293
  private
289
294
 
290
295
  def self.expand_app_source_path(app_config)
@@ -8,6 +8,11 @@ module Licensed
8
8
  # command - The command being run
9
9
  # report - A report object containing information about the command run
10
10
  def end_report_command(command, report)
11
+ if report.warnings.any?
12
+ shell.newline
13
+ report.warnings.each { |e| shell.warn e }
14
+ end
15
+
11
16
  if report.errors.any?
12
17
  shell.newline
13
18
  report.errors.each { |e| shell.error e }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "4.3.0".freeze
3
+ VERSION = "4.4.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.3.0
4
+ version: 4.4.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-03-20 00:00:00.000000000 Z
11
+ date: 2023-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee