licensed 2.8.0 → 2.9.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 +2 -2
- data/CHANGELOG.md +16 -1
- data/docs/commands.md +2 -0
- data/docs/configuration.md +16 -0
- data/lib/licensed/commands/cache.rb +9 -2
- data/lib/licensed/commands/environment.rb +2 -2
- data/lib/licensed/commands/status.rb +5 -1
- data/lib/licensed/configuration.rb +61 -36
- data/lib/licensed/git.rb +3 -1
- data/lib/licensed/sources/go.rb +25 -18
- data/lib/licensed/sources/mix.rb +5 -1
- data/lib/licensed/version.rb +1 -1
- data/licensed.gemspec +2 -2
- data/script/bootstrap +2 -1
- metadata +16 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64aab6dfce9359aa8e821d75416c11d276b67668d14b5db2c135301fd32fcbdd
|
4
|
+
data.tar.gz: 96862d7720c79ae99b7d500c5d15b0956a8a54bab54b811df4f12828427a8bc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b57cd2414d204f2d547b3e1bcc64c026b7816a35afa370cdb315bdbdeccfb06b43b76abcc865cf468ea548b111c8bcce5396818537414732cba0a2256ca0525
|
7
|
+
data.tar.gz: 57f5618394751f20ff73f57209726400ec9197e1c21130cd8123864da7c4f7f3e868bf021d4fe6de0508a2328635178b696180d76e9aa7ff07d5ef6a49b22753
|
data/.github/workflows/test.yml
CHANGED
@@ -170,7 +170,7 @@ jobs:
|
|
170
170
|
runs-on: ubuntu-latest
|
171
171
|
strategy:
|
172
172
|
matrix:
|
173
|
-
go: [ '1.7.x', '1.10.x', '1.11.1' ]
|
173
|
+
go: [ '1.7.x', '1.10.x', '1.11.x', '1.12.x', '1.13.x', '1.14.x' ]
|
174
174
|
steps:
|
175
175
|
- uses: actions/checkout@master
|
176
176
|
- name: Setup go
|
@@ -342,7 +342,7 @@ jobs:
|
|
342
342
|
run: script/source-setup/pipenv
|
343
343
|
- name: Run tests
|
344
344
|
run: script/test pipenv
|
345
|
-
|
345
|
+
|
346
346
|
yarn:
|
347
347
|
runs-on: ubuntu-latest
|
348
348
|
strategy:
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## 2.9.0
|
10
|
+
2020-03-19
|
11
|
+
|
12
|
+
## Added
|
13
|
+
- Source paths use glob pattern matching (https://github.com/github/licensed/pull/245)
|
14
|
+
|
15
|
+
## Fixed
|
16
|
+
- Mix source supports updates to mix.lock format (:tada: @bruce https://github.com/github/licensed/pull/242)
|
17
|
+
- Go source supports `go list` format changes in go 1.14 (https://github.com/github/licensed/pull/247)
|
18
|
+
|
19
|
+
## Changed
|
20
|
+
- `licensed cache` will flag dependencies for re-review when license text changes (https://github.com/github/licensed/pull/248)
|
21
|
+
- `licensed status` will raise errors on dependencies that need re-review (https://github.com/github/licensed/pull/248)
|
22
|
+
- `licensee` minimum version bumped to 9.13.1 (https://github.com/github/licensed/pull/251)
|
23
|
+
|
9
24
|
## 2.8.0
|
10
25
|
2020-01-03
|
11
26
|
|
@@ -265,4 +280,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
265
280
|
|
266
281
|
Initial release :tada:
|
267
282
|
|
268
|
-
[Unreleased]: https://github.com/github/licensed/compare/2.
|
283
|
+
[Unreleased]: https://github.com/github/licensed/compare/2.9.0...HEAD
|
data/docs/commands.md
CHANGED
@@ -28,6 +28,8 @@ A dependency will fail the status checks if:
|
|
28
28
|
3. The cached record's `licenses` data is empty
|
29
29
|
4. The cached record's `license` metadata doesn't match an `allowed` license from the dependency's application configuration.
|
30
30
|
- If `license: other` is specified and all of the `licenses` entries match an `allowed` license a failure will not be logged
|
31
|
+
5. The cached record is flagged for re-review.
|
32
|
+
- This occurs when the record's license text has changed since the record was reviewed.
|
31
33
|
|
32
34
|
## `env`
|
33
35
|
|
data/docs/configuration.md
CHANGED
@@ -19,6 +19,22 @@ If a root path is not specified, it will default to using the following, in orde
|
|
19
19
|
1. the root of the local git repository, if run inside a git repository
|
20
20
|
2. the current directory
|
21
21
|
|
22
|
+
### Source path glob patterns
|
23
|
+
|
24
|
+
The `source_path` property can use a glob path to share configuration properties across multiple application entrypoints.
|
25
|
+
|
26
|
+
For example, there is a common pattern in go projects to include multiple executable entrypoints under folders in `cmd`. Using a glob pattern allows users to avoid manually configuring and maintaining multiple licensed application `source_path`s. Using a glob pattern will also ensure that any new entrypoints matching the pattern are automatically picked up by licensed commands as they are added.
|
27
|
+
|
28
|
+
```yml
|
29
|
+
sources:
|
30
|
+
go: true
|
31
|
+
|
32
|
+
# treat all directories under `cmd` as separate apps
|
33
|
+
source_path: cmd/*
|
34
|
+
```
|
35
|
+
|
36
|
+
Glob patterns are syntactic sugar for, and provide the same functionality as, manually specifying multiple `source_path` values. See the instructions on [specifying multiple apps](./#specifying-multiple-apps) below for additional considerations when using multiple apps.
|
37
|
+
|
22
38
|
## Restricting sources
|
23
39
|
|
24
40
|
The `sources` configuration property specifies which sources `licensed` will use to enumerate dependencies.
|
@@ -45,8 +45,15 @@ module Licensed
|
|
45
45
|
filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}")
|
46
46
|
cached_record = Licensed::DependencyRecord.read(filename)
|
47
47
|
if options[:force] || save_dependency_record?(dependency, cached_record)
|
48
|
-
|
49
|
-
|
48
|
+
if dependency.record.matches?(cached_record)
|
49
|
+
# use the cached license value if the license text wasn't updated
|
50
|
+
dependency.record["license"] = cached_record["license"]
|
51
|
+
elsif cached_record && app.reviewed?(dependency.record)
|
52
|
+
# if the license text changed and the dependency is set as reviewed
|
53
|
+
# force a re-review of the dependency
|
54
|
+
dependency.record["review_changed_license"] = true
|
55
|
+
end
|
56
|
+
|
50
57
|
dependency.record.save(filename)
|
51
58
|
report["cached"] = true
|
52
59
|
end
|
@@ -23,14 +23,14 @@ module Licensed
|
|
23
23
|
"allowed" => config["allowed"],
|
24
24
|
"ignored" => config["ignored"],
|
25
25
|
"reviewed" => config["reviewed"],
|
26
|
-
"version_strategy" => self.version_strategy
|
26
|
+
"version_strategy" => self.version_strategy,
|
27
|
+
"root" => config.root
|
27
28
|
}
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
32
|
def run(**options)
|
32
33
|
super do |report|
|
33
|
-
report["root"] = config.root
|
34
34
|
report["git_repo"] = Licensed::Git.git_repo?
|
35
35
|
end
|
36
36
|
end
|
@@ -35,7 +35,11 @@ module Licensed
|
|
35
35
|
else
|
36
36
|
report.errors << "cached dependency record out of date" if cached_record["version"] != dependency.version
|
37
37
|
report.errors << "missing license text" if cached_record.licenses.empty?
|
38
|
-
|
38
|
+
if cached_record["review_changed_license"]
|
39
|
+
report.errors << "license text has changed and needs re-review. if the new text is ok, remove the `review_changed_license` flag from the cached record"
|
40
|
+
elsif license_needs_review?(app, cached_record)
|
41
|
+
report.errors << "license needs review: #{cached_record["license"]}"
|
42
|
+
end
|
39
43
|
end
|
40
44
|
|
41
45
|
report.errors.empty?
|
@@ -4,40 +4,39 @@ require "pathname"
|
|
4
4
|
module Licensed
|
5
5
|
class AppConfiguration < Hash
|
6
6
|
DEFAULT_CACHE_PATH = ".licenses".freeze
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
|
8
|
+
# Returns the root for a configuration in following order of precendence:
|
9
|
+
# 1. explicitly configured "root" property
|
10
|
+
# 2. a found git repository root
|
11
|
+
# 3. the current directory
|
12
|
+
def self.root_for(configuration)
|
13
|
+
configuration["root"] || Licensed::Git.repository_root || Dir.pwd
|
14
|
+
end
|
12
15
|
|
13
16
|
def initialize(options = {}, inherited_options = {})
|
14
17
|
super()
|
15
18
|
|
16
19
|
# update order:
|
17
20
|
# 1. anything inherited from root config
|
18
|
-
# 2. app
|
19
|
-
# 3. explicitly configured app settings
|
21
|
+
# 2. explicitly configured app settings
|
20
22
|
update(inherited_options)
|
21
|
-
update(defaults_for(options, inherited_options))
|
22
23
|
update(options)
|
24
|
+
verify_arg "source_path"
|
23
25
|
|
24
26
|
self["sources"] ||= {}
|
25
27
|
self["reviewed"] ||= {}
|
26
28
|
self["ignored"] ||= {}
|
27
29
|
self["allowed"] ||= []
|
28
|
-
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
verify_arg "source_path"
|
34
|
-
verify_arg "cache_path"
|
30
|
+
self["root"] = AppConfiguration.root_for(self)
|
31
|
+
# defaults to the directory name of the source path if not set
|
32
|
+
self["name"] ||= File.basename(self["source_path"])
|
33
|
+
# setting the cache path might need a valid app name
|
34
|
+
self["cache_path"] = detect_cache_path(options, inherited_options)
|
35
35
|
end
|
36
36
|
|
37
37
|
# Returns the path to the workspace root as a Pathname.
|
38
|
-
# Defaults to Licensed::Git.repository_root if not explicitly set
|
39
38
|
def root
|
40
|
-
Pathname.new(self["root"])
|
39
|
+
@root ||= Pathname.new(self["root"])
|
41
40
|
end
|
42
41
|
|
43
42
|
# Returns the path to the app cache directory as a Pathname
|
@@ -102,13 +101,15 @@ module Licensed
|
|
102
101
|
|
103
102
|
private
|
104
103
|
|
105
|
-
|
106
|
-
|
104
|
+
# Returns the cache path for the application based on:
|
105
|
+
# 1. An explicitly set cache path for the application, if set
|
106
|
+
# 2. An inherited root cache path joined with the app name
|
107
|
+
# 3. The default cache path joined with the app name
|
108
|
+
def detect_cache_path(options, inherited_options)
|
109
|
+
return options["cache_path"] unless options["cache_path"].to_s.empty?
|
110
|
+
|
107
111
|
cache_path = inherited_options["cache_path"] || DEFAULT_CACHE_PATH
|
108
|
-
|
109
|
-
"name" => name,
|
110
|
-
"cache_path" => File.join(cache_path, name)
|
111
|
-
}
|
112
|
+
File.join(cache_path, self["name"])
|
112
113
|
end
|
113
114
|
|
114
115
|
def verify_arg(property)
|
@@ -118,9 +119,18 @@ module Licensed
|
|
118
119
|
end
|
119
120
|
end
|
120
121
|
|
121
|
-
class Configuration
|
122
|
+
class Configuration
|
123
|
+
DEFAULT_CONFIG_FILES = [
|
124
|
+
".licensed.yml".freeze,
|
125
|
+
".licensed.yaml".freeze,
|
126
|
+
".licensed.json".freeze
|
127
|
+
].freeze
|
128
|
+
|
122
129
|
class LoadError < StandardError; end
|
123
130
|
|
131
|
+
# An array of the applications in this licensed configuration.
|
132
|
+
attr_reader :apps
|
133
|
+
|
124
134
|
# Loads and returns a Licensed::Configuration object from the given path.
|
125
135
|
# The path can be relative or absolute, and can point at a file or directory.
|
126
136
|
# If the path given is a directory, the directory will be searched for a
|
@@ -133,21 +143,36 @@ module Licensed
|
|
133
143
|
|
134
144
|
def initialize(options = {})
|
135
145
|
apps = options.delete("apps") || []
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
# Returns an array of the applications for this licensed configuration.
|
142
|
-
# If the configuration did not explicitly configure any applications,
|
143
|
-
# return self as an application configuration.
|
144
|
-
def apps
|
145
|
-
return [self] if self["apps"].empty?
|
146
|
-
self["apps"]
|
146
|
+
apps << default_options.merge(options) if apps.empty?
|
147
|
+
apps = apps.flat_map { |app| self.class.expand_app_source_path(app) }
|
148
|
+
@apps = apps.map { |app| AppConfiguration.new(app, options) }
|
147
149
|
end
|
148
150
|
|
149
151
|
private
|
150
152
|
|
153
|
+
def self.expand_app_source_path(app_config)
|
154
|
+
return app_config if app_config["source_path"].to_s.empty?
|
155
|
+
|
156
|
+
source_path = File.expand_path(app_config["source_path"], AppConfiguration.root_for(app_config))
|
157
|
+
expanded_source_paths = Dir.glob(source_path).select { |p| File.directory?(p) }
|
158
|
+
# return the original configuration if glob didn't result in multiple paths
|
159
|
+
return app_config if expanded_source_paths.size <= 1
|
160
|
+
|
161
|
+
# map the expanded paths to new application configurations
|
162
|
+
expanded_source_paths.map do |path|
|
163
|
+
config = app_config.merge("source_path" => path)
|
164
|
+
|
165
|
+
# update configured values for name and cache_path for uniqueness.
|
166
|
+
# this is only needed when values are explicitly set, AppConfiguration
|
167
|
+
# will handle configurations that don't have these explicitly set
|
168
|
+
dir_name = File.basename(path)
|
169
|
+
config["name"] = "#{config["name"]}-#{dir_name}" if config["name"]
|
170
|
+
config["cache_path"] = File.join(config["cache_path"], dir_name) if config["cache_path"]
|
171
|
+
|
172
|
+
config
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
151
176
|
# Find a default configuration file in the given directory.
|
152
177
|
# File preference is given by the order of elements in DEFAULT_CONFIG_FILES
|
153
178
|
#
|
@@ -198,7 +223,7 @@ module Licensed
|
|
198
223
|
# manually set a cache path without additional name
|
199
224
|
{
|
200
225
|
"source_path" => Dir.pwd,
|
201
|
-
"cache_path" => DEFAULT_CACHE_PATH
|
226
|
+
"cache_path" => AppConfiguration::DEFAULT_CACHE_PATH
|
202
227
|
}
|
203
228
|
end
|
204
229
|
end
|
data/lib/licensed/git.rb
CHANGED
@@ -11,7 +11,9 @@ module Licensed
|
|
11
11
|
# or nil if not in a git repository.
|
12
12
|
def repository_root
|
13
13
|
return unless available?
|
14
|
-
Licensed::Shell.execute("git", "rev-parse", "--show-toplevel", allow_failure: true)
|
14
|
+
root = Licensed::Shell.execute("git", "rev-parse", "--show-toplevel", allow_failure: true)
|
15
|
+
return nil if root.empty?
|
16
|
+
root
|
15
17
|
end
|
16
18
|
|
17
19
|
# Returns true if a git repository is found, false otherwise
|
data/lib/licensed/sources/go.rb
CHANGED
@@ -15,7 +15,8 @@ module Licensed
|
|
15
15
|
def enumerate_dependencies
|
16
16
|
with_configured_gopath do
|
17
17
|
packages.map do |package|
|
18
|
-
import_path =
|
18
|
+
import_path = non_vendored_path(package["ImportPath"], root_package["ImportPath"])
|
19
|
+
import_path ||= package["ImportPath"]
|
19
20
|
error = package.dig("Error", "Err") if package["Error"]
|
20
21
|
|
21
22
|
Dependency.new(
|
@@ -86,14 +87,17 @@ module Licensed
|
|
86
87
|
# true if go standard packages includes the import path as given
|
87
88
|
return true if go_std_packages.include?(import_path)
|
88
89
|
return true if go_std_packages.include?("vendor/#{import_path}")
|
90
|
+
return true if go_std_packages.include?(import_path.sub("golang.org", "internal"))
|
89
91
|
|
90
92
|
# additional checks are only for vendored dependencies - return false
|
91
93
|
# if package isn't vendored
|
92
|
-
|
94
|
+
non_vendored_import_path = non_vendored_path(import_path, root_package["ImportPath"])
|
95
|
+
return false unless non_vendored_import_path
|
93
96
|
|
94
97
|
# return true if any of the go standard packages matches against
|
95
98
|
# the non-vendored import path
|
96
|
-
return true if go_std_packages.include?(non_vendored_import_path
|
99
|
+
return true if go_std_packages.include?(non_vendored_import_path)
|
100
|
+
return true if go_std_packages.include?(non_vendored_import_path.sub("golang.org", "internal"))
|
97
101
|
|
98
102
|
# modify the import path to look like the import path `go list` returns for vendored std packages
|
99
103
|
vendor_path = import_path.sub("#{root_package["ImportPath"]}/", "")
|
@@ -104,7 +108,7 @@ module Licensed
|
|
104
108
|
def local_package?(package)
|
105
109
|
return false unless package && package["ImportPath"]
|
106
110
|
import_path = package["ImportPath"]
|
107
|
-
import_path.start_with?(root_package["ImportPath"]) && !
|
111
|
+
import_path.start_with?(root_package["ImportPath"]) && !import_path.include?("vendor/")
|
108
112
|
end
|
109
113
|
|
110
114
|
# Returns the version for a given package
|
@@ -150,34 +154,37 @@ module Licensed
|
|
150
154
|
return if package.nil?
|
151
155
|
|
152
156
|
# search root choices:
|
153
|
-
# 1. module directory if using go modules
|
157
|
+
# 1. module directory if using go modules and directory is available
|
154
158
|
# 2. vendor folder if package is vendored
|
155
159
|
# 3. package root value if available
|
156
160
|
# 4. GOPATH if the package directory is under the gopath
|
157
161
|
# 5. nil
|
158
|
-
|
159
|
-
return
|
162
|
+
module_dir = package.dig("Module", "Dir")
|
163
|
+
return module_dir if module_dir
|
164
|
+
return package["Dir"].match("^(.*/vendor)/.*$")[1] if vendored_path?(package["Dir"], config.root)
|
160
165
|
return package["Root"] if package["Root"]
|
161
166
|
return gopath if package["Dir"]&.start_with?(gopath)
|
162
167
|
nil
|
163
168
|
end
|
164
169
|
|
165
|
-
# Returns whether a package is vendored or not based on
|
166
|
-
#
|
170
|
+
# Returns whether a package is vendored or not based on a base path and
|
171
|
+
# whether the path contains a vendor component
|
167
172
|
#
|
168
173
|
# path - Package path to test
|
169
|
-
|
170
|
-
|
171
|
-
path.
|
174
|
+
# base - The base path that the input must start with
|
175
|
+
def vendored_path?(path, base)
|
176
|
+
return false if path.nil? || base.nil?
|
177
|
+
path.start_with?(base.to_s) && path.include?("vendor/")
|
172
178
|
end
|
173
179
|
|
174
|
-
# Returns the
|
180
|
+
# Returns the path parameter without the vendor component if one is found
|
175
181
|
#
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
return
|
180
|
-
|
182
|
+
# path - Package path with vendor component
|
183
|
+
# base - The base path that the input must start with
|
184
|
+
def non_vendored_path(path, base)
|
185
|
+
return unless path
|
186
|
+
return unless vendored_path?(path, base)
|
187
|
+
path.split("vendor/")[1]
|
181
188
|
end
|
182
189
|
|
183
190
|
# Returns a hash of information about the package with a given import path
|
data/lib/licensed/sources/mix.rb
CHANGED
@@ -93,8 +93,12 @@ module Licensed
|
|
93
93
|
:[a-zA-Z0-9_]+ # after an Elixir atom,
|
94
94
|
,\s* # and skipping a comma and any number of spaces,
|
95
95
|
"(?<version>.*?)" # capture the contents of a double-quoted string as the version,
|
96
|
-
|
96
|
+
.*?\],\s* # and later
|
97
97
|
"(?<repo>.*?)" # capture the contents of a double-quoted string as the repo
|
98
|
+
(?:
|
99
|
+
,\s* # a comma
|
100
|
+
"[a-f0-9]{64}" # a digest
|
101
|
+
)?
|
98
102
|
\},?\s*\Z # right before the final closing brace.
|
99
103
|
/x,
|
100
104
|
|
data/lib/licensed/version.rb
CHANGED
data/licensed.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.required_ruby_version = ">= 2.3.0"
|
25
25
|
|
26
|
-
spec.add_dependency "licensee", "
|
26
|
+
spec.add_dependency "licensee", ">= 9.13.1", "< 10.0.0"
|
27
27
|
spec.add_dependency "thor", "~> 0.19"
|
28
28
|
spec.add_dependency "pathname-common_prefix", "~> 0.0.1"
|
29
29
|
spec.add_dependency "tomlrb", "~> 1.2"
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency "ruby-xxHash", "~> 0.4"
|
32
32
|
spec.add_dependency "parallel", ">= 0.18.0"
|
33
33
|
|
34
|
-
spec.add_development_dependency "rake", "
|
34
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
35
35
|
spec.add_development_dependency "minitest", "~> 5.8"
|
36
36
|
spec.add_development_dependency "mocha", "~> 1.0"
|
37
37
|
spec.add_development_dependency "rubocop", "~> 0.49", "< 0.67"
|
data/script/bootstrap
CHANGED
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: licensed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.9.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-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: licensee
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 9.13.1
|
20
|
+
- - "<"
|
18
21
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
22
|
+
version: 10.0.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
29
|
+
version: 9.13.1
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 10.0.0
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: thor
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,16 +118,16 @@ dependencies:
|
|
112
118
|
name: rake
|
113
119
|
requirement: !ruby/object:Gem::Requirement
|
114
120
|
requirements:
|
115
|
-
- - "
|
121
|
+
- - ">="
|
116
122
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
123
|
+
version: 12.3.3
|
118
124
|
type: :development
|
119
125
|
prerelease: false
|
120
126
|
version_requirements: !ruby/object:Gem::Requirement
|
121
127
|
requirements:
|
122
|
-
- - "
|
128
|
+
- - ">="
|
123
129
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
130
|
+
version: 12.3.3
|
125
131
|
- !ruby/object:Gem::Dependency
|
126
132
|
name: minitest
|
127
133
|
requirement: !ruby/object:Gem::Requirement
|