license_finder 6.14.2 → 7.0.1

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +9 -0
  3. data/.rubocop.yml +12 -2
  4. data/CHANGELOG.md +35 -4
  5. data/Dockerfile +26 -5
  6. data/README.md +30 -27
  7. data/Rakefile +2 -2
  8. data/VERSION +1 -1
  9. data/ci/pipelines/release.yml.erb +1 -1
  10. data/ci/scripts/pushscript.sh +2 -3
  11. data/ci/scripts/run-tests.sh +4 -3
  12. data/ci/tasks/rubocop.yml +1 -1
  13. data/dlf +9 -5
  14. data/lib/license_finder/cli/approvals.rb +2 -2
  15. data/lib/license_finder/cli/base.rb +9 -5
  16. data/lib/license_finder/cli/dependencies.rb +4 -4
  17. data/lib/license_finder/cli/ignored_dependencies.rb +3 -3
  18. data/lib/license_finder/cli/ignored_groups.rb +3 -3
  19. data/lib/license_finder/cli/inherited_decisions.rb +5 -5
  20. data/lib/license_finder/cli/licenses.rb +2 -2
  21. data/lib/license_finder/cli/main.rb +17 -11
  22. data/lib/license_finder/cli/permitted_licenses.rb +3 -3
  23. data/lib/license_finder/cli/project_name.rb +4 -4
  24. data/lib/license_finder/cli/restricted_licenses.rb +3 -3
  25. data/lib/license_finder/configuration.rb +6 -3
  26. data/lib/license_finder/core.rb +2 -1
  27. data/lib/license_finder/decisions.rb +9 -5
  28. data/lib/license_finder/license/definitions.rb +22 -0
  29. data/lib/license_finder/license/text.rb +5 -3
  30. data/lib/license_finder/license.rb +8 -2
  31. data/lib/license_finder/logger.rb +1 -1
  32. data/lib/license_finder/package.rb +3 -11
  33. data/lib/license_finder/package_delta.rb +1 -1
  34. data/lib/license_finder/package_manager.rb +1 -0
  35. data/lib/license_finder/package_managers/cocoa_pods.rb +14 -9
  36. data/lib/license_finder/package_managers/conan.rb +2 -2
  37. data/lib/license_finder/package_managers/conda.rb +1 -1
  38. data/lib/license_finder/package_managers/glide.rb +7 -1
  39. data/lib/license_finder/package_managers/go_15vendorexperiment.rb +2 -2
  40. data/lib/license_finder/package_managers/go_dep.rb +1 -1
  41. data/lib/license_finder/package_managers/go_workspace.rb +1 -1
  42. data/lib/license_finder/package_managers/maven.rb +2 -6
  43. data/lib/license_finder/package_managers/nuget.rb +1 -1
  44. data/lib/license_finder/package_managers/pub.rb +86 -0
  45. data/lib/license_finder/package_managers/sbt.rb +1 -5
  46. data/lib/license_finder/package_managers/yarn.rb +48 -9
  47. data/lib/license_finder/package_utils/license_files.rb +2 -2
  48. data/lib/license_finder/packages/bower_package.rb +5 -2
  49. data/lib/license_finder/packages/erlangmk_package.rb +2 -4
  50. data/lib/license_finder/packages/npm_package.rb +1 -0
  51. data/lib/license_finder/packages/pubspec_package.rb +18 -0
  52. data/lib/license_finder/printer.rb +39 -0
  53. data/lib/license_finder/report.rb +2 -1
  54. data/lib/license_finder/reports/csv_report.rb +1 -1
  55. data/lib/license_finder/reports/erb_report.rb +7 -3
  56. data/lib/license_finder/reports/json_report.rb +2 -1
  57. data/lib/license_finder/reports/junit_report.rb +5 -1
  58. data/lib/license_finder/reports/xml_report.rb +5 -1
  59. data/lib/license_finder/scanner.rb +1 -1
  60. data/license_finder.gemspec +15 -13
  61. metadata +58 -26
@@ -38,7 +38,7 @@ module LicenseFinder
38
38
  project_path.join(GODEP_VENDOR_PATH)
39
39
  else
40
40
  download_dependencies
41
- Pathname(ENV['GOPATH'] ? ENV['GOPATH'] + '/src' : ENV['HOME'] + '/go/src')
41
+ Pathname(ENV['GOPATH'] ? "#{ENV['GOPATH']}/src" : "#{ENV['HOME']}/go/src")
42
42
  end
43
43
  end
44
44
 
@@ -94,7 +94,7 @@ module LicenseFinder
94
94
  deps = val.split("\n")
95
95
  Cmd.run('go list std').first.split("\n").each do |std|
96
96
  deps.delete_if do |dep|
97
- dep =~ %r{(\/|^)#{std}(\/|$)}
97
+ dep =~ %r{(/|^)#{std}(/|$)}
98
98
  end
99
99
  end
100
100
  deps
@@ -34,14 +34,10 @@ module LicenseFinder
34
34
  end
35
35
 
36
36
  def package_management_command
37
- wrapper = if Platform.windows?
38
- 'mvnw.cmd'
39
- else
40
- './mvnw'
41
- end
37
+ wrapper = File.join(project_path, Platform.windows? ? 'mvnw.cmd' : 'mvnw')
42
38
  maven = 'mvn'
43
39
 
44
- File.exist?(File.join(project_path, wrapper)) ? wrapper : maven
40
+ File.exist?(wrapper) ? wrapper : maven
45
41
  end
46
42
 
47
43
  def possible_package_paths
@@ -64,7 +64,7 @@ module LicenseFinder
64
64
 
65
65
  file = files.first
66
66
  Zip::File.open file do |zipfile|
67
- content = zipfile.read(dep.name + '.nuspec')
67
+ content = zipfile.read("#{dep.name}.nuspec")
68
68
  Nuget.nuspec_license_urls(content)
69
69
  end
70
70
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ module LicenseFinder
7
+ class Pub < PackageManager
8
+ class PubError < RuntimeError; end
9
+
10
+ def current_packages
11
+ unless File.exist?('pubspec.lock')
12
+ raise PubError, "No checked-out Pub packages found.
13
+ Please install your dependencies first."
14
+ end
15
+
16
+ if ENV['PUB_CACHE'].nil? || ENV['PUB_CACHE'].eql?('')
17
+ raise PubError, 'While PUB_CACHE environment variable is empty, retrieving package licenses is impossible. Please set the PUB_CACHE env variable (default: ~/.pub)'
18
+ end
19
+
20
+ stdout, _stderr, _status = Cmd.run('flutter pub deps --json')
21
+ yaml_deps = JSON.parse(stdout)
22
+ yaml_deps['packages'].map do |dependency|
23
+ package_name = dependency['name']
24
+ subpath = "#{dependency['name']}-#{dependency['version']}"
25
+ package_version = dependency['version']
26
+
27
+ project_repo = dependency['source'] == 'git' ? Pathname("#{ENV['PUB_CACHE']}/git/#{dependency['name']}-*/") : Pathname("#{ENV['PUB_CACHE']}/hosted/pub.dartlang.org/#{subpath}")
28
+
29
+ homepage = read_repository_home(project_repo)
30
+ homepage = "https://pub.dev/packages/#{package_name}" if homepage.nil? || homepage.empty?
31
+ PubPackage.new(
32
+ package_name,
33
+ package_version,
34
+ license_text(project_repo),
35
+ logger: logger,
36
+ install_path: project_repo,
37
+ homepage: homepage
38
+ )
39
+ end
40
+ end
41
+
42
+ def possible_package_paths
43
+ [project_path.join('pubspec.lock')]
44
+ end
45
+
46
+ def package_management_command
47
+ 'flutter'
48
+ end
49
+
50
+ def prepare_command
51
+ 'flutter pub get'
52
+ end
53
+
54
+ def prepare
55
+ prep_cmd = "#{prepare_command} #{production_flag}"
56
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
57
+
58
+ return if status.success?
59
+
60
+ log_errors stderr
61
+ raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
62
+ end
63
+
64
+ private
65
+
66
+ def license_text(subpath)
67
+ license_path = license_pattern(subpath).find { |f| File.exist?(f) }
68
+ license_path.nil? ? nil : IO.read(license_path)
69
+ end
70
+
71
+ def license_pattern(subpath)
72
+ Dir.glob(subpath.join('LICENSE*'), File::FNM_CASEFOLD)
73
+ end
74
+
75
+ def production_flag
76
+ return '' if @ignored_groups.nil?
77
+
78
+ @ignored_groups.include?('devDependencies') ? '' : 'no-'
79
+ end
80
+
81
+ def read_repository_home(project_repo)
82
+ package_yaml = project_repo.join('pubspec.yaml')
83
+ YAML.load(IO.read(package_yaml))['repository'] if Dir.exist?(project_repo) && File.exist?(package_yaml)
84
+ end
85
+ end
86
+ end
@@ -17,11 +17,7 @@ module LicenseFinder
17
17
 
18
18
  dependencies = SbtDependencyFinder.new(project_path).dependencies
19
19
  packages = dependencies.flat_map do |text|
20
- options = {
21
- headers: true
22
- }
23
-
24
- contents = CSV.parse(text, options)
20
+ contents = CSV.parse(text, headers: true)
25
21
  contents.map do |row|
26
22
  group_id, name, version = row['Dependency'].split('#').map(&:strip)
27
23
  spec = {
@@ -2,19 +2,22 @@
2
2
 
3
3
  module LicenseFinder
4
4
  class Yarn < PackageManager
5
- SHELL_COMMAND = 'yarn licenses list --no-progress --json'
5
+ SHELL_COMMAND = 'yarn licenses list --json'
6
6
 
7
7
  def possible_package_paths
8
8
  [project_path.join('yarn.lock')]
9
9
  end
10
10
 
11
11
  def current_packages
12
- cmd = "#{Yarn::SHELL_COMMAND}#{production_flag}"
13
- suffix = " --cwd #{project_path}" unless project_path.nil?
14
- cmd += suffix unless suffix.nil?
12
+ # the licenses plugin supports the classic production flag
13
+ cmd = "#{Yarn::SHELL_COMMAND}#{classic_yarn_production_flag}"
14
+ if yarn_version == 1
15
+ cmd += ' --no-progress'
16
+ cmd += " --cwd #{project_path}" unless project_path.nil?
17
+ end
15
18
 
16
- stdout, _stderr, status = Cmd.run(cmd)
17
- return [] unless status.success?
19
+ stdout, stderr, status = Cmd.run(cmd)
20
+ raise "Command '#{cmd}' failed to execute: #{stderr}" unless status.success?
18
21
 
19
22
  packages = []
20
23
  incompatible_packages = []
@@ -39,7 +42,7 @@ module LicenseFinder
39
42
  end
40
43
 
41
44
  def prepare
42
- prep_cmd = "#{prepare_command}#{production_flag}"
45
+ prep_cmd = prepare_command.to_s
43
46
  _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
44
47
  return if status.success?
45
48
 
@@ -56,11 +59,41 @@ module LicenseFinder
56
59
  end
57
60
 
58
61
  def prepare_command
59
- 'yarn install --ignore-engines --ignore-scripts'
62
+ if yarn_version == 1
63
+ classic_yarn_prepare_command
64
+ else
65
+ yarn_prepare_command
66
+ end
60
67
  end
61
68
 
62
69
  private
63
70
 
71
+ def yarn_prepare_command
72
+ "#{yarn_plugin_production_command}yarn install && yarn plugin import https://raw.githubusercontent.com/mhassan1/yarn-plugin-licenses/#{yarn_licenses_plugin_version}/bundles/@yarnpkg/plugin-licenses.js"
73
+ end
74
+
75
+ def classic_yarn_prepare_command
76
+ "yarn install --ignore-engines --ignore-scripts#{classic_yarn_production_flag}"
77
+ end
78
+
79
+ def yarn_licenses_plugin_version
80
+ if yarn_version == 2
81
+ 'v0.6.0'
82
+ else
83
+ 'v0.7.2'
84
+ end
85
+ end
86
+
87
+ def yarn_version
88
+ Dir.chdir(project_path) do
89
+ version_string, stderr_str, status = Cmd.run('yarn -v')
90
+ raise "Command 'yarn -v' failed to execute: #{stderr_str}" unless status.success?
91
+
92
+ version = version_string.split('.').map(&:to_i)
93
+ return version[0]
94
+ end
95
+ end
96
+
64
97
  def packages_from_json(json_data)
65
98
  body = json_data['body']
66
99
  head = json_data['head']
@@ -98,10 +131,16 @@ module LicenseFinder
98
131
  all_packages - [yarn_internal_package]
99
132
  end
100
133
 
101
- def production_flag
134
+ def classic_yarn_production_flag
102
135
  return '' if @ignored_groups.nil?
103
136
 
104
137
  @ignored_groups.include?('devDependencies') ? ' --production' : ''
105
138
  end
139
+
140
+ def yarn_plugin_production_command
141
+ return '' if @ignored_groups.nil?
142
+
143
+ @ignored_groups.include?('devDependencies') ? 'yarn plugin import workspace-tools && yarn workspaces focus --all --production && ' : ''
144
+ end
106
145
  end
107
146
  end
@@ -4,7 +4,7 @@ require 'license_finder/package_utils/possible_license_file'
4
4
 
5
5
  module LicenseFinder
6
6
  class LicenseFiles
7
- CANDIDATE_FILE_NAMES = %w[License Licence COPYING README].freeze
7
+ CANDIDATE_FILE_NAMES = %w[LICENSE License license LICENCE Licence licence COPYING copying README readme].freeze
8
8
  CANDIDATE_PATH_WILDCARD = "*{#{CANDIDATE_FILE_NAMES.join(',')}}*"
9
9
 
10
10
  def self.find(install_path, options = {})
@@ -35,7 +35,7 @@ module LicenseFinder
35
35
  def candidate_files_and_dirs
36
36
  return [] if install_path.nil?
37
37
 
38
- Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD), File::FNM_CASEFOLD)
38
+ Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD))
39
39
  end
40
40
  end
41
41
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'open-uri'
4
-
5
4
  module LicenseFinder
6
5
  class BowerPackage < Package
7
6
  def initialize(bower_module, options = {})
@@ -35,7 +34,11 @@ module LicenseFinder
35
34
  end
36
35
 
37
36
  def package_url
38
- meta = JSON.parse(open("https://registry.bower.io/packages/#{CGI.escape(name)}").read)
37
+ meta = if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0')
38
+ JSON.parse(open("https://registry.bower.io/packages/#{CGI.escape(name)}").read)
39
+ else
40
+ JSON.parse(URI.open("https://registry.bower.io/packages/#{CGI.escape(name)}").read)
41
+ end
39
42
  meta['url']
40
43
  end
41
44
  end
@@ -37,9 +37,7 @@ module LicenseFinder
37
37
  end
38
38
 
39
39
  def dep_version
40
- @dep_version ||= begin
41
- dep_version_unformatted.sub(version_prefix_re, '')
42
- end
40
+ @dep_version ||= dep_version_unformatted.sub(version_prefix_re, '')
43
41
  end
44
42
 
45
43
  def dep_repo
@@ -88,7 +86,7 @@ module LicenseFinder
88
86
  def dep_version_valid?
89
87
  return false unless set?(dep_version_unformatted)
90
88
 
91
- if dep_version =~ version_re
89
+ if dep_version&.match?(version_re)
92
90
  Gem::Version.correct?(dep_version)
93
91
  else
94
92
  dep_version =~ word_dot_re
@@ -156,6 +156,7 @@ module LicenseFinder
156
156
 
157
157
  class PackageJson
158
158
  attr_reader :groups
159
+
159
160
  DEPENDENCY_GROUPS = %w[dependencies devDependencies].freeze
160
161
 
161
162
  def initialize(path)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class PubPackage < Package
5
+ def initialize(name, version, license_text, options = {})
6
+ super(name, version, options)
7
+ @license = License.find_by_text(license_text.to_s)
8
+ end
9
+
10
+ def licenses_from_spec
11
+ [@license].compact
12
+ end
13
+
14
+ def package_manager
15
+ 'Pub'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class Printer
5
+ attr_reader :padding
6
+
7
+ def initialize #:nodoc:
8
+ @base = nil
9
+ @mute = false
10
+ @padding = 0
11
+ @always_force = false
12
+ end
13
+
14
+ def say(message = '', color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
15
+ buffer = prepare_message(message, *color)
16
+ buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
17
+
18
+ stdout.print(buffer)
19
+ stdout.flush
20
+ end
21
+
22
+ def prepare_message(message, *color)
23
+ spaces = ' ' * padding
24
+ spaces + set_color(message.to_s, *color)
25
+ end
26
+
27
+ def set_color(string, *) #:nodoc:
28
+ string
29
+ end
30
+
31
+ def padding=(value)
32
+ @padding = [0, value].max
33
+ end
34
+
35
+ def stdout
36
+ $stdout
37
+ end
38
+ end
39
+ end
@@ -9,11 +9,12 @@ module LicenseFinder
9
9
  def initialize(dependencies, options)
10
10
  @dependencies = dependencies
11
11
  @project_name = options[:project_name]
12
+ @use_spdx_id = options[:use_spdx_id]
12
13
  end
13
14
 
14
15
  private
15
16
 
16
- attr_reader :dependencies, :project_name
17
+ attr_reader :dependencies, :project_name, :use_spdx_id
17
18
 
18
19
  def sorted_dependencies
19
20
  dependencies.sort
@@ -60,7 +60,7 @@ module LicenseFinder
60
60
  if dep.missing?
61
61
  MISSING_DEPENDENCY_TEXT
62
62
  else
63
- dep.licenses.map(&:name).join(self.class::COMMA_SEP)
63
+ dep.licenses.map(&@use_spdx_id ? :standard_id : :name).join(self.class::COMMA_SEP)
64
64
  end
65
65
  end
66
66
 
@@ -5,7 +5,11 @@ module LicenseFinder
5
5
  TEMPLATE_PATH = ROOT_PATH.join('reports', 'templates')
6
6
 
7
7
  def to_s(filename = TEMPLATE_PATH.join("#{template_name}.erb"))
8
- template = ERB.new(filename.read, nil, '-')
8
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
9
+ template = ERB.new(filename.read, nil, '-')
10
+ else
11
+ template = ERB.new(filename.read, trim_mode: '-')
12
+ end
9
13
  template.result(binding)
10
14
  end
11
15
 
@@ -22,7 +26,7 @@ module LicenseFinder
22
26
  end
23
27
 
24
28
  def link_to_license(license)
25
- link_to_maybe license.name, license.url
29
+ link_to_maybe (@use_spdx_id ? license.standard_id : license.name), license.url
26
30
  end
27
31
 
28
32
  def link_to_dependency(dependency)
@@ -42,7 +46,7 @@ module LicenseFinder
42
46
  end
43
47
 
44
48
  def license_names(dependency)
45
- dependency.licenses.map(&:name).sort.join ', '
49
+ dependency.licenses.map(&@use_spdx_id? :standard_id : :name).sort.join ', '
46
50
  end
47
51
 
48
52
  def license_links(dependency)
@@ -24,7 +24,8 @@ module LicenseFinder
24
24
  end
25
25
 
26
26
  def format_licenses(dep)
27
- dep.missing? ? [] : dep.licenses.map(&:name)
27
+ dep.missing? ? [] :
28
+ dep.licenses.map(&(@use_spdx_id ? :standard_id : :name))
28
29
  end
29
30
  end
30
31
  end
@@ -6,7 +6,11 @@ module LicenseFinder
6
6
  TEMPLATE_PATH = ROOT_PATH.join('templates')
7
7
 
8
8
  def to_s(filename = TEMPLATE_PATH.join("#{template_name}.erb"))
9
- template = ERB.new(filename.read, nil, '-')
9
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
10
+ template = ERB.new(filename.read, nil, '-')
11
+ else
12
+ template = ERB.new(filename.read, trim_mode: '-')
13
+ end
10
14
  template.result(binding)
11
15
  end
12
16
 
@@ -6,7 +6,11 @@ module LicenseFinder
6
6
  TEMPLATE_PATH = ROOT_PATH.join('templates')
7
7
 
8
8
  def to_s(filename = TEMPLATE_PATH.join("#{template_name}.erb"))
9
- template = ERB.new(filename.read, nil, '-')
9
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
10
+ template = ERB.new(filename.read, nil, '-')
11
+ else
12
+ template = ERB.new(filename.read, trim_mode: '-')
13
+ end
10
14
  template.result(binding)
11
15
  end
12
16
 
@@ -5,7 +5,7 @@ module LicenseFinder
5
5
  PACKAGE_MANAGERS = [
6
6
  GoModules, GoDep, GoWorkspace, Go15VendorExperiment, Glide, Gvt, Govendor, Trash, Dep, Bundler, NPM, Pip,
7
7
  Yarn, Bower, Maven, Gradle, CocoaPods, Rebar, Erlangmk, Nuget, Carthage, Mix, Conan, Sbt, Cargo, Dotnet, Composer, Pipenv,
8
- Conda, Spm
8
+ Conda, Spm, Pub
9
9
  ].freeze
10
10
 
11
11
  class << self
@@ -3,7 +3,7 @@
3
3
  version = File.read(File.expand_path('VERSION', __dir__)).strip
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.required_ruby_version = '>= 2.3.3'
6
+ s.required_ruby_version = '>= 2.4.0'
7
7
  s.name = 'license_finder'
8
8
  s.version = version
9
9
 
@@ -45,26 +45,28 @@ Gem::Specification.new do |s|
45
45
 
46
46
  s.add_dependency 'bundler'
47
47
  s.add_dependency 'rubyzip', '>=1', '<3'
48
- s.add_dependency 'thor', '~> 1.0.1'
48
+ s.add_dependency 'thor', '~> 1.2'
49
49
  s.add_dependency 'tomlrb', '>= 1.3', '< 2.1'
50
50
  s.add_dependency 'with_env', '1.1.0'
51
- s.add_dependency 'xml-simple', '~> 1.1.5'
51
+ s.add_dependency 'xml-simple', '~> 1.1.9'
52
52
 
53
53
  s.add_development_dependency 'addressable', '2.8.0'
54
- s.add_development_dependency 'capybara', '~> 3.15.0'
55
- s.add_development_dependency 'cocoapods', '>= 1.0.0' if RUBY_PLATFORM =~ /darwin/
56
- s.add_development_dependency 'fakefs', '~> 1.2.0'
57
- s.add_development_dependency 'mime-types', '3.3.1'
58
- s.add_development_dependency 'pry', '~> 0.14.0'
59
- s.add_development_dependency 'rake', '~> 13.0.1'
54
+ s.add_development_dependency 'capybara', '~> 3.32.2'
55
+ s.add_development_dependency 'cocoapods', '>= 1.0.0' if RUBY_PLATFORM.match?(/darwin/)
56
+ s.add_development_dependency 'e2mmap', '~> 0.1.0'
57
+ s.add_development_dependency 'fakefs', '~> 1.4.1'
58
+ s.add_development_dependency 'matrix', '~> 0.1.0'
59
+ s.add_development_dependency 'mime-types', '3.4.1'
60
+ s.add_development_dependency 'pry', '~> 0.14.1'
61
+ s.add_development_dependency 'rake', '~> 13.0.6'
60
62
  s.add_development_dependency 'rspec', '~> 3'
61
63
  s.add_development_dependency 'rspec-its', '~> 1.3.0'
62
- s.add_development_dependency 'rubocop', '~> 0.81.0'
63
- s.add_development_dependency 'rubocop-performance', '~> 1.5.0'
64
- s.add_development_dependency 'webmock', '~> 3.5'
64
+ s.add_development_dependency 'rubocop', '~> 1.12.1'
65
+ s.add_development_dependency 'rubocop-performance', '~> 1.10.2'
66
+ s.add_development_dependency 'webmock', '~> 3.14'
65
67
 
66
68
  s.add_development_dependency 'nokogiri', '~>1.10'
67
- s.add_development_dependency 'rack', '~> 2.2.2'
69
+ s.add_development_dependency 'rack', '~> 2.2.3'
68
70
  s.add_development_dependency 'rack-test', '~> 1.1.0', '> 0.7'
69
71
 
70
72
  s.files = `git ls-files`.split("\n").reject { |f| f.start_with?('spec', 'features') }