dependabot-bundler 0.331.0 → 0.332.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: 0d913e03bbafff1bf6a1e905d3f6102572f398f2231748e7f3dc431cf67dae8b
4
- data.tar.gz: df7093e86cc83e024a6d6527fa6b8e1b180e1db936a7ae98f216e537a7561600
3
+ metadata.gz: 0373cdfce669d8fb9d4fb6081a0b2660c58217e1c309cbc49e772971ba5f9f1a
4
+ data.tar.gz: f0a48edc13f2826d1177be53e368fb9bb9957d50f53bfb1ecdf62b7dc3a13b34
5
5
  SHA512:
6
- metadata.gz: ae5d37a7e93a31327fd166a9f491bcc032a77e739b45de5e0abf306c4f0cd0c9a5c09036ebad1540c88b539ede05abb0164f185c5434144db81d003279a43320
7
- data.tar.gz: fb3c5408c9a52a44df3caa36cd962bf29aa9ecca9d2ffec30d0a23ba5e58c743db813c072b5864bc273675b48c8bca28700b48e7c4adc8b410d7115aff97d0d5
6
+ metadata.gz: f259e4c088e2e8ccbf1a343e216b606681c4e40538a5aa6306fb508b176904467bbaaeeb9f73a8050e16c14d249204be42444640f1f0485f0da45c4127fdf468
7
+ data.tar.gz: e0a5c41f18681d4db017a5c6e28646739af2315d89a59e937ad2fee2a6078fb6d48b00c8da8652324616640c95ef740b683442b3bbd2059a77178aa0c9475632
@@ -122,21 +122,17 @@ module Dependabot
122
122
  parsed_gemfile.each do |dep|
123
123
  next unless gemfile_declaration_finder.gemfile_includes_dependency?(dep)
124
124
 
125
- dep =
126
- Dependency.new(
127
- name: dep.fetch("name"),
128
- version: dependency_version(dep.fetch("name"))&.to_s,
129
- requirements: [{
130
- requirement: gemfile_declaration_finder.enhanced_req_string(dep),
131
- groups: dep.fetch("groups").map(&:to_sym),
132
- source: dep.fetch("source")&.transform_keys(&:to_sym),
133
- file: file.name
134
- }],
135
- package_manager: "bundler"
136
- )
137
-
138
- file.dependencies << dep
139
- dependencies << dep
125
+ dependencies << Dependency.new(
126
+ name: dep.fetch("name"),
127
+ version: dependency_version(dep.fetch("name"))&.to_s,
128
+ requirements: [{
129
+ requirement: gemfile_declaration_finder.enhanced_req_string(dep),
130
+ groups: dep.fetch("groups").map(&:to_sym),
131
+ source: dep.fetch("source")&.transform_keys(&:to_sym),
132
+ file: file.name
133
+ }],
134
+ package_manager: "bundler"
135
+ )
140
136
  end
141
137
  end
142
138
 
@@ -144,7 +140,7 @@ module Dependabot
144
140
  end
145
141
 
146
142
  sig { returns(DependencySet) }
147
- def gemspec_dependencies # rubocop:disable Metrics/PerceivedComplexity,Metrics/AbcSize
143
+ def gemspec_dependencies # rubocop:disable Metrics/PerceivedComplexity
148
144
  @gemspec_dependencies = T.let(@gemspec_dependencies, T.nilable(DependencySet))
149
145
  return @gemspec_dependencies if @gemspec_dependencies
150
146
 
@@ -159,7 +155,7 @@ module Dependabot
159
155
  parsed_gemspec(gemspec).each do |dependency|
160
156
  next unless gemspec_declaration_finder.gemspec_includes_dependency?(dependency)
161
157
 
162
- dep = Dependency.new(
158
+ queue << Dependency.new(
163
159
  name: dependency.fetch("name"),
164
160
  version: dependency_version(dependency.fetch("name"))&.to_s,
165
161
  requirements: [{
@@ -174,9 +170,6 @@ module Dependabot
174
170
  }],
175
171
  package_manager: "bundler"
176
172
  )
177
-
178
- gemspec.dependencies << dep
179
- queue << dep
180
173
  end
181
174
  end
182
175
  end
@@ -198,23 +191,15 @@ module Dependabot
198
191
  parsed_lockfile.specs.each do |dependency|
199
192
  next if dependency.source.is_a?(::Bundler::Source::Path)
200
193
 
201
- # if a dependency is listed in the lockfiles' DEPENDENCIES section,
202
- # then it is a direct dependency & we want to keep track of that fact
203
- is_direct = parsed_lockfile.dependencies.key?(dependency.name)
204
-
205
- dep = Dependency.new(
194
+ dependencies << Dependency.new(
206
195
  name: dependency.name,
207
196
  version: dependency_version(dependency.name)&.to_s,
208
197
  requirements: [],
209
198
  package_manager: "bundler",
210
199
  subdependency_metadata: [{
211
200
  production: production_dep_names.include?(dependency.name)
212
- }],
213
- direct_relationship: is_direct
201
+ }]
214
202
  )
215
-
216
- T.must(lockfile).dependencies << dep
217
- dependencies << dep
218
203
  end
219
204
 
220
205
  dependencies
@@ -357,10 +342,6 @@ module Dependabot
357
342
  get_original_file("Gemfile.lock") || get_original_file("gems.locked"),
358
343
  T.nilable(Dependabot::DependencyFile)
359
344
  )
360
-
361
- # Set the lockfile as higher priority so we know to ignore the Gemfile, etc
362
- # when producing a graph.
363
- @lockfile&.tap { |f| f.priority = 1 }
364
345
  end
365
346
 
366
347
  sig { returns(T.untyped) }
@@ -43,17 +43,25 @@ module Dependabot
43
43
  @credentials = credentials
44
44
 
45
45
  @source_type = T.let(nil, T.nilable(String))
46
+ @options = T.let({}, T::Hash[Symbol, T.untyped])
47
+ @repo_contents_path = T.let(nil, T.nilable(String))
46
48
  end
47
49
 
48
50
  sig { returns(Dependabot::Dependency) }
49
51
  attr_reader :dependency
50
52
 
51
- sig { returns(T::Array[T.untyped]) }
53
+ sig { override.returns(T::Array[T.untyped]) }
52
54
  attr_reader :dependency_files
53
55
 
54
- sig { returns(T::Array[T.untyped]) }
56
+ sig { override.returns(T::Array[T.untyped]) }
55
57
  attr_reader :credentials
56
58
 
59
+ sig { override.returns(T::Hash[Symbol, T.untyped]) }
60
+ attr_reader :options
61
+
62
+ sig { override.returns(T.nilable(String)) }
63
+ attr_reader :repo_contents_path
64
+
57
65
  sig { returns(Dependabot::Package::PackageDetails) }
58
66
  def fetch
59
67
  case source_type
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/bundler/update_checker"
@@ -10,11 +10,33 @@ module Dependabot
10
10
  module Bundler
11
11
  class UpdateChecker < UpdateCheckers::Base
12
12
  class ConflictingDependencyResolver
13
+ extend T::Sig
14
+
13
15
  require_relative "shared_bundler_helpers"
16
+
14
17
  include SharedBundlerHelpers
15
18
 
19
+ sig { override.returns(T::Hash[Symbol, T.untyped]) }
16
20
  attr_reader :options
17
21
 
22
+ sig { override.returns(T::Array[Dependabot::Credential]) }
23
+ attr_reader :credentials
24
+
25
+ sig { override.returns(T::Array[Dependabot::DependencyFile]) }
26
+ attr_reader :dependency_files
27
+
28
+ sig { override.returns(T.nilable(String)) }
29
+ attr_reader :repo_contents_path
30
+
31
+ sig do
32
+ params(
33
+ dependency_files: T::Array[Dependabot::DependencyFile],
34
+ repo_contents_path: T.nilable(String),
35
+ credentials: T::Array[Dependabot::Credential],
36
+ options: T::Hash[Symbol, T.untyped]
37
+ )
38
+ .void
39
+ end
18
40
  def initialize(dependency_files:, repo_contents_path:, credentials:, options:)
19
41
  @dependency_files = dependency_files
20
42
  @repo_contents_path = repo_contents_path
@@ -31,6 +53,13 @@ module Dependabot
31
53
  # * name [String] the blocking dependencies name
32
54
  # * version [String] the version of the blocking dependency
33
55
  # * requirement [String] the requirement on the target_dependency
56
+ sig do
57
+ params(
58
+ dependency: Dependabot::Dependency,
59
+ target_version: String
60
+ )
61
+ .returns(T::Array[T::Hash[String, String]])
62
+ end
34
63
  def conflicting_dependencies(dependency:, target_version:)
35
64
  return [] if lockfile.nil?
36
65
 
@@ -44,7 +73,7 @@ module Dependabot
44
73
  dependency_name: dependency.name,
45
74
  target_version: target_version,
46
75
  credentials: credentials,
47
- lockfile_name: lockfile.name
76
+ lockfile_name: T.must(lockfile).name
48
77
  }
49
78
  )
50
79
  end
@@ -52,8 +81,12 @@ module Dependabot
52
81
 
53
82
  private
54
83
 
84
+ sig { override.returns(String) }
55
85
  def bundler_version
56
- @bundler_version ||= Helpers.bundler_version(lockfile)
86
+ @bundler_version ||= T.let(
87
+ Helpers.bundler_version(lockfile),
88
+ T.nilable(String)
89
+ )
57
90
  end
58
91
  end
59
92
  end
@@ -1,6 +1,7 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
4
5
  require "dependabot/bundler/file_parser"
5
6
  require "dependabot/bundler/file_updater/lockfile_updater"
6
7
  require "dependabot/bundler/native_helpers"
@@ -14,14 +15,28 @@ module Dependabot
14
15
  module Bundler
15
16
  class UpdateChecker
16
17
  class ForceUpdater
18
+ extend T::Sig
19
+
17
20
  require_relative "shared_bundler_helpers"
21
+
18
22
  include SharedBundlerHelpers
19
23
 
20
- def initialize(dependency:, dependency_files:, repo_contents_path: nil,
21
- credentials:, target_version:,
22
- requirements_update_strategy:,
23
- update_multiple_dependencies: true,
24
- options:)
24
+ sig do
25
+ params(
26
+ dependency: Dependabot::Dependency,
27
+ dependency_files: T::Array[Dependabot::DependencyFile],
28
+ credentials: T::Array[Dependabot::Credential],
29
+ target_version: Dependabot::Version,
30
+ requirements_update_strategy: Dependabot::RequirementsUpdateStrategy,
31
+ options: T::Hash[Symbol, T.untyped],
32
+ repo_contents_path: T.nilable(String),
33
+ update_multiple_dependencies: T::Boolean
34
+ ).void
35
+ end
36
+ def initialize(dependency:, dependency_files:, credentials:, target_version:,
37
+ requirements_update_strategy:, options:,
38
+ repo_contents_path: nil,
39
+ update_multiple_dependencies: true)
25
40
  @dependency = dependency
26
41
  @dependency_files = dependency_files
27
42
  @repo_contents_path = repo_contents_path
@@ -30,28 +45,50 @@ module Dependabot
30
45
  @requirements_update_strategy = requirements_update_strategy
31
46
  @update_multiple_dependencies = update_multiple_dependencies
32
47
  @options = options
48
+
49
+ @updated_dependencies = T.let(nil, T.nilable(T::Array[Dependabot::Dependency]))
50
+ @original_dependencies = T.let(nil, T.nilable(T::Array[Dependabot::Dependency]))
51
+ @bundler_version = T.let(nil, T.nilable(String))
33
52
  end
34
53
 
54
+ sig { returns(T::Array[Dependabot::Dependency]) }
35
55
  def updated_dependencies
36
56
  @updated_dependencies ||= force_update
37
57
  end
38
58
 
39
- private
40
-
41
- attr_reader :dependency
59
+ # Abstract method implementations
60
+ sig { override.returns(T::Array[Dependabot::DependencyFile]) }
42
61
  attr_reader :dependency_files
62
+
63
+ sig { override.returns(T.nilable(String)) }
43
64
  attr_reader :repo_contents_path
65
+
66
+ sig { override.returns(T::Array[Dependabot::Credential]) }
44
67
  attr_reader :credentials
68
+
69
+ sig { override.returns(T::Hash[Symbol, T.untyped]) }
70
+ attr_reader :options
71
+
72
+ private
73
+
74
+ sig { returns(Dependabot::Dependency) }
75
+ attr_reader :dependency
76
+
77
+ sig { returns(Dependabot::Version) }
45
78
  attr_reader :target_version
79
+
80
+ sig { returns(Dependabot::RequirementsUpdateStrategy) }
46
81
  attr_reader :requirements_update_strategy
47
- attr_reader :options
48
82
 
83
+ sig { returns(T::Boolean) }
49
84
  def update_multiple_dependencies?
50
85
  @update_multiple_dependencies
51
86
  end
52
87
 
88
+ # rubocop:disable Metrics/AbcSize
89
+ sig { returns(T::Array[Dependabot::Dependency]) }
53
90
  def force_update
54
- requirement = dependency.requirements.find { |req| req[:file] == gemfile.name }
91
+ requirement = dependency.requirements.find { |req| req[:file] == T.must(gemfile).name }
55
92
 
56
93
  valid_gem_version?(target_version)
57
94
 
@@ -71,8 +108,8 @@ module Dependabot
71
108
  dependency_name: dependency.name,
72
109
  target_version: target_version,
73
110
  credentials: credentials,
74
- gemfile_name: gemfile.name,
75
- lockfile_name: lockfile.name,
111
+ gemfile_name: T.must(gemfile).name,
112
+ lockfile_name: T.must(lockfile).name,
76
113
  update_multiple_dependencies: update_multiple_dependencies?
77
114
  }
78
115
  )
@@ -82,7 +119,9 @@ module Dependabot
82
119
  raise Dependabot::DependencyFileNotResolvable, msg
83
120
  end
84
121
  end
122
+ # rubocop:enable Metrics/AbcSize
85
123
 
124
+ sig { params(target_version: T.nilable(Dependabot::Version)).returns(TrueClass) }
86
125
  def valid_gem_version?(target_version)
87
126
  # to rule out empty, non gem info ending up in as target_version
88
127
  return true if target_version.is_a?(Gem::Version)
@@ -92,6 +131,7 @@ module Dependabot
92
131
  raise Dependabot::DependencyFileNotResolvable
93
132
  end
94
133
 
134
+ sig { returns(T::Array[Dependabot::Dependency]) }
95
135
  def original_dependencies
96
136
  @original_dependencies ||=
97
137
  FileParser.new(
@@ -101,6 +141,13 @@ module Dependabot
101
141
  ).parse
102
142
  end
103
143
 
144
+ sig do
145
+ params(
146
+ updated_deps: T::Array[T::Hash[String, T.untyped]],
147
+ specs: T::Array[T::Hash[String, T.untyped]]
148
+ )
149
+ .returns(T::Array[Dependabot::Dependency])
150
+ end
104
151
  def dependencies_from(updated_deps, specs)
105
152
  # You might think we'd want to remove dependencies whose version
106
153
  # hadn't changed from this array. We don't. We still need to unlock
@@ -114,12 +161,13 @@ module Dependabot
114
161
  original_dependencies.find { |d| d.name == dep.fetch("name") }
115
162
  spec = specs.find { |d| d.fetch("name") == dep.fetch("name") }
116
163
 
117
- next if spec.fetch("version") == original_dep.version
164
+ next if T.must(spec).fetch("version") == T.must(original_dep).version
118
165
 
119
166
  build_dependency(original_dep, spec)
120
167
  end
121
168
  end
122
169
 
170
+ sig { params(original_dep: T.untyped, updated_spec: T.untyped).returns(Dependabot::Dependency) }
123
171
  def build_dependency(original_dep, updated_spec)
124
172
  Dependency.new(
125
173
  name: updated_spec.fetch("name"),
@@ -138,27 +186,32 @@ module Dependabot
138
186
  )
139
187
  end
140
188
 
189
+ sig { params(dependency: Dependabot::Dependency).returns(T.nilable(T::Hash[String, T.untyped])) }
141
190
  def source_for(dependency)
142
191
  dependency.requirements
143
192
  .find { |r| r.fetch(:source) }
144
193
  &.fetch(:source)
145
194
  end
146
195
 
196
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
147
197
  def gemfile
148
198
  dependency_files.find { |f| f.name == "Gemfile" } ||
149
199
  dependency_files.find { |f| f.name == "gems.rb" }
150
200
  end
151
201
 
202
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
152
203
  def lockfile
153
204
  dependency_files.find { |f| f.name == "Gemfile.lock" } ||
154
205
  dependency_files.find { |f| f.name == "gems.locked" }
155
206
  end
156
207
 
208
+ sig { returns(String) }
157
209
  def sanitized_lockfile_body
158
210
  re = FileUpdater::LockfileUpdater::LOCKFILE_ENDING
159
- lockfile.content.gsub(re, "")
211
+ T.must(T.must(lockfile).content).gsub(re, "")
160
212
  end
161
213
 
214
+ sig { void }
162
215
  def write_temporary_dependency_files
163
216
  dependency_files.each do |file|
164
217
  path = file.name
@@ -166,9 +219,10 @@ module Dependabot
166
219
  File.write(path, file.content)
167
220
  end
168
221
 
169
- File.write(lockfile.name, sanitized_lockfile_body) if lockfile
222
+ File.write(T.must(lockfile).name, sanitized_lockfile_body) if lockfile
170
223
  end
171
224
 
225
+ sig { override.returns(String) }
172
226
  def bundler_version
173
227
  @bundler_version ||= Helpers.bundler_version(lockfile)
174
228
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "excon"
@@ -23,8 +23,17 @@ module Dependabot
23
23
 
24
24
  abstract!
25
25
 
26
- sig { returns(T::Hash[Symbol, T.untyped]) }
27
- attr_reader :options
26
+ sig { abstract.returns(T::Hash[Symbol, T.untyped]) }
27
+ def options; end
28
+
29
+ sig { abstract.returns(T::Array[Dependabot::DependencyFile]) }
30
+ def dependency_files; end
31
+
32
+ sig { abstract.returns(T.nilable(String)) }
33
+ def repo_contents_path; end
34
+
35
+ sig { abstract.returns(T::Array[Dependabot::Credential]) }
36
+ def credentials; end
28
37
 
29
38
  GIT_REGEX = /reset --hard [^\s]*` in directory (?<path>[^\s]*)/
30
39
  GIT_REF_REGEX = /not exist in the repository (?<path>[^\s]*)\./
@@ -51,21 +60,24 @@ module Dependabot
51
60
  Bundler::Fetcher::FallbackError
52
61
  ).freeze
53
62
 
54
- attr_reader :dependency_files
55
- attr_reader :repo_contents_path
56
- attr_reader :credentials
57
-
58
63
  #########################
59
64
  # Bundler context setup #
60
65
  #########################
61
66
 
62
- def in_a_native_bundler_context(error_handling: true)
67
+ sig do
68
+ params(
69
+ error_handling: T::Boolean,
70
+ _blk: T.proc.params(arg0: String).returns(T.untyped)
71
+ )
72
+ .returns(T.untyped)
73
+ end
74
+ def in_a_native_bundler_context(error_handling: true, &_blk)
63
75
  SharedHelpers
64
76
  .in_a_temporary_repo_directory(base_directory,
65
77
  repo_contents_path) do |tmp_dir|
66
78
  write_temporary_dependency_files
67
79
 
68
- yield(tmp_dir)
80
+ yield(tmp_dir.to_s)
69
81
  end
70
82
  rescue SharedHelpers::HelperSubprocessFailed => e
71
83
  retry_count ||= 0
@@ -75,10 +87,12 @@ module Dependabot
75
87
  error_handling ? handle_bundler_errors(e) : raise
76
88
  end
77
89
 
90
+ sig { returns(String) }
78
91
  def base_directory
79
- dependency_files.first.directory
92
+ T.must(dependency_files.first).directory
80
93
  end
81
94
 
95
+ sig { params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
82
96
  def retryable_error?(error)
83
97
  return true if error.error_class == "JSON::ParserError"
84
98
  return true if RETRYABLE_ERRORS.include?(error.error_class)
@@ -92,6 +106,7 @@ module Dependabot
92
106
  # rubocop:disable Metrics/PerceivedComplexity
93
107
  # rubocop:disable Metrics/AbcSize
94
108
  # rubocop:disable Metrics/MethodLength
109
+ sig { params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).void }
95
110
  def handle_bundler_errors(error)
96
111
  if error.error_class == "JSON::ParserError"
97
112
  msg = "Error evaluating your dependency files: #{error.message}"
@@ -105,25 +120,22 @@ module Dependabot
105
120
  # We couldn't evaluate the Gemfile, let alone resolve it
106
121
  raise Dependabot::DependencyFileNotEvaluatable, msg
107
122
  when "Bundler::Source::Git::MissingGitRevisionError"
108
- gem_name =
109
- error.message.match(GIT_REF_REGEX)
110
- .named_captures["path"]
111
- .split("/").last
112
- raise GitDependencyReferenceNotFound, gem_name
123
+ match_data = error.message.match(GIT_REF_REGEX)
124
+ gem_name = T.must(T.must(match_data).named_captures["path"])
125
+ .split("/").last
126
+ raise GitDependencyReferenceNotFound, T.must(gem_name)
113
127
  when "Bundler::PathError"
114
- gem_name =
115
- error.message.match(PATH_REGEX)
116
- .named_captures["path"]
117
- .split("/").last.split("-")[0..-2].join
128
+ match_data = error.message.match(PATH_REGEX)
129
+ path = T.must(T.must(match_data).named_captures["path"])
130
+ gem_name = T.must(T.must(path.split("/").last).split("-")[0..-2]).join
118
131
  raise Dependabot::PathDependenciesNotReachable, [gem_name]
119
132
  when "Bundler::Source::Git::GitCommandError"
120
133
  if error.message.match?(GIT_REGEX)
121
134
  # We couldn't find the specified branch / commit (or the two
122
135
  # weren't compatible).
123
- gem_name =
124
- error.message.match(GIT_REGEX)
125
- .named_captures["path"]
126
- .split("/").last.split("-")[0..-2].join
136
+ match_data = error.message.match(GIT_REGEX)
137
+ path = T.must(T.must(match_data).named_captures["path"])
138
+ gem_name = T.must(T.must(path.split("/").last).split("-")[0..-2]).join
127
139
  raise GitDependencyReferenceNotFound, gem_name
128
140
  end
129
141
 
@@ -144,24 +156,24 @@ module Dependabot
144
156
  raise Dependabot::DependencyFileNotResolvable, msg
145
157
  when "Bundler::Fetcher::AuthenticationRequiredError"
146
158
  regex = BundlerErrorPatterns::MISSING_AUTH_REGEX
147
- source = error.message.match(regex)[:source]
159
+ source = T.must(T.must(error.message.match(regex))[:source])
148
160
  raise Dependabot::PrivateSourceAuthenticationFailure, source
149
161
  when "Bundler::Fetcher::AuthenticationForbiddenError"
150
162
  regex = BundlerErrorPatterns::FORBIDDEN_AUTH_REGEX
151
- source = error.message.match(regex)[:source]
163
+ source = T.must(T.must(error.message.match(regex))[:source])
152
164
  raise Dependabot::PrivateSourceAuthenticationFailure, source
153
165
  when "Bundler::Fetcher::BadAuthenticationError"
154
166
  regex = BundlerErrorPatterns::BAD_AUTH_REGEX
155
- source = error.message.match(regex)[:source]
167
+ source = T.must(T.must(error.message.match(regex))[:source])
156
168
  raise Dependabot::PrivateSourceAuthenticationFailure, source
157
169
  when "Bundler::Fetcher::CertificateFailureError"
158
170
  regex = BundlerErrorPatterns::BAD_CERT_REGEX
159
- source = error.message.match(regex)[:source]
171
+ source = T.must(T.must(error.message.match(regex))[:source])
160
172
  raise Dependabot::PrivateSourceCertificateFailure, source
161
173
  when "Bundler::HTTPError"
162
174
  regex = BundlerErrorPatterns::HTTP_ERR_REGEX
163
175
  if error.message.match?(regex)
164
- source = error.message.match(regex)[:source]
176
+ source = T.must(T.must(error.message.match(regex))[:source])
165
177
  raise if [
166
178
  "rubygems.org",
167
179
  "www.rubygems.org"
@@ -184,6 +196,7 @@ module Dependabot
184
196
  # rubocop:enable Metrics/AbcSize
185
197
  # rubocop:enable Metrics/MethodLength
186
198
 
199
+ sig { returns(T::Array[T::Hash[String, T.untyped]]) }
187
200
  def inaccessible_git_dependencies
188
201
  in_a_native_bundler_context(error_handling: false) do |tmp_dir|
189
202
  git_specs = NativeHelpers.run_bundler_subprocess(
@@ -192,7 +205,7 @@ module Dependabot
192
205
  options: options,
193
206
  args: {
194
207
  dir: tmp_dir,
195
- gemfile_name: gemfile.name,
208
+ gemfile_name: T.must(gemfile).name,
196
209
  credentials: credentials
197
210
  }
198
211
  )
@@ -210,8 +223,10 @@ module Dependabot
210
223
  end
211
224
  end
212
225
 
226
+ sig { returns(T.nilable(String)) }
213
227
  def jfrog_source
214
- return @jfrog_source unless defined?(@jfrog_source)
228
+ @jfrog_source = T.let(@jfrog_source, T.nilable(String)) if @jfrog_source.nil?
229
+ return @jfrog_source unless @jfrog_source.nil?
215
230
 
216
231
  @jfrog_source = in_a_native_bundler_context(error_handling: false) do |dir|
217
232
  NativeHelpers.run_bundler_subprocess(
@@ -220,16 +235,14 @@ module Dependabot
220
235
  options: options,
221
236
  args: {
222
237
  dir: dir,
223
- gemfile_name: gemfile.name,
238
+ gemfile_name: T.must(gemfile).name,
224
239
  credentials: credentials
225
240
  }
226
241
  )
227
242
  end
228
243
  end
229
244
 
230
- sig { abstract.returns(String) }
231
- def bundler_version; end
232
-
245
+ sig { void }
233
246
  def write_temporary_dependency_files
234
247
  dependency_files.each do |file|
235
248
  path = file.name
@@ -237,23 +250,32 @@ module Dependabot
237
250
  File.write(path, file.content)
238
251
  end
239
252
 
240
- File.write(lockfile.name, lockfile.content) if lockfile
253
+ lockfile_obj = lockfile
254
+ File.write(lockfile_obj.name, lockfile_obj.content) if lockfile_obj
241
255
  end
242
256
 
257
+ sig { returns(T::Array[Dependabot::Credential]) }
243
258
  def private_registry_credentials
244
259
  credentials
245
260
  .select { |cred| cred["type"] == "rubygems_server" }
246
261
  end
247
262
 
263
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
248
264
  def gemfile
249
265
  dependency_files.find { |f| f.name == "Gemfile" } ||
250
266
  dependency_files.find { |f| f.name == "gems.rb" }
251
267
  end
252
268
 
269
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
253
270
  def lockfile
254
271
  dependency_files.find { |f| f.name == "Gemfile.lock" } ||
255
272
  dependency_files.find { |f| f.name == "gems.locked" }
256
273
  end
274
+
275
+ private
276
+
277
+ sig { abstract.returns(String) }
278
+ def bundler_version; end
257
279
  end
258
280
  end
259
281
  end
@@ -1,7 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "excon"
5
+ require "sorbet-runtime"
5
6
 
6
7
  require "dependabot/bundler/helpers"
7
8
  require "dependabot/bundler/update_checker"
@@ -15,19 +16,36 @@ module Dependabot
15
16
  module Bundler
16
17
  class UpdateChecker
17
18
  class VersionResolver
19
+ extend T::Sig
20
+
18
21
  require_relative "file_preparer"
19
22
  require_relative "latest_version_finder"
20
23
  require_relative "shared_bundler_helpers"
21
24
  include SharedBundlerHelpers
22
25
 
23
- def initialize(dependency:, unprepared_dependency_files:,
24
- repo_contents_path: nil, credentials:, ignored_versions:,
26
+ sig do
27
+ params(
28
+ dependency: Dependabot::Dependency,
29
+ unprepared_dependency_files: T::Array[Dependabot::DependencyFile],
30
+ credentials: T::Array[Dependabot::Credential],
31
+ ignored_versions: T::Array[String],
32
+ options: T::Hash[Symbol, T.untyped],
33
+ repo_contents_path: T.nilable(String),
34
+ raise_on_ignored: T::Boolean,
35
+ replacement_git_pin: T.nilable(String),
36
+ remove_git_source: T::Boolean,
37
+ unlock_requirement: T::Boolean,
38
+ latest_allowable_version: T.nilable(T.any(String, Dependabot::Version)),
39
+ cooldown_options: T.nilable(Dependabot::Package::ReleaseCooldownOptions)
40
+ ).void
41
+ end
42
+ def initialize(dependency:, unprepared_dependency_files:, credentials:, ignored_versions:, options:,
43
+ repo_contents_path: nil,
25
44
  raise_on_ignored: false,
26
45
  replacement_git_pin: nil, remove_git_source: false,
27
46
  unlock_requirement: true,
28
47
  latest_allowable_version: nil,
29
- cooldown_options: nil,
30
- options:)
48
+ cooldown_options: nil)
31
49
  @dependency = dependency
32
50
  @unprepared_dependency_files = unprepared_dependency_files
33
51
  @credentials = credentials
@@ -41,50 +59,77 @@ module Dependabot
41
59
  @cooldown_options = cooldown_options
42
60
  @options = options
43
61
 
44
- @latest_allowable_version_incompatible_with_ruby = false
62
+ @latest_allowable_version_incompatible_with_ruby = T.let(false, T::Boolean)
63
+ @latest_resolvable_version_details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped]))
64
+ @dependency_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
65
+ @latest_version_details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped]))
66
+ @gemspec_ruby_unlocked = T.let(false, T::Boolean)
67
+ @bundler_version = T.let(nil, T.nilable(String))
45
68
  end
46
69
 
70
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
47
71
  def latest_resolvable_version_details
48
72
  @latest_resolvable_version_details ||=
49
73
  fetch_latest_resolvable_version_details
50
74
  end
51
75
 
76
+ sig { returns(T::Boolean) }
52
77
  def latest_allowable_version_incompatible_with_ruby?
53
78
  @latest_allowable_version_incompatible_with_ruby
54
79
  end
55
80
 
81
+ # Abstract method implementations
82
+ sig { override.returns(T::Hash[Symbol, T.untyped]) }
83
+ attr_reader :options
84
+
85
+ sig { override.returns(T::Array[Dependabot::DependencyFile]) }
86
+ def dependency_files
87
+ @dependency_files ||=
88
+ FilePreparer.new(
89
+ dependency: dependency,
90
+ dependency_files: unprepared_dependency_files,
91
+ replacement_git_pin: replacement_git_pin,
92
+ remove_git_source: remove_git_source?,
93
+ unlock_requirement: unlock_requirement?,
94
+ latest_allowable_version: latest_allowable_version
95
+ ).prepared_dependency_files
96
+ end
97
+
98
+ sig { override.returns(T.nilable(String)) }
99
+ attr_reader :repo_contents_path
100
+
101
+ sig { override.returns(T::Array[Dependabot::Credential]) }
102
+ attr_reader :credentials
103
+
56
104
  private
57
105
 
106
+ sig { returns(Dependabot::Dependency) }
58
107
  attr_reader :dependency
108
+
109
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
59
110
  attr_reader :unprepared_dependency_files
60
- attr_reader :repo_contents_path
61
- attr_reader :credentials
111
+
112
+ sig { returns(T::Array[String]) }
62
113
  attr_reader :ignored_versions
114
+
115
+ sig { returns(T.nilable(String)) }
63
116
  attr_reader :replacement_git_pin
117
+
118
+ sig { returns(T.nilable(T.any(String, Dependabot::Version))) }
64
119
  attr_reader :latest_allowable_version
65
- attr_reader :options
66
120
 
121
+ sig { returns(T::Boolean) }
67
122
  def remove_git_source?
68
123
  @remove_git_source
69
124
  end
70
125
 
126
+ sig { returns(T::Boolean) }
71
127
  def unlock_requirement?
72
128
  @unlock_requirement
73
129
  end
74
130
 
75
- def dependency_files
76
- @dependency_files ||=
77
- FilePreparer.new(
78
- dependency: dependency,
79
- dependency_files: unprepared_dependency_files,
80
- replacement_git_pin: replacement_git_pin,
81
- remove_git_source: remove_git_source?,
82
- unlock_requirement: unlock_requirement?,
83
- latest_allowable_version: latest_allowable_version
84
- ).prepared_dependency_files
85
- end
86
-
87
131
  # rubocop:disable Metrics/PerceivedComplexity
132
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
88
133
  def fetch_latest_resolvable_version_details
89
134
  return latest_version_details unless gemfile
90
135
 
@@ -100,7 +145,7 @@ module Dependabot
100
145
  args: {
101
146
  dependency_name: dependency.name,
102
147
  dependency_requirements: dependency.requirements,
103
- gemfile_name: gemfile.name,
148
+ gemfile_name: T.must(gemfile).name,
104
149
  lockfile_name: lockfile&.name,
105
150
  dir: tmp_dir,
106
151
  credentials: credentials
@@ -136,12 +181,14 @@ module Dependabot
136
181
  end
137
182
  # rubocop:enable Metrics/PerceivedComplexity
138
183
 
184
+ sig { params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
139
185
  def circular_dependency_at_new_version?(error)
140
186
  return false unless error.error_class.include?("CyclicDependencyError")
141
187
 
142
188
  error.message.include?("'#{dependency.name}'")
143
189
  end
144
190
 
191
+ sig { params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
145
192
  def error_due_to_restrictive_upper_bound?(error)
146
193
  # We see this when the dependency doesn't appear in the lockfile and
147
194
  # has an overly restrictive upper bound that we've added, either due
@@ -152,6 +199,7 @@ module Dependabot
152
199
  error.message.include?("#{dependency.name} ")
153
200
  end
154
201
 
202
+ sig { params(error: T.untyped).returns(T::Boolean) }
155
203
  def ruby_lock_error?(error)
156
204
  return false unless conflict_on_ruby?(error)
157
205
  return false if @gemspec_ruby_unlocked
@@ -159,6 +207,7 @@ module Dependabot
159
207
  dependency_files.any? { |f| f.name.end_with?(".gemspec") }
160
208
  end
161
209
 
210
+ sig { params(error: Dependabot::SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
162
211
  def conflict_on_ruby?(error)
163
212
  if bundler_version == "1"
164
213
  error.message.include?(" for gem \"ruby\0\"")
@@ -167,6 +216,7 @@ module Dependabot
167
216
  end
168
217
  end
169
218
 
219
+ sig { returns(T::Boolean) }
170
220
  def regenerate_dependency_files_without_ruby_lock
171
221
  @dependency_files =
172
222
  FilePreparer.new(
@@ -178,8 +228,10 @@ module Dependabot
178
228
  latest_allowable_version: latest_allowable_version,
179
229
  lock_ruby_version: false
180
230
  ).prepared_dependency_files
231
+ true
181
232
  end
182
233
 
234
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
183
235
  def latest_version_details
184
236
  @latest_version_details ||=
185
237
  LatestVersionFinder.new(
@@ -194,6 +246,7 @@ module Dependabot
194
246
  ).latest_version_details
195
247
  end
196
248
 
249
+ sig { params(details: T.untyped).returns(T::Boolean) }
197
250
  def ruby_version_incompatible?(details)
198
251
  # It's only the old index we have a problem with
199
252
  return false unless details[:fetcher] == "Bundler::Fetcher::Dependency"
@@ -231,16 +284,19 @@ module Dependabot
231
284
  false
232
285
  end
233
286
 
287
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
234
288
  def gemfile
235
289
  dependency_files.find { |f| f.name == "Gemfile" } ||
236
290
  dependency_files.find { |f| f.name == "gems.rb" }
237
291
  end
238
292
 
293
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
239
294
  def lockfile
240
295
  dependency_files.find { |f| f.name == "Gemfile.lock" } ||
241
296
  dependency_files.find { |f| f.name == "gems.locked" }
242
297
  end
243
298
 
299
+ sig { override.returns(String) }
244
300
  def bundler_version
245
301
  @bundler_version ||= Helpers.bundler_version(lockfile)
246
302
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.331.0
4
+ version: 0.332.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.331.0
18
+ version: 0.332.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.331.0
25
+ version: 0.332.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: parallel
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -322,7 +322,7 @@ licenses:
322
322
  - MIT
323
323
  metadata:
324
324
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
325
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.331.0
325
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.332.0
326
326
  rdoc_options: []
327
327
  require_paths:
328
328
  - lib