dependabot-bundler 0.331.0 → 0.333.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 +4 -4
- data/lib/dependabot/bundler/file_fetcher.rb +23 -3
- data/lib/dependabot/bundler/file_parser.rb +16 -34
- data/lib/dependabot/bundler/metadata_finder.rb +1 -1
- data/lib/dependabot/bundler/package/package_details_fetcher.rb +10 -2
- data/lib/dependabot/bundler/update_checker/conflicting_dependency_resolver.rb +36 -3
- data/lib/dependabot/bundler/update_checker/force_updater.rb +70 -16
- data/lib/dependabot/bundler/update_checker/latest_version_finder.rb +2 -6
- data/lib/dependabot/bundler/update_checker/shared_bundler_helpers.rb +57 -35
- data/lib/dependabot/bundler/update_checker/version_resolver.rb +78 -22
- data/lib/dependabot/bundler/update_checker.rb +72 -19
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed2db4c89c832c17cf73a1183c1ca6645f8f8c141a357526eb997691227dade6
|
4
|
+
data.tar.gz: 41f43a96a647a712ba845860aaecd0bcca8a5aa316c93e578c271f5f7aabd50d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e1ed157de7a72eb7d78ca0cafce120e2517e1142a1f38a2fb676edd787db470da46f782f091123028c9a45c647d77f15740e4ee12fa189be9dbd1176f77aae8
|
7
|
+
data.tar.gz: 99d4ccb5ccb39ed52adca7aaaeb84e34356b7efa263541fbdd7a00cbca100b818d52311c3145f2abc73da100fb8e318b05c2fa9fbc5d501c5a7a0d06ff936bad
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
require "dependabot/file_fetchers"
|
6
6
|
require "dependabot/file_fetchers/base"
|
7
|
+
require "dependabot/file_filtering"
|
7
8
|
require "dependabot/bundler/file_updater/lockfile_updater"
|
8
9
|
require "dependabot/bundler/cached_lockfile_parser"
|
9
10
|
require "dependabot/errors"
|
@@ -52,7 +53,13 @@ module Dependabot
|
|
52
53
|
fetched_files += path_gemspecs
|
53
54
|
fetched_files += find_included_files(fetched_files)
|
54
55
|
|
55
|
-
|
56
|
+
# Filter excluded files from final collection
|
57
|
+
unique_files = uniq_files(fetched_files)
|
58
|
+
filtered_files = unique_files.reject do |file|
|
59
|
+
Dependabot::FileFiltering.should_exclude_path?(file.name, "file from final collection", @exclude_paths)
|
60
|
+
end
|
61
|
+
|
62
|
+
filtered_files
|
56
63
|
end
|
57
64
|
|
58
65
|
private
|
@@ -174,8 +181,12 @@ module Dependabot
|
|
174
181
|
end
|
175
182
|
|
176
183
|
@find_included_files ||= T.let(
|
177
|
-
paths.
|
178
|
-
|
184
|
+
paths.filter_map do |path|
|
185
|
+
# Skip excluded included files
|
186
|
+
next nil if Dependabot::FileFiltering.should_exclude_path?(path, "included file", @exclude_paths)
|
187
|
+
|
188
|
+
fetch_file_from_host(path)
|
189
|
+
end.tap { |req_files| req_files.each { |f| f.support_file = true } }, # rubocop:disable Style/MultilineBlockChain
|
179
190
|
T.nilable(T::Array[DependencyFile])
|
180
191
|
)
|
181
192
|
end
|
@@ -238,6 +249,15 @@ module Dependabot
|
|
238
249
|
next if previously_fetched_files.map(&:name).include?(path)
|
239
250
|
next if file.name == path
|
240
251
|
|
252
|
+
# Skip excluded child Gemfiles
|
253
|
+
if Dependabot::Experiments.enabled?(:enable_exclude_paths_subdirectory_manifest_files) &&
|
254
|
+
!@exclude_paths.empty? && Dependabot::FileFiltering.exclude_path?(path, @exclude_paths)
|
255
|
+
raise Dependabot::DependencyFileNotEvaluatable,
|
256
|
+
"Cannot process requirements: '#{file.name}' references excluded file '#{path}'. " \
|
257
|
+
"Please either remove the reference from '#{file.name}' " \
|
258
|
+
"or update your exclude_paths configuration."
|
259
|
+
end
|
260
|
+
|
241
261
|
fetched_file = fetch_file_from_host(path)
|
242
262
|
grandchild_gemfiles = fetch_child_gemfiles(
|
243
263
|
file: fetched_file,
|
@@ -20,6 +20,7 @@ module Dependabot
|
|
20
20
|
module Bundler
|
21
21
|
class FileParser < Dependabot::FileParsers::Base # rubocop:disable Metrics/ClassLength
|
22
22
|
extend T::Sig
|
23
|
+
|
23
24
|
require "dependabot/file_parsers/base/dependency_set"
|
24
25
|
require "dependabot/bundler/file_parser/file_preparer"
|
25
26
|
require "dependabot/bundler/file_parser/gemfile_declaration_finder"
|
@@ -122,21 +123,17 @@ module Dependabot
|
|
122
123
|
parsed_gemfile.each do |dep|
|
123
124
|
next unless gemfile_declaration_finder.gemfile_includes_dependency?(dep)
|
124
125
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
)
|
137
|
-
|
138
|
-
file.dependencies << dep
|
139
|
-
dependencies << dep
|
126
|
+
dependencies << 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
|
+
)
|
140
137
|
end
|
141
138
|
end
|
142
139
|
|
@@ -144,7 +141,7 @@ module Dependabot
|
|
144
141
|
end
|
145
142
|
|
146
143
|
sig { returns(DependencySet) }
|
147
|
-
def gemspec_dependencies # rubocop:disable Metrics/PerceivedComplexity
|
144
|
+
def gemspec_dependencies # rubocop:disable Metrics/PerceivedComplexity
|
148
145
|
@gemspec_dependencies = T.let(@gemspec_dependencies, T.nilable(DependencySet))
|
149
146
|
return @gemspec_dependencies if @gemspec_dependencies
|
150
147
|
|
@@ -159,7 +156,7 @@ module Dependabot
|
|
159
156
|
parsed_gemspec(gemspec).each do |dependency|
|
160
157
|
next unless gemspec_declaration_finder.gemspec_includes_dependency?(dependency)
|
161
158
|
|
162
|
-
|
159
|
+
queue << Dependency.new(
|
163
160
|
name: dependency.fetch("name"),
|
164
161
|
version: dependency_version(dependency.fetch("name"))&.to_s,
|
165
162
|
requirements: [{
|
@@ -174,9 +171,6 @@ module Dependabot
|
|
174
171
|
}],
|
175
172
|
package_manager: "bundler"
|
176
173
|
)
|
177
|
-
|
178
|
-
gemspec.dependencies << dep
|
179
|
-
queue << dep
|
180
174
|
end
|
181
175
|
end
|
182
176
|
end
|
@@ -198,23 +192,15 @@ module Dependabot
|
|
198
192
|
parsed_lockfile.specs.each do |dependency|
|
199
193
|
next if dependency.source.is_a?(::Bundler::Source::Path)
|
200
194
|
|
201
|
-
|
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(
|
195
|
+
dependencies << Dependency.new(
|
206
196
|
name: dependency.name,
|
207
197
|
version: dependency_version(dependency.name)&.to_s,
|
208
198
|
requirements: [],
|
209
199
|
package_manager: "bundler",
|
210
200
|
subdependency_metadata: [{
|
211
201
|
production: production_dep_names.include?(dependency.name)
|
212
|
-
}]
|
213
|
-
direct_relationship: is_direct
|
202
|
+
}]
|
214
203
|
)
|
215
|
-
|
216
|
-
T.must(lockfile).dependencies << dep
|
217
|
-
dependencies << dep
|
218
204
|
end
|
219
205
|
|
220
206
|
dependencies
|
@@ -357,10 +343,6 @@ module Dependabot
|
|
357
343
|
get_original_file("Gemfile.lock") || get_original_file("gems.locked"),
|
358
344
|
T.nilable(Dependabot::DependencyFile)
|
359
345
|
)
|
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
346
|
end
|
365
347
|
|
366
348
|
sig { returns(T.untyped) }
|
@@ -204,7 +204,7 @@ module Dependabot
|
|
204
204
|
cred["type"] == "rubygems_server" && cred.replaces_base?
|
205
205
|
end
|
206
206
|
host = credential ? credential["host"] : "rubygems.org"
|
207
|
-
@base_url = "https://#{host}#{host&.end_with?('/')
|
207
|
+
@base_url = "https://#{host}#{'/' unless host&.end_with?('/')}"
|
208
208
|
end
|
209
209
|
|
210
210
|
def registry_auth_headers
|
@@ -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:
|
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 ||=
|
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:
|
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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
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
|
@@ -122,12 +122,8 @@ module Dependabot
|
|
122
122
|
@wants_prerelease ||= T.let(
|
123
123
|
begin
|
124
124
|
current_version = dependency.numeric_version
|
125
|
-
|
126
|
-
|
127
|
-
else
|
128
|
-
dependency.requirements.any? do |req|
|
129
|
-
req[:requirement].match?(/[a-z]/i)
|
130
|
-
end
|
125
|
+
current_version&.prerelease? || dependency.requirements.any? do |req|
|
126
|
+
req[:requirement].match?(/[a-z]/i)
|
131
127
|
end
|
132
128
|
end, T.nilable(T::Boolean)
|
133
129
|
)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
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
|
-
|
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
|
-
|
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
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
124
|
-
|
125
|
-
|
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
|
-
|
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 {
|
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
|
-
|
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:
|
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
|
-
|
24
|
-
|
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
|
-
|
61
|
-
|
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
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "dependabot/bundler/file_updater/requirement_replacer"
|
@@ -17,40 +17,53 @@ module Dependabot
|
|
17
17
|
require_relative "update_checker/version_resolver"
|
18
18
|
require_relative "update_checker/latest_version_finder"
|
19
19
|
require_relative "update_checker/conflicting_dependency_resolver"
|
20
|
+
extend T::Sig
|
20
21
|
|
22
|
+
sig { override.returns(T.nilable(T.any(String, Dependabot::Bundler::Version))) }
|
21
23
|
def latest_version
|
22
24
|
return latest_version_for_git_dependency if git_dependency?
|
23
25
|
|
24
26
|
latest_version_details&.fetch(:version)
|
25
27
|
end
|
26
28
|
|
29
|
+
sig { override.returns(T.nilable(T.any(String, Dependabot::Bundler::Version))) }
|
27
30
|
def latest_resolvable_version
|
28
31
|
return latest_resolvable_version_for_git_dependency if git_dependency?
|
29
32
|
|
30
33
|
latest_resolvable_version_details&.fetch(:version)
|
31
34
|
end
|
32
35
|
|
36
|
+
sig { override.returns(T.nilable(Dependabot::Bundler::Version)) }
|
33
37
|
def lowest_security_fix_version
|
34
|
-
|
35
|
-
.lowest_security_fix_version
|
38
|
+
T.cast(
|
39
|
+
latest_version_finder(remove_git_source: false).lowest_security_fix_version,
|
40
|
+
T.nilable(Dependabot::Bundler::Version)
|
41
|
+
)
|
36
42
|
end
|
37
43
|
|
44
|
+
sig { override.returns(T.nilable(Dependabot::Bundler::Version)) }
|
38
45
|
def lowest_resolvable_security_fix_version
|
39
46
|
raise "Dependency not vulnerable!" unless vulnerable?
|
40
|
-
return latest_resolvable_version if git_dependency?
|
47
|
+
return T.cast(latest_resolvable_version, T.nilable(Dependabot::Bundler::Version)) if git_dependency?
|
41
48
|
|
42
49
|
lowest_fix =
|
43
50
|
latest_version_finder(remove_git_source: false)
|
44
51
|
.lowest_security_fix_version
|
45
|
-
return unless lowest_fix && resolvable?(lowest_fix)
|
52
|
+
return unless lowest_fix && resolvable?(T.cast(lowest_fix, Dependabot::Bundler::Version))
|
46
53
|
|
47
|
-
lowest_fix
|
54
|
+
T.cast(lowest_fix, Dependabot::Bundler::Version)
|
48
55
|
end
|
49
56
|
|
57
|
+
sig { override.returns(T.nilable(T.any(String, Dependabot::Bundler::Version))) }
|
50
58
|
def latest_resolvable_version_with_no_unlock
|
51
59
|
current_ver = dependency.version
|
52
60
|
return current_ver if git_dependency? && git_commit_checker.pinned?
|
53
61
|
|
62
|
+
@latest_resolvable_version_detail_with_no_unlock = T.let(
|
63
|
+
@latest_resolvable_version_detail_with_no_unlock,
|
64
|
+
T.nilable(T::Hash[Symbol, T.untyped])
|
65
|
+
)
|
66
|
+
|
54
67
|
@latest_resolvable_version_detail_with_no_unlock ||=
|
55
68
|
version_resolver(remove_git_source: false, unlock_requirement: false)
|
56
69
|
.latest_resolvable_version_details
|
@@ -62,6 +75,7 @@ module Dependabot
|
|
62
75
|
end
|
63
76
|
end
|
64
77
|
|
78
|
+
sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
65
79
|
def updated_requirements
|
66
80
|
latest_version_for_req_updater = latest_version_details&.fetch(:version)&.to_s
|
67
81
|
latest_resolvable_version_for_req_updater = preferred_resolvable_version_details&.fetch(:version)&.to_s
|
@@ -75,9 +89,10 @@ module Dependabot
|
|
75
89
|
).updated_requirements
|
76
90
|
end
|
77
91
|
|
92
|
+
sig { returns(T::Boolean) }
|
78
93
|
def requirements_unlocked_or_can_be?
|
79
94
|
return true if requirements_unlocked?
|
80
|
-
return false if requirements_update_strategy.lockfile_only?
|
95
|
+
return false if T.must(requirements_update_strategy).lockfile_only?
|
81
96
|
|
82
97
|
dependency.specific_requirements
|
83
98
|
.all? do |req|
|
@@ -92,6 +107,7 @@ module Dependabot
|
|
92
107
|
end
|
93
108
|
end
|
94
109
|
|
110
|
+
sig { returns(T.nilable(Dependabot::RequirementsUpdateStrategy)) }
|
95
111
|
def requirements_update_strategy
|
96
112
|
# If passed in as an option (in the base class) honour that option
|
97
113
|
return @requirements_update_strategy if @requirements_update_strategy
|
@@ -104,6 +120,7 @@ module Dependabot
|
|
104
120
|
end
|
105
121
|
end
|
106
122
|
|
123
|
+
sig { override.returns(T::Array[T::Hash[String, String]]) }
|
107
124
|
def conflicting_dependencies
|
108
125
|
ConflictingDependencyResolver.new(
|
109
126
|
dependency_files: dependency_files,
|
@@ -112,16 +129,18 @@ module Dependabot
|
|
112
129
|
options: options
|
113
130
|
).conflicting_dependencies(
|
114
131
|
dependency: dependency,
|
115
|
-
target_version: lowest_security_fix_version
|
132
|
+
target_version: lowest_security_fix_version.to_s # Convert Version to String
|
116
133
|
)
|
117
134
|
end
|
118
135
|
|
119
136
|
private
|
120
137
|
|
138
|
+
sig { returns(T::Boolean) }
|
121
139
|
def requirements_unlocked?
|
122
140
|
dependency.specific_requirements.none?
|
123
141
|
end
|
124
142
|
|
143
|
+
sig { override.returns(T::Boolean) }
|
125
144
|
def latest_version_resolvable_with_full_unlock?
|
126
145
|
return false unless latest_version
|
127
146
|
return false if version_resolver(remove_git_source: false).latest_allowable_version_incompatible_with_ruby?
|
@@ -139,22 +158,26 @@ module Dependabot
|
|
139
158
|
false
|
140
159
|
end
|
141
160
|
|
161
|
+
sig { override.returns(T::Array[Dependabot::Dependency]) }
|
142
162
|
def updated_dependencies_after_full_unlock
|
143
163
|
force_updater.updated_dependencies
|
144
164
|
end
|
145
165
|
|
166
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
146
167
|
def preferred_resolvable_version_details
|
147
168
|
return { version: lowest_resolvable_security_fix_version } if vulnerable?
|
148
169
|
|
149
170
|
latest_resolvable_version_details
|
150
171
|
end
|
151
172
|
|
173
|
+
sig { returns(T::Boolean) }
|
152
174
|
def git_dependency?
|
153
175
|
git_commit_checker.git_dependency?
|
154
176
|
end
|
155
177
|
|
178
|
+
sig { params(version: Dependabot::Bundler::Version).returns(T.untyped) }
|
156
179
|
def resolvable?(version)
|
157
|
-
@resolvable ||= {}
|
180
|
+
@resolvable ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
|
158
181
|
return @resolvable[version] if @resolvable.key?(version)
|
159
182
|
|
160
183
|
@resolvable[version] =
|
@@ -165,7 +188,7 @@ module Dependabot
|
|
165
188
|
repo_contents_path: repo_contents_path,
|
166
189
|
credentials: credentials,
|
167
190
|
target_version: version,
|
168
|
-
requirements_update_strategy: requirements_update_strategy,
|
191
|
+
requirements_update_strategy: T.must(requirements_update_strategy),
|
169
192
|
update_multiple_dependencies: false,
|
170
193
|
options: options
|
171
194
|
).updated_dependencies
|
@@ -175,8 +198,9 @@ module Dependabot
|
|
175
198
|
end
|
176
199
|
end
|
177
200
|
|
201
|
+
sig { params(tag: T.nilable(String)).returns(T.untyped) }
|
178
202
|
def git_tag_resolvable?(tag)
|
179
|
-
@git_tag_resolvable ||= {}
|
203
|
+
@git_tag_resolvable ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
|
180
204
|
return @git_tag_resolvable[tag] if @git_tag_resolvable.key?(tag)
|
181
205
|
|
182
206
|
@git_tag_resolvable[tag] =
|
@@ -198,20 +222,23 @@ module Dependabot
|
|
198
222
|
end
|
199
223
|
end
|
200
224
|
|
225
|
+
sig { params(remove_git_source: T::Boolean).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
201
226
|
def latest_version_details(remove_git_source: false)
|
202
|
-
@latest_version_details ||= {}
|
227
|
+
@latest_version_details ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
|
203
228
|
@latest_version_details[remove_git_source] ||=
|
204
229
|
latest_version_finder(remove_git_source: remove_git_source)
|
205
230
|
.latest_version_details
|
206
231
|
end
|
207
232
|
|
233
|
+
sig { params(remove_git_source: T::Boolean).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
208
234
|
def latest_resolvable_version_details(remove_git_source: false)
|
209
|
-
@latest_resolvable_version_details ||= {}
|
235
|
+
@latest_resolvable_version_details ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
|
210
236
|
@latest_resolvable_version_details[remove_git_source] ||=
|
211
237
|
version_resolver(remove_git_source: remove_git_source)
|
212
238
|
.latest_resolvable_version_details
|
213
239
|
end
|
214
240
|
|
241
|
+
sig { returns(T.nilable(T.any(String, Dependabot::Bundler::Version))) }
|
215
242
|
def latest_version_for_git_dependency
|
216
243
|
latest_release =
|
217
244
|
latest_version_details(remove_git_source: true)
|
@@ -238,6 +265,7 @@ module Dependabot
|
|
238
265
|
dependency.version
|
239
266
|
end
|
240
267
|
|
268
|
+
sig { returns(T.any(String, T.nilable(Dependabot::Bundler::Version))) }
|
241
269
|
def latest_resolvable_version_for_git_dependency
|
242
270
|
latest_release = latest_resolvable_version_without_git_source
|
243
271
|
|
@@ -255,7 +283,7 @@ module Dependabot
|
|
255
283
|
if git_commit_checker.pinned_ref_looks_like_version? &&
|
256
284
|
latest_git_tag_is_resolvable?
|
257
285
|
new_tag = git_commit_checker.local_tag_for_latest_version
|
258
|
-
return new_tag
|
286
|
+
return new_tag&.fetch(:tag_sha)
|
259
287
|
end
|
260
288
|
|
261
289
|
# If the dependency is pinned to a tag that doesn't look like a
|
@@ -263,6 +291,7 @@ module Dependabot
|
|
263
291
|
dependency.version
|
264
292
|
end
|
265
293
|
|
294
|
+
sig { returns(T.any(String, T.nilable(Dependabot::Bundler::Version))) }
|
266
295
|
def latest_resolvable_version_without_git_source
|
267
296
|
return nil unless latest_version.is_a?(Gem::Version)
|
268
297
|
|
@@ -272,6 +301,7 @@ module Dependabot
|
|
272
301
|
nil
|
273
302
|
end
|
274
303
|
|
304
|
+
sig { returns(T.any(String, T.nilable(Dependabot::Bundler::Version))) }
|
275
305
|
def latest_resolvable_commit_with_unchanged_git_source
|
276
306
|
details = latest_resolvable_version_details(remove_git_source: false)
|
277
307
|
|
@@ -285,6 +315,7 @@ module Dependabot
|
|
285
315
|
nil
|
286
316
|
end
|
287
317
|
|
318
|
+
sig { returns(T::Boolean) }
|
288
319
|
def latest_git_tag_is_resolvable?
|
289
320
|
latest_tag_details = git_commit_checker.local_tag_for_latest_version
|
290
321
|
return false unless latest_tag_details
|
@@ -292,12 +323,14 @@ module Dependabot
|
|
292
323
|
git_tag_resolvable?(latest_tag_details.fetch(:tag))
|
293
324
|
end
|
294
325
|
|
326
|
+
sig { params(release: T.untyped).returns(T::Boolean) }
|
295
327
|
def git_branch_or_ref_in_release?(release)
|
296
328
|
return false unless release
|
297
329
|
|
298
330
|
git_commit_checker.branch_or_ref_in_release?(release)
|
299
331
|
end
|
300
332
|
|
333
|
+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
|
301
334
|
def updated_source
|
302
335
|
# Never need to update source, unless a git_dependency
|
303
336
|
return dependency_source_details unless git_dependency?
|
@@ -306,31 +339,42 @@ module Dependabot
|
|
306
339
|
if git_commit_checker.pinned_ref_looks_like_version? &&
|
307
340
|
latest_git_tag_is_resolvable?
|
308
341
|
new_tag = git_commit_checker.local_tag_for_latest_version
|
309
|
-
return dependency_source_details.merge(ref: new_tag.fetch(:tag))
|
342
|
+
return T.must(dependency_source_details).merge(ref: T.must(new_tag).fetch(:tag))
|
310
343
|
end
|
311
344
|
|
312
345
|
# Otherwise return the original source
|
313
346
|
dependency_source_details
|
314
347
|
end
|
315
348
|
|
349
|
+
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.untyped])) }
|
316
350
|
def dependency_source_details
|
317
351
|
dependency.source_details
|
318
352
|
end
|
319
353
|
|
354
|
+
sig { returns(Dependabot::Bundler::UpdateChecker::ForceUpdater) }
|
320
355
|
def force_updater
|
356
|
+
if @force_updater.nil?
|
357
|
+
@force_updater = T.let(@force_updater,
|
358
|
+
T.nilable(Dependabot::Bundler::UpdateChecker::ForceUpdater))
|
359
|
+
end
|
321
360
|
@force_updater ||=
|
322
361
|
ForceUpdater.new(
|
323
362
|
dependency: dependency,
|
324
363
|
dependency_files: dependency_files,
|
325
364
|
repo_contents_path: repo_contents_path,
|
326
365
|
credentials: credentials,
|
327
|
-
target_version: latest_version,
|
328
|
-
requirements_update_strategy: requirements_update_strategy,
|
366
|
+
target_version: T.cast(latest_version, Dependabot::Version),
|
367
|
+
requirements_update_strategy: T.must(requirements_update_strategy),
|
329
368
|
options: options
|
330
369
|
)
|
331
370
|
end
|
332
371
|
|
372
|
+
sig { returns(Dependabot::GitCommitChecker) }
|
333
373
|
def git_commit_checker
|
374
|
+
if @git_commit_checker.nil?
|
375
|
+
@git_commit_checker = T.let(@git_commit_checker,
|
376
|
+
T.nilable(Dependabot::GitCommitChecker))
|
377
|
+
end
|
334
378
|
@git_commit_checker ||=
|
335
379
|
GitCommitChecker.new(
|
336
380
|
dependency: dependency,
|
@@ -338,8 +382,9 @@ module Dependabot
|
|
338
382
|
)
|
339
383
|
end
|
340
384
|
|
385
|
+
sig { params(remove_git_source: T::Boolean, unlock_requirement: T::Boolean).returns(T.untyped) }
|
341
386
|
def version_resolver(remove_git_source:, unlock_requirement: true)
|
342
|
-
@version_resolver ||= {}
|
387
|
+
@version_resolver ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
|
343
388
|
@version_resolver[remove_git_source] ||= {}
|
344
389
|
@version_resolver[remove_git_source][unlock_requirement] ||=
|
345
390
|
VersionResolver.new(
|
@@ -357,8 +402,9 @@ module Dependabot
|
|
357
402
|
)
|
358
403
|
end
|
359
404
|
|
405
|
+
sig { params(remove_git_source: T::Boolean).returns(Dependabot::Bundler::UpdateChecker::LatestVersionFinder) }
|
360
406
|
def latest_version_finder(remove_git_source:)
|
361
|
-
@latest_version_finder ||= {}
|
407
|
+
@latest_version_finder ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
|
362
408
|
@latest_version_finder[remove_git_source] ||=
|
363
409
|
begin
|
364
410
|
prepared_dependency_files = prepared_dependency_files(
|
@@ -379,6 +425,13 @@ module Dependabot
|
|
379
425
|
end
|
380
426
|
end
|
381
427
|
|
428
|
+
sig do
|
429
|
+
params(
|
430
|
+
remove_git_source: T::Boolean,
|
431
|
+
unlock_requirement: T::Boolean,
|
432
|
+
latest_allowable_version: T.nilable(T.any(String, Dependabot::Bundler::Version))
|
433
|
+
).returns(T::Array[Dependabot::DependencyFile])
|
434
|
+
end
|
382
435
|
def prepared_dependency_files(remove_git_source:, unlock_requirement:,
|
383
436
|
latest_allowable_version: nil)
|
384
437
|
FilePreparer.new(
|
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.
|
4
|
+
version: 0.333.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.
|
18
|
+
version: 0.333.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.
|
25
|
+
version: 0.333.0
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: parallel
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -225,14 +225,14 @@ dependencies:
|
|
225
225
|
requirements:
|
226
226
|
- - "~>"
|
227
227
|
- !ruby/object:Gem::Version
|
228
|
-
version: '3.
|
228
|
+
version: '3.25'
|
229
229
|
type: :development
|
230
230
|
prerelease: false
|
231
231
|
version_requirements: !ruby/object:Gem::Requirement
|
232
232
|
requirements:
|
233
233
|
- - "~>"
|
234
234
|
- !ruby/object:Gem::Version
|
235
|
-
version: '3.
|
235
|
+
version: '3.25'
|
236
236
|
- !ruby/object:Gem::Dependency
|
237
237
|
name: webrick
|
238
238
|
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.
|
325
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.333.0
|
326
326
|
rdoc_options: []
|
327
327
|
require_paths:
|
328
328
|
- lib
|