dependabot-python 0.357.0 → 0.359.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/python/file_parser/pyproject_files_parser.rb +56 -5
- data/lib/dependabot/python/file_parser.rb +1 -10
- data/lib/dependabot/python/file_updater/poetry_file_updater.rb +43 -0
- data/lib/dependabot/python/update_checker/latest_version_finder.rb +121 -2
- data/lib/dependabot/python/update_checker/requirements_updater.rb +2 -2
- data/lib/dependabot/python/update_checker.rb +68 -4
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b809922cec5a45858a2db5ccbc1a44616bd29e338b208ef2ce62c40cc92c5cc
|
|
4
|
+
data.tar.gz: 690573daf64882e4308e2b67962d218b050d6e35f5f2de463037c9d3bb4373f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85cbac2d3e04004f10fb8829b512c22962339aca71b3e2fe00b5b22a0af1a745cc6a0810d038f5bf084dcebd749959fb73bcf08408de67a5683a61d7eb47e121
|
|
7
|
+
data.tar.gz: f2336e9490af88f4a08ed69c4116b085d161e2e0e8ef5ea5e2e494fb1308ea5b62239761a675c4f214cd79b943a0414d7e2133a6a5e5573b4aac1ef433723a8a
|
|
@@ -19,7 +19,8 @@ module Dependabot
|
|
|
19
19
|
POETRY_DEPENDENCY_TYPES = %w(dependencies dev-dependencies).freeze
|
|
20
20
|
|
|
21
21
|
# https://python-poetry.org/docs/dependency-specification/
|
|
22
|
-
|
|
22
|
+
# Git dependencies with tags are now supported for version tracking
|
|
23
|
+
UNSUPPORTED_DEPENDENCY_TYPES = %w(path url).freeze
|
|
23
24
|
|
|
24
25
|
sig { params(dependency_files: T::Array[Dependabot::DependencyFile]).void }
|
|
25
26
|
def initialize(dependency_files:)
|
|
@@ -148,13 +149,29 @@ module Dependabot
|
|
|
148
149
|
|
|
149
150
|
# @param req can be an Array, Hash or String that represents the constraints for a dependency
|
|
150
151
|
sig { params(req: T.untyped, type: String).returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) }
|
|
152
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
151
153
|
def parse_requirements_from(req, type)
|
|
152
154
|
[req].flatten.compact.filter_map do |requirement|
|
|
155
|
+
# Skip unsupported dependency types (path, url), but allow git
|
|
153
156
|
next if requirement.is_a?(Hash) && UNSUPPORTED_DEPENDENCY_TYPES.intersect?(requirement.keys)
|
|
157
|
+
# Skip git dependencies without tags (e.g., with branch, rev)
|
|
158
|
+
next if requirement.is_a?(Hash) && requirement["git"] && !requirement["tag"]
|
|
154
159
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
160
|
+
# Handle git dependencies with tags
|
|
161
|
+
if requirement.is_a?(Hash) && requirement["git"] && requirement["tag"]
|
|
162
|
+
{
|
|
163
|
+
requirement: nil,
|
|
164
|
+
file: T.must(pyproject).name,
|
|
165
|
+
source: {
|
|
166
|
+
type: "git",
|
|
167
|
+
url: requirement["git"],
|
|
168
|
+
ref: requirement["tag"],
|
|
169
|
+
branch: nil
|
|
170
|
+
},
|
|
171
|
+
groups: [type]
|
|
172
|
+
}
|
|
173
|
+
elsif requirement.is_a?(String)
|
|
174
|
+
check_requirements(requirement)
|
|
158
175
|
{
|
|
159
176
|
requirement: requirement,
|
|
160
177
|
file: T.must(pyproject).name,
|
|
@@ -162,15 +179,21 @@ module Dependabot
|
|
|
162
179
|
groups: [type]
|
|
163
180
|
}
|
|
164
181
|
else
|
|
182
|
+
check_requirements(requirement)
|
|
183
|
+
# String sources are registry name references (e.g., "custom") that reference
|
|
184
|
+
# [[tool.poetry.source]] definitions. Resolve them to proper hashes.
|
|
185
|
+
source_value = requirement.fetch("source", nil)
|
|
186
|
+
source = resolve_source(source_value)
|
|
165
187
|
{
|
|
166
188
|
requirement: requirement["version"],
|
|
167
189
|
file: T.must(pyproject).name,
|
|
168
|
-
source:
|
|
190
|
+
source: source,
|
|
169
191
|
groups: [type]
|
|
170
192
|
}
|
|
171
193
|
end
|
|
172
194
|
end
|
|
173
195
|
end
|
|
196
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
174
197
|
|
|
175
198
|
sig { returns(T.nilable(T::Boolean)) }
|
|
176
199
|
def using_poetry?
|
|
@@ -280,6 +303,34 @@ module Dependabot
|
|
|
280
303
|
NameNormaliser.normalise(name)
|
|
281
304
|
end
|
|
282
305
|
|
|
306
|
+
sig { params(source_value: T.untyped).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
|
307
|
+
def resolve_source(source_value)
|
|
308
|
+
# Return nil if no source specified
|
|
309
|
+
return nil if source_value.nil?
|
|
310
|
+
|
|
311
|
+
# If already a hash, return as-is (handles git sources)
|
|
312
|
+
return source_value if source_value.is_a?(Hash)
|
|
313
|
+
|
|
314
|
+
# String sources are references to [[tool.poetry.source]] definitions
|
|
315
|
+
# Look up the source definition and create a hash
|
|
316
|
+
return nil unless source_value.is_a?(String)
|
|
317
|
+
|
|
318
|
+
source_name = source_value
|
|
319
|
+
poetry_sources = parsed_pyproject.dig("tool", "poetry", "source") || []
|
|
320
|
+
source_def = poetry_sources.find { |s| s["name"] == source_name }
|
|
321
|
+
|
|
322
|
+
# If source definition not found, return nil
|
|
323
|
+
return nil unless source_def
|
|
324
|
+
|
|
325
|
+
# Create a hash with type and url from the source definition
|
|
326
|
+
# Use "registry" as the type since these are package index sources
|
|
327
|
+
{
|
|
328
|
+
type: "registry",
|
|
329
|
+
url: source_def["url"],
|
|
330
|
+
name: source_name
|
|
331
|
+
}
|
|
332
|
+
end
|
|
333
|
+
|
|
283
334
|
sig { returns(T.untyped) }
|
|
284
335
|
def parsed_pyproject
|
|
285
336
|
@parsed_pyproject ||= T.let(TomlRB.parse(T.must(pyproject).content), T.untyped)
|
|
@@ -101,16 +101,12 @@ module Dependabot
|
|
|
101
101
|
|
|
102
102
|
sig { returns(Ecosystem::VersionManager) }
|
|
103
103
|
def package_manager
|
|
104
|
-
if Dependabot::Experiments.enabled?(:enable_file_parser_python_local)
|
|
105
|
-
Dependabot.logger.info("Detected package manager : #{detected_package_manager.name}")
|
|
106
|
-
end
|
|
107
|
-
|
|
108
104
|
@package_manager ||= T.let(detected_package_manager, T.nilable(Dependabot::Ecosystem::VersionManager))
|
|
109
105
|
end
|
|
110
106
|
|
|
111
107
|
sig { returns(Ecosystem::VersionManager) }
|
|
112
108
|
def detected_package_manager
|
|
113
|
-
setup_python_environment
|
|
109
|
+
setup_python_environment
|
|
114
110
|
|
|
115
111
|
return PipenvPackageManager.new(T.must(detect_pipenv_version)) if detect_pipenv_version
|
|
116
112
|
|
|
@@ -225,11 +221,6 @@ module Dependabot
|
|
|
225
221
|
|
|
226
222
|
sig { returns(String) }
|
|
227
223
|
def python_raw_version
|
|
228
|
-
if Dependabot::Experiments.enabled?(:enable_file_parser_python_local)
|
|
229
|
-
Dependabot.logger.info("Detected python version: #{language_version_manager.python_version}")
|
|
230
|
-
Dependabot.logger.info("Detected python major minor version: #{language_version_manager.python_major_minor}")
|
|
231
|
-
end
|
|
232
|
-
|
|
233
224
|
language_version_manager.python_version
|
|
234
225
|
end
|
|
235
226
|
|
|
@@ -115,6 +115,9 @@ module Dependabot
|
|
|
115
115
|
).returns(String)
|
|
116
116
|
end
|
|
117
117
|
def replace_dep(dep, content, new_r, old_r)
|
|
118
|
+
# Handle Git dependencies with tags
|
|
119
|
+
return update_git_tag(dep, content, new_r, old_r) if git_dependency?(new_r) && git_dependency?(old_r)
|
|
120
|
+
|
|
118
121
|
new_req = new_r[:requirement]
|
|
119
122
|
old_req = old_r[:requirement]
|
|
120
123
|
|
|
@@ -149,6 +152,38 @@ module Dependabot
|
|
|
149
152
|
content
|
|
150
153
|
end
|
|
151
154
|
|
|
155
|
+
sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Boolean) }
|
|
156
|
+
def git_dependency?(req)
|
|
157
|
+
req.dig(:source, :type) == "git"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
sig do
|
|
161
|
+
params(
|
|
162
|
+
dep: Dependabot::Dependency,
|
|
163
|
+
content: String,
|
|
164
|
+
new_r: T::Hash[Symbol, T.untyped],
|
|
165
|
+
old_r: T::Hash[Symbol, T.untyped]
|
|
166
|
+
).returns(String)
|
|
167
|
+
end
|
|
168
|
+
def update_git_tag(dep, content, new_r, old_r)
|
|
169
|
+
old_tag = old_r.dig(:source, :ref)
|
|
170
|
+
new_tag = new_r.dig(:source, :ref)
|
|
171
|
+
|
|
172
|
+
return content if old_tag == new_tag
|
|
173
|
+
|
|
174
|
+
# Match git dependency declaration with tag
|
|
175
|
+
# Example: fastapi = { git = "...", extras = ["all"], tag = "0.110.0" }
|
|
176
|
+
git_dep_regex = /
|
|
177
|
+
^(\s*)#{Regexp.escape(dep.name)}(\s*=\s*\{[^}]*tag\s*=\s*)
|
|
178
|
+
["']#{Regexp.escape(old_tag)}["']([^}]*\})
|
|
179
|
+
/mx
|
|
180
|
+
|
|
181
|
+
content.gsub(git_dep_regex) do
|
|
182
|
+
match_data = T.must(Regexp.last_match)
|
|
183
|
+
"#{match_data[1]}#{dep.name}#{match_data[2]}\"#{new_tag}\"#{match_data[3]}"
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
152
187
|
sig { returns(String) }
|
|
153
188
|
def updated_lockfile_content
|
|
154
189
|
@updated_lockfile_content ||=
|
|
@@ -199,6 +234,9 @@ module Dependabot
|
|
|
199
234
|
|
|
200
235
|
if poetry_object
|
|
201
236
|
dependencies.each do |dep|
|
|
237
|
+
# Skip Git dependencies - they use tags/refs, not versions
|
|
238
|
+
next if git_dependency_being_updated?(dep)
|
|
239
|
+
|
|
202
240
|
if dep.requirements.find { |r| r[:file] == pyproject&.name }
|
|
203
241
|
lock_declaration_to_new_version!(poetry_object, dep)
|
|
204
242
|
else
|
|
@@ -240,6 +278,11 @@ module Dependabot
|
|
|
240
278
|
poetry_object[subdep_type][dep.name] = dep.version
|
|
241
279
|
end
|
|
242
280
|
|
|
281
|
+
sig { params(dep: Dependabot::Dependency).returns(T::Boolean) }
|
|
282
|
+
def git_dependency_being_updated?(dep)
|
|
283
|
+
dep.requirements.any? { |r| r.dig(:source, :type) == "git" }
|
|
284
|
+
end
|
|
285
|
+
|
|
243
286
|
sig { params(pyproject_content: String).returns(String) }
|
|
244
287
|
def sanitize(pyproject_content)
|
|
245
288
|
PyprojectPreparer
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "cgi"
|
|
@@ -7,6 +7,7 @@ require "nokogiri"
|
|
|
7
7
|
require "sorbet-runtime"
|
|
8
8
|
|
|
9
9
|
require "dependabot/dependency"
|
|
10
|
+
require "dependabot/git_commit_checker"
|
|
10
11
|
require "dependabot/python/update_checker"
|
|
11
12
|
require "dependabot/update_checkers/version_filters"
|
|
12
13
|
require "dependabot/registry_client"
|
|
@@ -22,6 +23,38 @@ module Dependabot
|
|
|
22
23
|
class LatestVersionFinder < Dependabot::Package::PackageLatestVersionFinder
|
|
23
24
|
extend T::Sig
|
|
24
25
|
|
|
26
|
+
sig do
|
|
27
|
+
params(git_commit_checker: Dependabot::GitCommitChecker)
|
|
28
|
+
.returns(T.nilable(T::Hash[Symbol, T.untyped]))
|
|
29
|
+
end
|
|
30
|
+
def latest_version_tag(git_commit_checker:)
|
|
31
|
+
return git_commit_checker.local_tag_for_latest_version unless cooldown_enabled?
|
|
32
|
+
|
|
33
|
+
allowed_version_tags = git_commit_checker.local_tags_for_allowed_versions
|
|
34
|
+
tags_in_cooldown = select_version_tags_in_cooldown_period(git_commit_checker)
|
|
35
|
+
|
|
36
|
+
return max_version_from_tags(allowed_version_tags) if tags_in_cooldown.empty?
|
|
37
|
+
|
|
38
|
+
filtered_tags = allowed_version_tags.reject do |tag|
|
|
39
|
+
tags_in_cooldown.include?(tag[:tag])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
if filtered_tags.empty?
|
|
43
|
+
Dependabot.logger.info("All git tags filtered by cooldown for #{dependency.name}, returning nil")
|
|
44
|
+
return nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
filtered_count = allowed_version_tags.count - filtered_tags.count
|
|
48
|
+
if filtered_count.positive?
|
|
49
|
+
Dependabot.logger.info("Filtered #{filtered_count} git tags due to cooldown for #{dependency.name}")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
max_version_from_tags(filtered_tags)
|
|
53
|
+
rescue StandardError => e
|
|
54
|
+
Dependabot.logger.error("Error fetching latest version tag: #{e.message}")
|
|
55
|
+
git_commit_checker.local_tag_for_latest_version
|
|
56
|
+
end
|
|
57
|
+
|
|
25
58
|
sig do
|
|
26
59
|
override.returns(T.nilable(Dependabot::Package::PackageDetails))
|
|
27
60
|
end
|
|
@@ -35,7 +68,93 @@ module Dependabot
|
|
|
35
68
|
|
|
36
69
|
sig { override.returns(T::Boolean) }
|
|
37
70
|
def cooldown_enabled?
|
|
38
|
-
|
|
71
|
+
return false if cooldown_options.nil?
|
|
72
|
+
|
|
73
|
+
cooldown = T.must(cooldown_options)
|
|
74
|
+
cooldown.default_days.to_i.positive? ||
|
|
75
|
+
cooldown.semver_major_days.to_i.positive? ||
|
|
76
|
+
cooldown.semver_minor_days.to_i.positive? ||
|
|
77
|
+
cooldown.semver_patch_days.to_i.positive?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
sig { params(tags: T::Array[T::Hash[Symbol, T.untyped]]).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
|
83
|
+
def max_version_from_tags(tags)
|
|
84
|
+
tags.max_by { |t| t[:version] }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
sig { params(git_commit_checker: Dependabot::GitCommitChecker).returns(T::Array[String]) }
|
|
88
|
+
def select_version_tags_in_cooldown_period(git_commit_checker)
|
|
89
|
+
version_tags_in_cooldown_period = T.let([], T::Array[String])
|
|
90
|
+
|
|
91
|
+
git_commit_checker.refs_for_tag_with_detail.each do |git_tag_with_detail|
|
|
92
|
+
if check_if_version_in_cooldown_period?(git_tag_with_detail)
|
|
93
|
+
version_tags_in_cooldown_period << git_tag_with_detail.tag
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
version_tags_in_cooldown_period
|
|
97
|
+
rescue StandardError => e
|
|
98
|
+
Dependabot.logger.error("Error checking if version is in cooldown: #{e.message}")
|
|
99
|
+
[]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
sig { params(tag_with_detail: Dependabot::GitTagWithDetail).returns(T::Boolean) }
|
|
103
|
+
def check_if_version_in_cooldown_period?(tag_with_detail)
|
|
104
|
+
return false unless tag_with_detail.release_date
|
|
105
|
+
|
|
106
|
+
current_version = version_class.correct?(dependency.version) ? version_class.new(dependency.version) : nil
|
|
107
|
+
tag_version_str = tag_with_detail.tag.delete_prefix("v")
|
|
108
|
+
return false unless version_class.correct?(tag_version_str)
|
|
109
|
+
|
|
110
|
+
new_version = version_class.new(tag_version_str)
|
|
111
|
+
days = cooldown_days_for(current_version, new_version)
|
|
112
|
+
|
|
113
|
+
passed_seconds = Time.now.to_i - release_date_to_seconds(tag_with_detail.release_date)
|
|
114
|
+
passed_seconds < days * DAY_IN_SECONDS
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
sig do
|
|
118
|
+
params(
|
|
119
|
+
current_version: T.nilable(Dependabot::Version),
|
|
120
|
+
new_version: Dependabot::Version
|
|
121
|
+
).returns(Integer)
|
|
122
|
+
end
|
|
123
|
+
def cooldown_days_for(current_version, new_version)
|
|
124
|
+
return 0 unless cooldown_enabled?
|
|
125
|
+
|
|
126
|
+
cooldown = T.must(cooldown_options)
|
|
127
|
+
return 0 unless cooldown.included?(dependency.name)
|
|
128
|
+
return cooldown.default_days if current_version.nil?
|
|
129
|
+
|
|
130
|
+
current_version_semver = current_version.semver_parts
|
|
131
|
+
new_version_semver = new_version.semver_parts
|
|
132
|
+
|
|
133
|
+
return cooldown.default_days if current_version_semver.nil? || new_version_semver.nil?
|
|
134
|
+
|
|
135
|
+
current_major, current_minor, current_patch = current_version_semver
|
|
136
|
+
new_major, new_minor, new_patch = new_version_semver
|
|
137
|
+
|
|
138
|
+
return cooldown.semver_major_days if new_major > current_major
|
|
139
|
+
return cooldown.semver_minor_days if new_minor > current_minor
|
|
140
|
+
return cooldown.semver_patch_days if new_patch > current_patch
|
|
141
|
+
|
|
142
|
+
cooldown.default_days
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
sig { returns(T.class_of(Dependabot::Version)) }
|
|
146
|
+
def version_class
|
|
147
|
+
dependency.version_class
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
sig { params(release_date: T.nilable(String)).returns(Integer) }
|
|
151
|
+
def release_date_to_seconds(release_date)
|
|
152
|
+
return 0 unless release_date
|
|
153
|
+
|
|
154
|
+
Time.parse(release_date).to_i
|
|
155
|
+
rescue ArgumentError => e
|
|
156
|
+
Dependabot.logger.error("Invalid release date format: #{release_date} and error: #{e.message}")
|
|
157
|
+
0
|
|
39
158
|
end
|
|
40
159
|
end
|
|
41
160
|
end
|
|
@@ -389,7 +389,7 @@ module Dependabot
|
|
|
389
389
|
version = version.release if version.prerelease?
|
|
390
390
|
|
|
391
391
|
lb_segments = version.segments
|
|
392
|
-
lb_segments.pop while lb_segments.last
|
|
392
|
+
lb_segments.pop while lb_segments.last&.zero?
|
|
393
393
|
|
|
394
394
|
lb_segments
|
|
395
395
|
end
|
|
@@ -400,7 +400,7 @@ module Dependabot
|
|
|
400
400
|
version = req.requirements.first.last.release
|
|
401
401
|
|
|
402
402
|
if req_string.strip.start_with?("^")
|
|
403
|
-
version.segments.index { |i| i != 0 }
|
|
403
|
+
version.segments.index { |i| i != 0 } || (version.segments.count - 1)
|
|
404
404
|
elsif req_string.include?("*")
|
|
405
405
|
version.segments.count - 1
|
|
406
406
|
elsif req_string.strip.start_with?("~=", "==")
|
|
@@ -17,6 +17,7 @@ require "dependabot/update_checkers/base"
|
|
|
17
17
|
|
|
18
18
|
module Dependabot
|
|
19
19
|
module Python
|
|
20
|
+
# rubocop:disable Metrics/ClassLength
|
|
20
21
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
|
21
22
|
extend T::Sig
|
|
22
23
|
|
|
@@ -35,6 +36,8 @@ module Dependabot
|
|
|
35
36
|
|
|
36
37
|
sig { override.returns(T.nilable(Gem::Version)) }
|
|
37
38
|
def latest_version
|
|
39
|
+
return latest_version_for_git_dependency if git_dependency?
|
|
40
|
+
|
|
38
41
|
@latest_version ||= T.let(
|
|
39
42
|
fetch_latest_version,
|
|
40
43
|
T.nilable(Gem::Version)
|
|
@@ -43,6 +46,8 @@ module Dependabot
|
|
|
43
46
|
|
|
44
47
|
sig { override.returns(T.nilable(Gem::Version)) }
|
|
45
48
|
def latest_resolvable_version
|
|
49
|
+
return latest_resolvable_version_for_git_dependency if git_dependency?
|
|
50
|
+
|
|
46
51
|
@latest_resolvable_version ||= T.let(
|
|
47
52
|
if resolver_type == :requirements
|
|
48
53
|
resolver.latest_resolvable_version
|
|
@@ -59,6 +64,8 @@ module Dependabot
|
|
|
59
64
|
|
|
60
65
|
sig { override.returns(T.nilable(Gem::Version)) }
|
|
61
66
|
def latest_resolvable_version_with_no_unlock
|
|
67
|
+
return T.cast(dependency.version, T.nilable(Gem::Version)) if git_dependency? && git_commit_checker.pinned?
|
|
68
|
+
|
|
62
69
|
@latest_resolvable_version_with_no_unlock ||= T.let(
|
|
63
70
|
if resolver_type == :requirements
|
|
64
71
|
resolver.latest_resolvable_version_with_no_unlock
|
|
@@ -88,6 +95,8 @@ module Dependabot
|
|
|
88
95
|
|
|
89
96
|
sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
90
97
|
def updated_requirements
|
|
98
|
+
return updated_git_requirements if git_dependency?
|
|
99
|
+
|
|
91
100
|
RequirementsUpdater.new(
|
|
92
101
|
requirements: requirements,
|
|
93
102
|
latest_resolvable_version: preferred_resolvable_version&.to_s,
|
|
@@ -112,6 +121,64 @@ module Dependabot
|
|
|
112
121
|
|
|
113
122
|
private
|
|
114
123
|
|
|
124
|
+
sig { returns(T::Boolean) }
|
|
125
|
+
def git_dependency?
|
|
126
|
+
git_commit_checker.git_dependency?
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
sig { returns(T.nilable(Gem::Version)) }
|
|
130
|
+
def latest_version_for_git_dependency
|
|
131
|
+
latest_git_version_details&.fetch(:version)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
sig { returns(T.nilable(Gem::Version)) }
|
|
135
|
+
def latest_resolvable_version_for_git_dependency
|
|
136
|
+
# For git dependencies, we assume the latest version is resolvable
|
|
137
|
+
latest_version_for_git_dependency
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
141
|
+
def updated_git_requirements
|
|
142
|
+
updated_source = updated_git_source
|
|
143
|
+
return requirements unless updated_source
|
|
144
|
+
|
|
145
|
+
requirements.map do |req|
|
|
146
|
+
req.merge(source: updated_source)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
|
151
|
+
def updated_git_source
|
|
152
|
+
# Update the git tag if a new version is available
|
|
153
|
+
if git_commit_checker.pinned_ref_looks_like_version? && latest_git_version_details
|
|
154
|
+
new_tag = T.must(latest_git_version_details).fetch(:tag)
|
|
155
|
+
source_details = dependency.source_details
|
|
156
|
+
return source_details.transform_keys(&:to_sym).merge(ref: new_tag) if source_details
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Otherwise return the original source
|
|
160
|
+
dependency.source_details&.transform_keys(&:to_sym)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
|
164
|
+
def latest_git_version_details
|
|
165
|
+
@latest_git_version_details ||= T.let(
|
|
166
|
+
latest_version_finder.latest_version_tag(git_commit_checker: git_commit_checker),
|
|
167
|
+
T.nilable(T::Hash[Symbol, T.untyped])
|
|
168
|
+
)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
sig { returns(Dependabot::GitCommitChecker) }
|
|
172
|
+
def git_commit_checker
|
|
173
|
+
@git_commit_checker ||= T.let(
|
|
174
|
+
Dependabot::GitCommitChecker.new(
|
|
175
|
+
dependency: dependency,
|
|
176
|
+
credentials: credentials
|
|
177
|
+
),
|
|
178
|
+
T.nilable(Dependabot::GitCommitChecker)
|
|
179
|
+
)
|
|
180
|
+
end
|
|
181
|
+
|
|
115
182
|
sig { override.returns(T::Boolean) }
|
|
116
183
|
def latest_version_resolvable_with_full_unlock?
|
|
117
184
|
# Full unlock checks aren't implemented for Python (yet)
|
|
@@ -135,10 +202,6 @@ module Dependabot
|
|
|
135
202
|
|
|
136
203
|
sig { returns(T.untyped) }
|
|
137
204
|
def resolver
|
|
138
|
-
if Dependabot::Experiments.enabled?(:enable_file_parser_python_local)
|
|
139
|
-
Dependabot.logger.info("Python package resolver : #{resolver_type}")
|
|
140
|
-
end
|
|
141
|
-
|
|
142
205
|
case resolver_type
|
|
143
206
|
when :pip_compile then pip_compile_version_resolver
|
|
144
207
|
when :pipenv then pipenv_version_resolver
|
|
@@ -456,6 +519,7 @@ module Dependabot
|
|
|
456
519
|
dependency_files.select { |f| f.name.end_with?(".in") }
|
|
457
520
|
end
|
|
458
521
|
end
|
|
522
|
+
# rubocop:enable Metrics/ClassLength
|
|
459
523
|
end
|
|
460
524
|
end
|
|
461
525
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-python
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.359.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.359.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.359.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -291,7 +291,7 @@ licenses:
|
|
|
291
291
|
- MIT
|
|
292
292
|
metadata:
|
|
293
293
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
294
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
294
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.359.0
|
|
295
295
|
rdoc_options: []
|
|
296
296
|
require_paths:
|
|
297
297
|
- lib
|