dependabot-common 0.386.0 → 0.388.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/clients/github_release.rb +61 -0
- data/lib/dependabot/dependency_requirement.rb +62 -17
- data/lib/dependabot/error_details.rb +51 -0
- data/lib/dependabot/errors.rb +10 -6
- data/lib/dependabot/file_fetchers/base.rb +2 -2
- data/lib/dependabot/git_commit_checker/source_details.rb +42 -0
- data/lib/dependabot/git_commit_checker.rb +63 -30
- data/lib/dependabot/git_cooldown_date_resolver.rb +13 -5
- data/lib/dependabot/git_metadata_fetcher.rb +3 -9
- data/lib/dependabot/metadata_finders/base/release_finder.rb +111 -77
- data/lib/dependabot/package/release_cooldown_options.rb +1 -1
- data/lib/dependabot/pull_request_creator/branch_namer/base.rb +2 -2
- data/lib/dependabot/version.rb +9 -0
- data/lib/dependabot.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 29f29c96dbb5e187d5cdecfe015ecd60456ea004a7553a97b812416034451ebf
|
|
4
|
+
data.tar.gz: 1d6e5d04baaf18853476f074e742eb8a60113e2fdfa457db4b3019b1055b30ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2c2d09853e0044b7dd6ed6ca9f56501ee8436f113eecec3d85506d1543b79994cb3544cb5718b6f55960f7257af74848e33bc330d956275f98a2d8220f09d4d6
|
|
7
|
+
data.tar.gz: 343ab8ddca784ef0e497987de868f0b405aeeb3bfb8f11c92ad24da3b6d067981fde09397e4d6a5633e2556bfa527f594f432dc4ca9aa79cd9b2b556be930e52
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sawyer"
|
|
5
|
+
require "sorbet-runtime"
|
|
6
|
+
require "time"
|
|
7
|
+
|
|
8
|
+
module Dependabot
|
|
9
|
+
module Clients
|
|
10
|
+
# Typed view over the release fields returned by Octokit.
|
|
11
|
+
class GithubRelease < T::ImmutableStruct
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
const :id, T.nilable(Integer)
|
|
15
|
+
const :name, T.nilable(String)
|
|
16
|
+
const :tag_name, String
|
|
17
|
+
const :body, T.nilable(String)
|
|
18
|
+
const :html_url, T.nilable(String)
|
|
19
|
+
const :prerelease, T::Boolean
|
|
20
|
+
const :published_at, T.nilable(Time)
|
|
21
|
+
|
|
22
|
+
sig { params(resource: Sawyer::Resource).returns(T.nilable(GithubRelease)) }
|
|
23
|
+
def self.from_resource(resource)
|
|
24
|
+
tag_name = T.cast(resource[:tag_name], Object)
|
|
25
|
+
return unless tag_name.is_a?(String)
|
|
26
|
+
|
|
27
|
+
id = T.cast(resource[:id], Object)
|
|
28
|
+
prerelease = T.cast(resource[:prerelease], Object)
|
|
29
|
+
|
|
30
|
+
new(
|
|
31
|
+
id: id.is_a?(Integer) ? id : nil,
|
|
32
|
+
name: string_value(resource, :name),
|
|
33
|
+
tag_name: tag_name,
|
|
34
|
+
body: string_value(resource, :body),
|
|
35
|
+
html_url: string_value(resource, :html_url),
|
|
36
|
+
prerelease: prerelease == true,
|
|
37
|
+
published_at: time_value(resource, :published_at)
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
sig { params(resource: Sawyer::Resource, key: Symbol).returns(T.nilable(String)) }
|
|
42
|
+
def self.string_value(resource, key)
|
|
43
|
+
value = T.cast(resource[key], Object)
|
|
44
|
+
value.is_a?(String) ? value : nil
|
|
45
|
+
end
|
|
46
|
+
private_class_method :string_value
|
|
47
|
+
|
|
48
|
+
sig { params(resource: Sawyer::Resource, key: Symbol).returns(T.nilable(Time)) }
|
|
49
|
+
def self.time_value(resource, key)
|
|
50
|
+
value = T.cast(resource[key], Object)
|
|
51
|
+
return value if value.is_a?(Time)
|
|
52
|
+
return unless value.is_a?(String)
|
|
53
|
+
|
|
54
|
+
Time.parse(value)
|
|
55
|
+
rescue ArgumentError
|
|
56
|
+
nil
|
|
57
|
+
end
|
|
58
|
+
private_class_method :time_value
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
@@ -33,18 +33,23 @@ module Dependabot
|
|
|
33
33
|
extend T::Sig
|
|
34
34
|
extend T::Generic
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
Group = T.type_alias { T.any(String, Symbol) }
|
|
37
|
+
ObjectHash = T.type_alias { T::Hash[T.any(Symbol, String), Object] }
|
|
38
|
+
Requirement = T.type_alias { T.any(String, Symbol) }
|
|
39
|
+
Input = T.type_alias { T.any(DependencyRequirement, ObjectHash) }
|
|
40
|
+
|
|
40
41
|
K = type_member { { fixed: Symbol } }
|
|
42
|
+
# Hash-style access remains dynamic until ecosystem callers migrate to the
|
|
43
|
+
# typed readers. Keeping that compatibility here avoids a flag-day change.
|
|
44
|
+
# rubocop:disable Sorbet/ForbidTUntyped
|
|
41
45
|
V = type_member { { fixed: T.untyped } }
|
|
42
46
|
Elem = type_member { { fixed: [Symbol, T.untyped] } }
|
|
47
|
+
# rubocop:enable Sorbet/ForbidTUntyped
|
|
43
48
|
|
|
44
49
|
# Builds a DependencyRequirement from a requirement hash, symbolising
|
|
45
50
|
# top-level keys. Accepts both plain hashes and existing
|
|
46
51
|
# DependencyRequirement instances and always returns a new instance.
|
|
47
|
-
sig { params(hash:
|
|
52
|
+
sig { params(hash: Input).returns(DependencyRequirement) }
|
|
48
53
|
def self.create(hash)
|
|
49
54
|
requirement = new
|
|
50
55
|
requirement.replace(hash.keys.to_h { |k| [k.to_sym, hash[k]] })
|
|
@@ -52,16 +57,21 @@ module Dependabot
|
|
|
52
57
|
end
|
|
53
58
|
|
|
54
59
|
# The version constraint string, e.g. ">= 1.0, < 2.0". Nil when the
|
|
55
|
-
# dependency is pinned by a lockfile rather than a manifest constraint
|
|
56
|
-
|
|
60
|
+
# dependency is pinned by a lockfile rather than a manifest constraint,
|
|
61
|
+
# or :unfixable when no valid updated requirement can be generated.
|
|
62
|
+
sig { returns(T.nilable(Requirement)) }
|
|
57
63
|
def requirement
|
|
58
|
-
self[:requirement]
|
|
64
|
+
value = T.cast(self[:requirement], T.nilable(Object))
|
|
65
|
+
return if value.nil?
|
|
66
|
+
return value if value.is_a?(String) || value == :unfixable
|
|
67
|
+
|
|
68
|
+
raise TypeError, "requirement must be a string, :unfixable, or nil"
|
|
59
69
|
end
|
|
60
70
|
|
|
61
71
|
# The manifest file this requirement was declared in, e.g. "Gemfile".
|
|
62
72
|
sig { returns(T.nilable(String)) }
|
|
63
73
|
def file
|
|
64
|
-
|
|
74
|
+
optional_string(:file)
|
|
65
75
|
end
|
|
66
76
|
|
|
67
77
|
# The dependency groups this requirement belongs to, e.g. ["dev"] or
|
|
@@ -69,26 +79,61 @@ module Dependabot
|
|
|
69
79
|
# Nilable because some requirement entries are constructed with
|
|
70
80
|
# groups: nil, and the reader must reflect that to stay a drop-in for
|
|
71
81
|
# the underlying hash access under sorbet-runtime.
|
|
72
|
-
sig { returns(T.nilable(T::Array[
|
|
82
|
+
sig { returns(T.nilable(T::Array[Group])) }
|
|
73
83
|
def groups
|
|
74
|
-
self[:groups]
|
|
84
|
+
value = T.cast(self[:groups], T.nilable(Object))
|
|
85
|
+
return if value.nil?
|
|
86
|
+
raise TypeError, "groups must be an array of strings or symbols, or nil" unless value.is_a?(Array)
|
|
87
|
+
|
|
88
|
+
value.each do |raw_group|
|
|
89
|
+
group = T.cast(raw_group, Object)
|
|
90
|
+
next if group.is_a?(String) || group.is_a?(Symbol)
|
|
91
|
+
|
|
92
|
+
raise TypeError, "groups must be an array of strings or symbols, or nil"
|
|
93
|
+
end
|
|
94
|
+
value
|
|
75
95
|
end
|
|
76
96
|
|
|
77
97
|
# The source details for the dependency, e.g.
|
|
78
98
|
# { type: "git", url: "https://github.com/..." }. Keys may be symbols
|
|
79
99
|
# or strings depending on whether the requirement was built by a file
|
|
80
100
|
# parser or deserialised from a job definition.
|
|
81
|
-
sig { returns(T.nilable(
|
|
101
|
+
sig { returns(T.nilable(ObjectHash)) }
|
|
82
102
|
def source
|
|
83
|
-
|
|
103
|
+
optional_object_hash(:source)
|
|
84
104
|
end
|
|
85
105
|
|
|
86
106
|
# Optional ecosystem-specific metadata about the requirement, e.g.
|
|
87
107
|
# { property_name: "rails.version" }.
|
|
88
|
-
sig { returns(T.nilable(
|
|
108
|
+
sig { returns(T.nilable(ObjectHash)) }
|
|
89
109
|
def metadata
|
|
90
|
-
|
|
110
|
+
optional_object_hash(:metadata)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
sig { params(key: Symbol).returns(T.nilable(String)) }
|
|
116
|
+
def optional_string(key)
|
|
117
|
+
value = T.cast(self[key], T.nilable(Object))
|
|
118
|
+
return if value.nil?
|
|
119
|
+
return value if value.is_a?(String)
|
|
120
|
+
|
|
121
|
+
raise TypeError, "#{key} must be a string or nil"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
sig { params(key: Symbol).returns(T.nilable(ObjectHash)) }
|
|
125
|
+
def optional_object_hash(key)
|
|
126
|
+
value = T.cast(self[key], T.nilable(Object))
|
|
127
|
+
return if value.nil?
|
|
128
|
+
raise TypeError, "#{key} must be a hash with string or symbol keys, or nil" unless value.is_a?(Hash)
|
|
129
|
+
|
|
130
|
+
value.each_key do |raw_nested_key|
|
|
131
|
+
nested_key = T.cast(raw_nested_key, Object)
|
|
132
|
+
next if nested_key.is_a?(String) || nested_key.is_a?(Symbol)
|
|
133
|
+
|
|
134
|
+
raise TypeError, "#{key} must be a hash with string or symbol keys, or nil"
|
|
135
|
+
end
|
|
136
|
+
value
|
|
91
137
|
end
|
|
92
|
-
# rubocop:enable Sorbet/ForbidTUntyped
|
|
93
138
|
end
|
|
94
139
|
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
module Dependabot
|
|
7
|
+
class ErrorDetails < T::ImmutableStruct
|
|
8
|
+
extend T::Sig
|
|
9
|
+
|
|
10
|
+
DetailHash = T.type_alias { T::Hash[T.any(String, Symbol), T.anything] }
|
|
11
|
+
Detail = T.type_alias { T.any(String, DetailHash) }
|
|
12
|
+
|
|
13
|
+
const :error_type, String
|
|
14
|
+
const :error_detail, T.nilable(Detail)
|
|
15
|
+
|
|
16
|
+
sig { params(hash: T::Hash[Symbol, T.anything]).returns(ErrorDetails) }
|
|
17
|
+
def self.from_hash(hash)
|
|
18
|
+
raw_type = T.cast(hash[:"error-type"], Object)
|
|
19
|
+
raise TypeError, "error-type must be a string" unless raw_type.is_a?(String)
|
|
20
|
+
|
|
21
|
+
new(
|
|
22
|
+
error_type: raw_type,
|
|
23
|
+
error_detail: parse_detail(T.cast(hash[:"error-detail"], T.nilable(Object)))
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
sig { returns(T::Hash[Symbol, Object]) }
|
|
28
|
+
def to_h
|
|
29
|
+
result = T.let({ "error-type": error_type }, T::Hash[Symbol, Object])
|
|
30
|
+
result[:"error-detail"] = error_detail if error_detail
|
|
31
|
+
result
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
sig { params(value: T.nilable(Object)).returns(T.nilable(Detail)) }
|
|
35
|
+
def self.parse_detail(value)
|
|
36
|
+
return if value.nil?
|
|
37
|
+
return value if value.is_a?(String)
|
|
38
|
+
raise TypeError, "error-detail must be a string or hash" unless value.is_a?(Hash)
|
|
39
|
+
|
|
40
|
+
result = T.let({}, DetailHash)
|
|
41
|
+
value.each do |raw_key, raw_value|
|
|
42
|
+
key = T.cast(raw_key, Object)
|
|
43
|
+
raise TypeError, "error-detail keys must be strings or symbols" unless key.is_a?(String) || key.is_a?(Symbol)
|
|
44
|
+
|
|
45
|
+
result[key] = T.cast(raw_value, Object)
|
|
46
|
+
end
|
|
47
|
+
result
|
|
48
|
+
end
|
|
49
|
+
private_class_method :parse_detail
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/dependabot/errors.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
5
|
+
require "dependabot/error_details"
|
|
5
6
|
require "dependabot/utils"
|
|
6
7
|
|
|
7
8
|
# rubocop:disable Metrics/ModuleLength
|
|
@@ -23,7 +24,7 @@ module Dependabot
|
|
|
23
24
|
|
|
24
25
|
# rubocop:disable Metrics/MethodLength
|
|
25
26
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|
26
|
-
sig { params(error: StandardError).returns(T.nilable(
|
|
27
|
+
sig { params(error: StandardError).returns(T.nilable(Dependabot::ErrorDetails)) }
|
|
27
28
|
def self.fetcher_error_details(error)
|
|
28
29
|
case error
|
|
29
30
|
when Dependabot::ToolVersionNotSupported
|
|
@@ -138,11 +139,12 @@ module Dependabot
|
|
|
138
139
|
"rate-limit-reset": T.cast(error, Octokit::Error).response_headers["X-RateLimit-Reset"]
|
|
139
140
|
}
|
|
140
141
|
}
|
|
141
|
-
end
|
|
142
|
+
end => details
|
|
143
|
+
Dependabot::ErrorDetails.from_hash(details) if details
|
|
142
144
|
end
|
|
143
145
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
144
146
|
|
|
145
|
-
sig { params(error: StandardError).returns(T.nilable(
|
|
147
|
+
sig { params(error: StandardError).returns(T.nilable(Dependabot::ErrorDetails)) }
|
|
146
148
|
def self.parser_error_details(error)
|
|
147
149
|
case error
|
|
148
150
|
when Dependabot::ToolFeatureNotSupported
|
|
@@ -220,13 +222,14 @@ module Dependabot
|
|
|
220
222
|
# and responsibility for fixing it is on them, not us. As a result we
|
|
221
223
|
# quietly log these as errors
|
|
222
224
|
{ "error-type": "server_error" }
|
|
223
|
-
end
|
|
225
|
+
end => details
|
|
226
|
+
Dependabot::ErrorDetails.from_hash(details) if details
|
|
224
227
|
end
|
|
225
228
|
|
|
226
229
|
# rubocop:disable Lint/RedundantCopDisableDirective
|
|
227
230
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|
228
231
|
# rubocop:disable Metrics/AbcSize
|
|
229
|
-
sig { params(error: StandardError).returns(T.nilable(
|
|
232
|
+
sig { params(error: StandardError).returns(T.nilable(Dependabot::ErrorDetails)) }
|
|
230
233
|
def self.updater_error_details(error)
|
|
231
234
|
case error
|
|
232
235
|
when Dependabot::ToolFeatureNotSupported
|
|
@@ -400,7 +403,8 @@ module Dependabot
|
|
|
400
403
|
"rate-limit-reset": T.cast(error, Octokit::Error).response_headers["X-RateLimit-Reset"]
|
|
401
404
|
}
|
|
402
405
|
}
|
|
403
|
-
end
|
|
406
|
+
end => details
|
|
407
|
+
Dependabot::ErrorDetails.from_hash(details) if details
|
|
404
408
|
end
|
|
405
409
|
|
|
406
410
|
# rubocop:enable Metrics/MethodLength
|
|
@@ -70,7 +70,7 @@ module Dependabot
|
|
|
70
70
|
sig { returns(T.nilable(String)) }
|
|
71
71
|
attr_reader :repo_contents_path
|
|
72
72
|
|
|
73
|
-
sig { returns(T::Hash[
|
|
73
|
+
sig { returns(T::Hash[Symbol, Object]) }
|
|
74
74
|
attr_reader :options
|
|
75
75
|
|
|
76
76
|
CLIENT_NOT_FOUND_ERRORS = T.let(
|
|
@@ -135,7 +135,7 @@ module Dependabot
|
|
|
135
135
|
source: Dependabot::Source,
|
|
136
136
|
credentials: T::Array[Dependabot::Credential],
|
|
137
137
|
repo_contents_path: T.nilable(String),
|
|
138
|
-
options: T::Hash[
|
|
138
|
+
options: T::Hash[Symbol, Object],
|
|
139
139
|
update_config: T.nilable(Dependabot::Config::UpdateConfig)
|
|
140
140
|
)
|
|
141
141
|
.void
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
module Dependabot
|
|
7
|
+
class GitCommitChecker
|
|
8
|
+
# Typed view over the source hash attached to a git dependency.
|
|
9
|
+
class SourceDetails < T::ImmutableStruct
|
|
10
|
+
extend T::Sig
|
|
11
|
+
|
|
12
|
+
const :type, T.nilable(String)
|
|
13
|
+
const :url, T.nilable(String)
|
|
14
|
+
const :branch, T.nilable(String)
|
|
15
|
+
const :ref, T.nilable(String)
|
|
16
|
+
|
|
17
|
+
sig do
|
|
18
|
+
params(details: T::Hash[T.any(String, Symbol), Object]).returns(SourceDetails)
|
|
19
|
+
end
|
|
20
|
+
def self.from_hash(details)
|
|
21
|
+
new(
|
|
22
|
+
type: string_value(details, :type),
|
|
23
|
+
url: string_value(details, :url),
|
|
24
|
+
branch: string_value(details, :branch),
|
|
25
|
+
ref: string_value(details, :ref)
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
sig do
|
|
30
|
+
params(
|
|
31
|
+
details: T::Hash[T.any(String, Symbol), Object],
|
|
32
|
+
key: Symbol
|
|
33
|
+
).returns(T.nilable(String))
|
|
34
|
+
end
|
|
35
|
+
def self.string_value(details, key)
|
|
36
|
+
value = details.key?(key) ? details[key] : details[key.to_s]
|
|
37
|
+
value.is_a?(String) ? value : nil
|
|
38
|
+
end
|
|
39
|
+
private_class_method :string_value
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "excon"
|
|
@@ -14,7 +14,9 @@ require "dependabot/utils"
|
|
|
14
14
|
require "dependabot/source"
|
|
15
15
|
require "dependabot/dependency"
|
|
16
16
|
require "dependabot/credential"
|
|
17
|
+
require "dependabot/clients/github_release"
|
|
17
18
|
require "dependabot/git_metadata_fetcher"
|
|
19
|
+
require "dependabot/git_commit_checker/source_details"
|
|
18
20
|
require "dependabot/git_tag_details"
|
|
19
21
|
require "dependabot/package/package_release"
|
|
20
22
|
require "dependabot/package/release_cooldown_options"
|
|
@@ -46,7 +48,7 @@ module Dependabot
|
|
|
46
48
|
ignored_versions: T::Array[String],
|
|
47
49
|
raise_on_ignored: T::Boolean,
|
|
48
50
|
consider_version_branches_pinned: T::Boolean,
|
|
49
|
-
dependency_source_details: T.nilable(T::Hash[Symbol,
|
|
51
|
+
dependency_source_details: T.nilable(T::Hash[Symbol, Object])
|
|
50
52
|
)
|
|
51
53
|
.void
|
|
52
54
|
end
|
|
@@ -63,14 +65,15 @@ module Dependabot
|
|
|
63
65
|
@ignored_versions = ignored_versions
|
|
64
66
|
@raise_on_ignored = raise_on_ignored
|
|
65
67
|
@consider_version_branches_pinned = consider_version_branches_pinned
|
|
66
|
-
@dependency_source_details =
|
|
68
|
+
@dependency_source_details = T.let(
|
|
69
|
+
dependency_source_details && SourceDetails.from_hash(dependency_source_details),
|
|
70
|
+
T.nilable(SourceDetails)
|
|
71
|
+
)
|
|
67
72
|
end
|
|
68
73
|
|
|
69
74
|
sig { returns(T::Boolean) }
|
|
70
75
|
def git_dependency?
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
dependency_source_details&.fetch(:type) == "git"
|
|
76
|
+
dependency_source_details&.type == "git"
|
|
74
77
|
end
|
|
75
78
|
|
|
76
79
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
@@ -78,7 +81,7 @@ module Dependabot
|
|
|
78
81
|
def pinned?
|
|
79
82
|
raise "Not a git dependency!" unless git_dependency?
|
|
80
83
|
|
|
81
|
-
branch = dependency_source_details&.
|
|
84
|
+
branch = dependency_source_details&.branch
|
|
82
85
|
|
|
83
86
|
return false if ref.nil?
|
|
84
87
|
return false if branch == ref
|
|
@@ -118,7 +121,7 @@ module Dependabot
|
|
|
118
121
|
sig { returns(T::Array[GitRef]) }
|
|
119
122
|
def tags
|
|
120
123
|
GitMetadataFetcher.new(
|
|
121
|
-
url:
|
|
124
|
+
url: T.must(source_details&.url),
|
|
122
125
|
credentials: credentials
|
|
123
126
|
).tags
|
|
124
127
|
end
|
|
@@ -128,7 +131,7 @@ module Dependabot
|
|
|
128
131
|
T.must(
|
|
129
132
|
T.let(
|
|
130
133
|
GitMetadataFetcher.new(
|
|
131
|
-
url:
|
|
134
|
+
url: T.must(source_details&.url),
|
|
132
135
|
credentials: credentials
|
|
133
136
|
).ref_details_for_pinned_ref(ref),
|
|
134
137
|
T.nilable(Excon::Response)
|
|
@@ -282,9 +285,12 @@ module Dependabot
|
|
|
282
285
|
false
|
|
283
286
|
end
|
|
284
287
|
|
|
285
|
-
sig { returns(T.nilable(
|
|
288
|
+
sig { returns(T.nilable(SourceDetails)) }
|
|
286
289
|
def dependency_source_details
|
|
287
|
-
@dependency_source_details
|
|
290
|
+
@dependency_source_details ||= begin
|
|
291
|
+
details = dependency.source_details(allowed_types: ["git"])
|
|
292
|
+
SourceDetails.from_hash(details) if details
|
|
293
|
+
end
|
|
288
294
|
end
|
|
289
295
|
|
|
290
296
|
sig { returns(T::Array[Dependabot::GitTagWithDetail]) }
|
|
@@ -333,7 +339,7 @@ module Dependabot
|
|
|
333
339
|
|
|
334
340
|
sig { override.returns(T.nilable(String)) }
|
|
335
341
|
def cooldown_source_url
|
|
336
|
-
dependency_source_details&.
|
|
342
|
+
dependency_source_details&.url
|
|
337
343
|
end
|
|
338
344
|
|
|
339
345
|
sig { override.returns(T::Array[Dependabot::Credential]) }
|
|
@@ -478,9 +484,11 @@ module Dependabot
|
|
|
478
484
|
|
|
479
485
|
sig { params(tags: T::Array[Dependabot::GitRef]).returns(T::Array[Dependabot::GitRef]) }
|
|
480
486
|
def handle_tag_prefix(tags)
|
|
481
|
-
if dependency_source_details&.
|
|
487
|
+
if dependency_source_details&.ref&.start_with?("tags/")
|
|
482
488
|
tags = tags.map do |tag|
|
|
483
|
-
|
|
489
|
+
duplicated_tag = tag.dup
|
|
490
|
+
duplicated_tag.name = "tags/#{tag.name}"
|
|
491
|
+
duplicated_tag
|
|
484
492
|
end
|
|
485
493
|
end
|
|
486
494
|
|
|
@@ -519,8 +527,11 @@ module Dependabot
|
|
|
519
527
|
client = Clients::GithubWithRetries
|
|
520
528
|
.for_github_dot_com(credentials: credentials)
|
|
521
529
|
|
|
522
|
-
|
|
523
|
-
T.
|
|
530
|
+
comparison = client.compare(T.must(listing_source_repo), ref1, ref2)
|
|
531
|
+
status = T.cast(comparison[:status], Object)
|
|
532
|
+
raise TypeError, "GitHub comparison status must be a string" unless status.is_a?(String)
|
|
533
|
+
|
|
534
|
+
status
|
|
524
535
|
end
|
|
525
536
|
|
|
526
537
|
sig { params(ref1: String, ref2: String).returns(String) }
|
|
@@ -529,9 +540,11 @@ module Dependabot
|
|
|
529
540
|
.for_gitlab_dot_com(credentials: credentials)
|
|
530
541
|
|
|
531
542
|
comparison = client.compare(T.must(listing_source_repo), ref1, ref2)
|
|
543
|
+
commits = T.cast(comparison["commits"], Object)
|
|
544
|
+
raise TypeError, "GitLab comparison commits must be an array" unless commits.is_a?(Array)
|
|
532
545
|
|
|
533
|
-
if
|
|
534
|
-
elsif T.
|
|
546
|
+
if commits.empty? then "behind"
|
|
547
|
+
elsif T.cast(comparison["compare_same_ref"], Object) == true then "identical"
|
|
535
548
|
else
|
|
536
549
|
"ahead"
|
|
537
550
|
end
|
|
@@ -550,7 +563,13 @@ module Dependabot
|
|
|
550
563
|
|
|
551
564
|
# Conservatively assume that ref2 is ahead in the equality case, of
|
|
552
565
|
# if we get an unexpected format (e.g., due to a 404)
|
|
553
|
-
|
|
566
|
+
comparison = T.cast(JSON.parse(response.body), Object)
|
|
567
|
+
raise TypeError, "Bitbucket comparison must be a hash" unless comparison.is_a?(Hash)
|
|
568
|
+
|
|
569
|
+
values = T.cast(comparison.fetch("values", ["x"]), Object)
|
|
570
|
+
raise TypeError, "Bitbucket comparison values must be an array" unless values.is_a?(Array)
|
|
571
|
+
|
|
572
|
+
if values.empty? then "behind"
|
|
554
573
|
else
|
|
555
574
|
"ahead"
|
|
556
575
|
end
|
|
@@ -558,12 +577,12 @@ module Dependabot
|
|
|
558
577
|
|
|
559
578
|
sig { returns(T.nilable(String)) }
|
|
560
579
|
def ref_or_branch
|
|
561
|
-
ref || dependency_source_details&.
|
|
580
|
+
ref || dependency_source_details&.branch
|
|
562
581
|
end
|
|
563
582
|
|
|
564
583
|
sig { returns(T.nilable(String)) }
|
|
565
584
|
def ref
|
|
566
|
-
dependency_source_details&.
|
|
585
|
+
dependency_source_details&.ref
|
|
567
586
|
end
|
|
568
587
|
|
|
569
588
|
sig { params(tag: String).returns(T::Boolean) }
|
|
@@ -667,9 +686,11 @@ module Dependabot
|
|
|
667
686
|
begin
|
|
668
687
|
tags = listing_repo_git_metadata_fetcher.tags
|
|
669
688
|
|
|
670
|
-
if dependency_source_details&.
|
|
689
|
+
if dependency_source_details&.ref&.start_with?("tags/")
|
|
671
690
|
tags = tags.map do |tag|
|
|
672
|
-
|
|
691
|
+
duplicated_tag = tag.dup
|
|
692
|
+
duplicated_tag.name = "tags/#{tag.name}"
|
|
693
|
+
duplicated_tag
|
|
673
694
|
end
|
|
674
695
|
end
|
|
675
696
|
|
|
@@ -695,7 +716,7 @@ module Dependabot
|
|
|
695
716
|
|
|
696
717
|
sig { returns(T::Boolean) }
|
|
697
718
|
def wants_prerelease?
|
|
698
|
-
return false unless dependency_source_details&.
|
|
719
|
+
return false unless dependency_source_details&.ref
|
|
699
720
|
return false unless pinned_ref_looks_like_version?
|
|
700
721
|
|
|
701
722
|
version = version_from_ref(T.must(ref))
|
|
@@ -732,7 +753,7 @@ module Dependabot
|
|
|
732
753
|
false
|
|
733
754
|
end
|
|
734
755
|
|
|
735
|
-
sig { returns(T::Array[
|
|
756
|
+
sig { returns(T::Array[Dependabot::Clients::GithubRelease]) }
|
|
736
757
|
def github_releases
|
|
737
758
|
@github_releases ||= T.let(
|
|
738
759
|
begin
|
|
@@ -747,11 +768,17 @@ module Dependabot
|
|
|
747
768
|
)
|
|
748
769
|
# The Octokit RBI types this as non-nil, but it can be nil at runtime
|
|
749
770
|
# (e.g. an empty/unexpected registry response), so guard against it.
|
|
750
|
-
|
|
771
|
+
releases = T.let(
|
|
772
|
+
client.releases(T.must(source).repo, per_page: 100),
|
|
773
|
+
T.nilable(T::Array[Sawyer::Resource])
|
|
774
|
+
)
|
|
775
|
+
(releases || []).filter_map do |release|
|
|
776
|
+
Dependabot::Clients::GithubRelease.from_resource(release)
|
|
777
|
+
end
|
|
751
778
|
rescue Octokit::Error
|
|
752
779
|
[]
|
|
753
780
|
end,
|
|
754
|
-
T.nilable(T::Array[
|
|
781
|
+
T.nilable(T::Array[Dependabot::Clients::GithubRelease])
|
|
755
782
|
)
|
|
756
783
|
end
|
|
757
784
|
|
|
@@ -892,7 +919,7 @@ module Dependabot
|
|
|
892
919
|
@local_repo_git_metadata_fetcher ||=
|
|
893
920
|
T.let(
|
|
894
921
|
GitMetadataFetcher.new(
|
|
895
|
-
url: dependency_source_details&.
|
|
922
|
+
url: T.must(dependency_source_details&.url),
|
|
896
923
|
credentials: credentials
|
|
897
924
|
),
|
|
898
925
|
T.nilable(Dependabot::GitMetadataFetcher)
|
|
@@ -913,8 +940,14 @@ module Dependabot
|
|
|
913
940
|
|
|
914
941
|
sig { returns(String) }
|
|
915
942
|
def ref_pinned
|
|
916
|
-
|
|
917
|
-
|
|
943
|
+
details = source_details
|
|
944
|
+
details&.ref || details&.branch || "HEAD"
|
|
945
|
+
end
|
|
946
|
+
|
|
947
|
+
sig { returns(T.nilable(SourceDetails)) }
|
|
948
|
+
def source_details
|
|
949
|
+
details = dependency.source_details
|
|
950
|
+
SourceDetails.from_hash(details) if details
|
|
918
951
|
end
|
|
919
952
|
end
|
|
920
953
|
# rubocop:enable Metrics/ClassLength
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
5
|
+
require "dependabot/clients/github_release"
|
|
5
6
|
require "dependabot/clients/github_with_retries"
|
|
6
7
|
require "dependabot/shared_helpers"
|
|
7
8
|
require "dependabot/source"
|
|
@@ -45,7 +46,8 @@ module Dependabot
|
|
|
45
46
|
releases = cached_github_releases
|
|
46
47
|
unless releases.empty?
|
|
47
48
|
release = releases.find { |r| r.tag_name == tag_name }
|
|
48
|
-
|
|
49
|
+
published_at = release&.published_at
|
|
50
|
+
return published_at if published_at
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
tag_creation_date(tag_name, commit_sha)
|
|
@@ -88,7 +90,7 @@ module Dependabot
|
|
|
88
90
|
|
|
89
91
|
# Fetches and caches GitHub releases for the dependency source.
|
|
90
92
|
# Returns an empty array for non-GitHub sources.
|
|
91
|
-
sig { returns(T::Array[
|
|
93
|
+
sig { returns(T::Array[Dependabot::Clients::GithubRelease]) }
|
|
92
94
|
def cached_github_releases
|
|
93
95
|
@cached_github_releases ||= T.let(
|
|
94
96
|
begin
|
|
@@ -99,7 +101,13 @@ module Dependabot
|
|
|
99
101
|
source: T.must(source),
|
|
100
102
|
credentials: cooldown_credentials
|
|
101
103
|
)
|
|
102
|
-
|
|
104
|
+
releases = T.let(
|
|
105
|
+
client.releases(T.must(source).repo, per_page: 100),
|
|
106
|
+
T.nilable(T::Array[Sawyer::Resource])
|
|
107
|
+
)
|
|
108
|
+
(releases || []).filter_map do |release|
|
|
109
|
+
Dependabot::Clients::GithubRelease.from_resource(release)
|
|
110
|
+
end
|
|
103
111
|
else
|
|
104
112
|
[]
|
|
105
113
|
end
|
|
@@ -107,7 +115,7 @@ module Dependabot
|
|
|
107
115
|
Dependabot.logger.debug("Error fetching GitHub releases: #{e.message}")
|
|
108
116
|
[]
|
|
109
117
|
end,
|
|
110
|
-
T.nilable(T::Array[
|
|
118
|
+
T.nilable(T::Array[Dependabot::Clients::GithubRelease])
|
|
111
119
|
)
|
|
112
120
|
end
|
|
113
121
|
end
|
|
@@ -147,12 +147,6 @@ module Dependabot
|
|
|
147
147
|
raise "Unexpected response: #{response_with_git.status} - #{response_with_git.body}"
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
if uri.match?(/github\.com/i)
|
|
151
|
-
response = response_with_git.data
|
|
152
|
-
response[:response_headers] = response[:headers] unless response.nil?
|
|
153
|
-
raise Octokit::Error.from_response(response)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
150
|
raise "Server error at #{uri}: #{response_with_git.body}" if response_with_git.status >= 500
|
|
157
151
|
|
|
158
152
|
raise Dependabot::GitDependenciesNotReachable, [uri]
|
|
@@ -213,7 +207,7 @@ module Dependabot
|
|
|
213
207
|
)
|
|
214
208
|
end
|
|
215
209
|
|
|
216
|
-
sig { params(uri: String).returns(
|
|
210
|
+
sig { params(uri: String).returns(GitResponse) }
|
|
217
211
|
def fetch_raw_upload_pack_with_git_for(uri)
|
|
218
212
|
service_pack_uri = uri
|
|
219
213
|
service_pack_uri += ".git" unless service_pack_uri.end_with?(".git") || skip_git_suffix(uri)
|
|
@@ -329,7 +323,7 @@ module Dependabot
|
|
|
329
323
|
T.must(line.split.first).chars.last(40).join
|
|
330
324
|
end
|
|
331
325
|
|
|
332
|
-
sig { returns(T::Hash[Symbol,
|
|
326
|
+
sig { returns(T::Hash[Symbol, Object]) }
|
|
333
327
|
def excon_defaults
|
|
334
328
|
# Some git hosts are slow when returning a large number of tags
|
|
335
329
|
SharedHelpers.excon_defaults(read_timeout: 20)
|
|
@@ -344,7 +338,7 @@ module Dependabot
|
|
|
344
338
|
|
|
345
339
|
# Added method to fetch tags with their creation dates from a git repository. In case
|
|
346
340
|
# private registry is used, it will clone the repository and fetch tags with their creation dates.
|
|
347
|
-
sig { params(uri: String).returns(
|
|
341
|
+
sig { params(uri: String).returns(GitResponse) }
|
|
348
342
|
def fetch_tags_with_detail_from_git_for(uri)
|
|
349
343
|
uri_ending_with_git = uri
|
|
350
344
|
uri_ending_with_git += ".git" unless uri_ending_with_git.end_with?(".git") || skip_git_suffix(uri)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
5
|
+
require "time"
|
|
5
6
|
|
|
6
7
|
require "dependabot/credential"
|
|
8
|
+
require "dependabot/clients/github_release"
|
|
7
9
|
require "dependabot/clients/github_with_retries"
|
|
8
10
|
require "dependabot/clients/gitlab_with_retries"
|
|
9
11
|
require "dependabot/metadata_finders/base"
|
|
@@ -12,40 +14,62 @@ require "dependabot/utils"
|
|
|
12
14
|
module Dependabot
|
|
13
15
|
module MetadataFinders
|
|
14
16
|
class Base
|
|
15
|
-
class GitLabRelease
|
|
17
|
+
class GitLabRelease < T::ImmutableStruct
|
|
16
18
|
extend T::Sig
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
sig { returns(String) }
|
|
25
|
-
attr_reader :body
|
|
26
|
-
|
|
27
|
-
sig { returns(String) }
|
|
28
|
-
attr_reader :html_url
|
|
20
|
+
const :name, String
|
|
21
|
+
const :tag_name, String
|
|
22
|
+
const :body, T.nilable(String)
|
|
23
|
+
const :html_url, String
|
|
24
|
+
const :authored_at, Time
|
|
29
25
|
|
|
30
26
|
sig do
|
|
31
27
|
params(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
html_url: String
|
|
36
|
-
).void
|
|
37
|
-
end
|
|
38
|
-
def initialize(name:, tag_name:, body:, html_url:)
|
|
39
|
-
@name = name
|
|
40
|
-
@tag_name = tag_name
|
|
41
|
-
@body = body
|
|
42
|
-
@html_url = html_url
|
|
28
|
+
tag: Gitlab::ObjectifiedHash,
|
|
29
|
+
source_url: String
|
|
30
|
+
).returns(T.nilable(GitLabRelease))
|
|
43
31
|
end
|
|
32
|
+
def self.from_tag(tag, source_url:)
|
|
33
|
+
name = T.cast(tag["name"], Object)
|
|
34
|
+
release = T.cast(tag["release"], Object)
|
|
35
|
+
commit = T.cast(tag["commit"], Object)
|
|
36
|
+
return unless name.is_a?(String)
|
|
37
|
+
return unless release.is_a?(Gitlab::ObjectifiedHash)
|
|
38
|
+
return unless commit.is_a?(Gitlab::ObjectifiedHash)
|
|
39
|
+
|
|
40
|
+
tag_name = T.cast(release["tag_name"], Object)
|
|
41
|
+
return unless tag_name.is_a?(String)
|
|
42
|
+
|
|
43
|
+
authored_at = time_value(T.cast(commit["authored_date"], Object))
|
|
44
|
+
return unless authored_at
|
|
45
|
+
|
|
46
|
+
description = T.cast(release["description"], Object)
|
|
47
|
+
new(
|
|
48
|
+
name: name,
|
|
49
|
+
tag_name: tag_name,
|
|
50
|
+
body: description.is_a?(String) ? description : nil,
|
|
51
|
+
html_url: "#{source_url}/tags/#{name}",
|
|
52
|
+
authored_at: authored_at
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
sig { params(value: Object).returns(T.nilable(Time)) }
|
|
57
|
+
def self.time_value(value)
|
|
58
|
+
return value if value.is_a?(Time)
|
|
59
|
+
return unless value.is_a?(String)
|
|
60
|
+
|
|
61
|
+
Time.parse(value)
|
|
62
|
+
rescue ArgumentError
|
|
63
|
+
nil
|
|
64
|
+
end
|
|
65
|
+
private_class_method :time_value
|
|
44
66
|
end
|
|
45
67
|
|
|
46
68
|
class ReleaseFinder
|
|
47
69
|
extend T::Sig
|
|
48
70
|
|
|
71
|
+
ReleaseType = T.type_alias { T.any(Dependabot::Clients::GithubRelease, GitLabRelease) }
|
|
72
|
+
|
|
49
73
|
sig { returns(Dependabot::Dependency) }
|
|
50
74
|
attr_reader :dependency
|
|
51
75
|
|
|
@@ -98,14 +122,13 @@ module Dependabot
|
|
|
98
122
|
|
|
99
123
|
private
|
|
100
124
|
|
|
101
|
-
sig { returns(T::Array[
|
|
125
|
+
sig { returns(T::Array[ReleaseType]) }
|
|
102
126
|
def all_dep_releases
|
|
103
127
|
releases = all_releases
|
|
104
128
|
dep_prefix = dependency.name.downcase
|
|
105
129
|
|
|
106
130
|
releases_with_dependency_name =
|
|
107
131
|
releases
|
|
108
|
-
.reject { |r| r.tag_name.nil? }
|
|
109
132
|
.select { |r| r.tag_name.start_with?(dep_prefix) }
|
|
110
133
|
|
|
111
134
|
return releases unless releases_with_dependency_name.any?
|
|
@@ -113,12 +136,12 @@ module Dependabot
|
|
|
113
136
|
releases_with_dependency_name
|
|
114
137
|
end
|
|
115
138
|
|
|
116
|
-
sig { returns(T::Array[
|
|
139
|
+
sig { returns(T::Array[ReleaseType]) }
|
|
117
140
|
def all_releases
|
|
118
|
-
@all_releases ||= T.let(fetch_dependency_releases, T.nilable(T::Array[
|
|
141
|
+
@all_releases ||= T.let(fetch_dependency_releases, T.nilable(T::Array[ReleaseType]))
|
|
119
142
|
end
|
|
120
143
|
|
|
121
|
-
sig { returns(T.nilable(T::Array[
|
|
144
|
+
sig { returns(T.nilable(T::Array[ReleaseType])) }
|
|
122
145
|
def relevant_releases
|
|
123
146
|
releases = releases_since_previous_version
|
|
124
147
|
|
|
@@ -139,7 +162,7 @@ module Dependabot
|
|
|
139
162
|
end
|
|
140
163
|
end
|
|
141
164
|
|
|
142
|
-
sig { returns(T.nilable(T::Array[
|
|
165
|
+
sig { returns(T.nilable(T::Array[ReleaseType])) }
|
|
143
166
|
def releases_since_previous_version
|
|
144
167
|
return [updated_release].compact unless previous_version
|
|
145
168
|
|
|
@@ -158,21 +181,21 @@ module Dependabot
|
|
|
158
181
|
end
|
|
159
182
|
end
|
|
160
183
|
|
|
161
|
-
sig { params(releases: T::Array[
|
|
184
|
+
sig { params(releases: T::Array[ReleaseType]).returns(T.nilable(T::Array[ReleaseType])) }
|
|
162
185
|
def filter_releases_using_previous_release(releases)
|
|
163
186
|
return releases if releases.index(previous_release).nil?
|
|
164
187
|
|
|
165
188
|
releases.first(T.must(releases.index(previous_release)))
|
|
166
189
|
end
|
|
167
190
|
|
|
168
|
-
sig { params(releases: T::Array[
|
|
191
|
+
sig { params(releases: T::Array[ReleaseType]).returns(T.nilable(T::Array[ReleaseType])) }
|
|
169
192
|
def filter_releases_using_updated_release(releases)
|
|
170
193
|
return releases if releases.index(updated_release).nil?
|
|
171
194
|
|
|
172
195
|
releases[releases.index(updated_release)..-1]
|
|
173
196
|
end
|
|
174
197
|
|
|
175
|
-
sig { params(releases: T::Array[
|
|
198
|
+
sig { params(releases: T::Array[ReleaseType], conservative: T::Boolean).returns(T::Array[ReleaseType]) }
|
|
176
199
|
def filter_releases_using_previous_version(releases, conservative:)
|
|
177
200
|
releases.reject do |release|
|
|
178
201
|
cleaned_tag = release.tag_name.gsub(/^[^0-9]*/, "")
|
|
@@ -193,7 +216,7 @@ module Dependabot
|
|
|
193
216
|
end
|
|
194
217
|
end
|
|
195
218
|
|
|
196
|
-
sig { params(releases: T::Array[
|
|
219
|
+
sig { params(releases: T::Array[ReleaseType], conservative: T::Boolean).returns(T::Array[ReleaseType]) }
|
|
197
220
|
def filter_releases_using_updated_version(releases, conservative:)
|
|
198
221
|
updated_version = version_class.new(new_version)
|
|
199
222
|
|
|
@@ -216,17 +239,17 @@ module Dependabot
|
|
|
216
239
|
end
|
|
217
240
|
end
|
|
218
241
|
|
|
219
|
-
sig { returns(T.
|
|
242
|
+
sig { returns(T.nilable(ReleaseType)) }
|
|
220
243
|
def updated_release
|
|
221
244
|
release_for_version(new_version)
|
|
222
245
|
end
|
|
223
246
|
|
|
224
|
-
sig { returns(T.
|
|
247
|
+
sig { returns(T.nilable(ReleaseType)) }
|
|
225
248
|
def previous_release
|
|
226
249
|
release_for_version(previous_version)
|
|
227
250
|
end
|
|
228
251
|
|
|
229
|
-
sig { params(version: T.nilable(String)).returns(T.
|
|
252
|
+
sig { params(version: T.nilable(String)).returns(T.nilable(ReleaseType)) }
|
|
230
253
|
def release_for_version(version)
|
|
231
254
|
return nil unless version
|
|
232
255
|
|
|
@@ -236,22 +259,23 @@ module Dependabot
|
|
|
236
259
|
all_dep_releases.find { |r| release_regex.match?(r.name.to_s) }
|
|
237
260
|
end
|
|
238
261
|
|
|
239
|
-
sig { params(release:
|
|
262
|
+
sig { params(release: ReleaseType).returns(String) }
|
|
240
263
|
def serialize_release(release)
|
|
241
|
-
|
|
242
|
-
title = "## #{
|
|
243
|
-
body = if
|
|
264
|
+
name = release.name
|
|
265
|
+
title = "## #{name.to_s == '' ? release.tag_name : name}\n"
|
|
266
|
+
body = if release.body.to_s.gsub(/\n*\z/m, "") == ""
|
|
244
267
|
"No release notes provided."
|
|
245
268
|
else
|
|
246
|
-
|
|
269
|
+
T.must(release.body).gsub(/\n*\z/m, "")
|
|
247
270
|
end
|
|
248
271
|
|
|
249
|
-
release_body_includes_title?(
|
|
272
|
+
release_body_includes_title?(release) ? body : title + body
|
|
250
273
|
end
|
|
251
274
|
|
|
252
|
-
sig { params(release:
|
|
275
|
+
sig { params(release: ReleaseType).returns(T::Boolean) }
|
|
253
276
|
def release_body_includes_title?(release)
|
|
254
|
-
|
|
277
|
+
name = release.name
|
|
278
|
+
title = name.nil? || name.empty? ? release.tag_name : name
|
|
255
279
|
release.body.to_s.match?(/\A\s*\#*\s*#{Regexp.quote(title)}/m)
|
|
256
280
|
end
|
|
257
281
|
|
|
@@ -265,7 +289,7 @@ module Dependabot
|
|
|
265
289
|
dependency.version_class
|
|
266
290
|
end
|
|
267
291
|
|
|
268
|
-
sig { returns(T::Array[
|
|
292
|
+
sig { returns(T::Array[ReleaseType]) }
|
|
269
293
|
def fetch_dependency_releases
|
|
270
294
|
return [] unless source
|
|
271
295
|
|
|
@@ -279,47 +303,45 @@ module Dependabot
|
|
|
279
303
|
end
|
|
280
304
|
end
|
|
281
305
|
|
|
282
|
-
sig { returns(T::Array[
|
|
306
|
+
sig { returns(T::Array[Dependabot::Clients::GithubRelease]) }
|
|
283
307
|
def fetch_github_releases
|
|
284
|
-
releases =
|
|
285
|
-
|
|
286
|
-
# Remove any releases without a tag name. These are draft releases and
|
|
287
|
-
# aren't yet associated with a tag, so shouldn't be used.
|
|
288
|
-
releases = releases.reject { |r| T.unsafe(r).tag_name.nil? }
|
|
308
|
+
releases = parsed_github_releases
|
|
289
309
|
|
|
290
310
|
clean_release_names =
|
|
291
|
-
releases.map { |
|
|
311
|
+
releases.map { |release| release.tag_name.gsub(/^[^0-9\.]*/, "") }
|
|
292
312
|
|
|
293
313
|
if clean_release_names.all? { |nm| version_class.correct?(nm) }
|
|
294
|
-
releases.sort_by do |
|
|
295
|
-
version_class.new(
|
|
314
|
+
releases.sort_by do |release|
|
|
315
|
+
version_class.new(release.tag_name.gsub(/^[^0-9\.]*/, ""))
|
|
296
316
|
end.reverse
|
|
297
317
|
else
|
|
298
|
-
releases.sort_by { |
|
|
318
|
+
releases.sort_by { |release| release.id || 0 }.reverse
|
|
299
319
|
end
|
|
300
320
|
rescue Octokit::NotFound, Octokit::UnavailableForLegalReasons
|
|
301
321
|
[]
|
|
302
322
|
end
|
|
303
323
|
|
|
304
|
-
sig { returns(T::Array[
|
|
324
|
+
sig { returns(T::Array[Dependabot::Clients::GithubRelease]) }
|
|
325
|
+
def parsed_github_releases
|
|
326
|
+
resources = T.let(
|
|
327
|
+
github_client.releases(T.must(source).repo, per_page: 100),
|
|
328
|
+
T.nilable(T::Array[Sawyer::Resource])
|
|
329
|
+
)
|
|
330
|
+
releases = (resources || []).filter_map do |release|
|
|
331
|
+
Dependabot::Clients::GithubRelease.from_resource(release)
|
|
332
|
+
end
|
|
333
|
+
releases
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
sig { returns(T::Array[GitLabRelease]) }
|
|
305
337
|
def fetch_gitlab_releases
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
)
|
|
311
|
-
.select(&:release)
|
|
312
|
-
.sort_by { |r| T.unsafe(r).commit.authored_date }
|
|
313
|
-
.reverse
|
|
314
|
-
|
|
315
|
-
releases.map do |tag|
|
|
316
|
-
GitLabRelease.new(
|
|
317
|
-
name: T.unsafe(tag).name,
|
|
318
|
-
tag_name: T.unsafe(tag).release.tag_name,
|
|
319
|
-
body: T.unsafe(tag).release.description,
|
|
320
|
-
html_url: "#{T.must(source).url}/tags/#{T.unsafe(tag).name}"
|
|
321
|
-
)
|
|
338
|
+
tags = gitlab_client.tags(T.must(source).repo)
|
|
339
|
+
releases = tags.filter_map do |tag|
|
|
340
|
+
next unless tag.is_a?(Gitlab::ObjectifiedHash)
|
|
341
|
+
|
|
342
|
+
GitLabRelease.from_tag(tag, source_url: T.must(source).url)
|
|
322
343
|
end
|
|
344
|
+
releases.sort_by(&:authored_at).reverse
|
|
323
345
|
rescue Gitlab::Error::NotFound
|
|
324
346
|
[]
|
|
325
347
|
end
|
|
@@ -359,20 +381,32 @@ module Dependabot
|
|
|
359
381
|
|
|
360
382
|
sig { returns(T.nilable(String)) }
|
|
361
383
|
def previous_ref
|
|
362
|
-
previous_refs = T.must(dependency.previous_requirements).filter_map do |
|
|
363
|
-
|
|
384
|
+
previous_refs = T.must(dependency.previous_requirements).filter_map do |requirement|
|
|
385
|
+
requirement_ref(requirement)
|
|
364
386
|
end.uniq
|
|
365
387
|
previous_refs.first if previous_refs.one?
|
|
366
388
|
end
|
|
367
389
|
|
|
368
390
|
sig { returns(T.nilable(String)) }
|
|
369
391
|
def new_ref
|
|
370
|
-
new_refs = dependency.requirements.filter_map do |
|
|
371
|
-
|
|
392
|
+
new_refs = dependency.requirements.filter_map do |requirement|
|
|
393
|
+
requirement_ref(requirement)
|
|
372
394
|
end.uniq
|
|
373
395
|
new_refs.first if new_refs.one?
|
|
374
396
|
end
|
|
375
397
|
|
|
398
|
+
sig { params(requirement: Dependabot::DependencyRequirement).returns(T.nilable(String)) }
|
|
399
|
+
def requirement_ref(requirement)
|
|
400
|
+
source = requirement.source
|
|
401
|
+
return unless source
|
|
402
|
+
|
|
403
|
+
symbol_ref = source[:ref]
|
|
404
|
+
return symbol_ref if symbol_ref.is_a?(String)
|
|
405
|
+
|
|
406
|
+
string_ref = source["ref"]
|
|
407
|
+
string_ref if string_ref.is_a?(String)
|
|
408
|
+
end
|
|
409
|
+
|
|
376
410
|
sig { returns(T::Boolean) }
|
|
377
411
|
def ref_changed?
|
|
378
412
|
# We could go from multiple previous refs (nil) to a single new ref
|
|
@@ -121,9 +121,9 @@ module Dependabot
|
|
|
121
121
|
|
|
122
122
|
# Apply case transformation to content after prefix
|
|
123
123
|
case branch_name_case
|
|
124
|
-
when "
|
|
124
|
+
when "lowercase"
|
|
125
125
|
content = content.downcase
|
|
126
|
-
when "
|
|
126
|
+
when "uppercase"
|
|
127
127
|
content = content.upcase
|
|
128
128
|
end
|
|
129
129
|
|
data/lib/dependabot/version.rb
CHANGED
|
@@ -24,6 +24,15 @@ module Dependabot
|
|
|
24
24
|
T.cast(super, Dependabot::Version)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
sig do
|
|
28
|
+
overridable
|
|
29
|
+
.params(_from_version: String, _to_version: String)
|
|
30
|
+
.returns(T.nilable(String))
|
|
31
|
+
end
|
|
32
|
+
def self.update_type(_from_version, _to_version)
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
|
|
27
36
|
# Opt-in to Rubygems 4 behavior
|
|
28
37
|
sig { override.overridable.params(version: VersionParameter).returns(T::Boolean) }
|
|
29
38
|
def self.correct?(version)
|
data/lib/dependabot.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-common
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.388.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -518,6 +518,7 @@ files:
|
|
|
518
518
|
- lib/dependabot/clients/bitbucket.rb
|
|
519
519
|
- lib/dependabot/clients/bitbucket_with_retries.rb
|
|
520
520
|
- lib/dependabot/clients/codecommit.rb
|
|
521
|
+
- lib/dependabot/clients/github_release.rb
|
|
521
522
|
- lib/dependabot/clients/github_with_retries.rb
|
|
522
523
|
- lib/dependabot/clients/gitlab_with_retries.rb
|
|
523
524
|
- lib/dependabot/command_helpers.rb
|
|
@@ -536,6 +537,7 @@ files:
|
|
|
536
537
|
- lib/dependabot/dependency_group.rb
|
|
537
538
|
- lib/dependabot/dependency_requirement.rb
|
|
538
539
|
- lib/dependabot/ecosystem.rb
|
|
540
|
+
- lib/dependabot/error_details.rb
|
|
539
541
|
- lib/dependabot/errors.rb
|
|
540
542
|
- lib/dependabot/experiments.rb
|
|
541
543
|
- lib/dependabot/file_fetchers.rb
|
|
@@ -552,6 +554,7 @@ files:
|
|
|
552
554
|
- lib/dependabot/file_updaters/base.rb
|
|
553
555
|
- lib/dependabot/file_updaters/vendor_updater.rb
|
|
554
556
|
- lib/dependabot/git_commit_checker.rb
|
|
557
|
+
- lib/dependabot/git_commit_checker/source_details.rb
|
|
555
558
|
- lib/dependabot/git_cooldown_date_resolver.rb
|
|
556
559
|
- lib/dependabot/git_metadata_fetcher.rb
|
|
557
560
|
- lib/dependabot/git_ref.rb
|
|
@@ -622,7 +625,7 @@ licenses:
|
|
|
622
625
|
- MIT
|
|
623
626
|
metadata:
|
|
624
627
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
625
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
628
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.388.0
|
|
626
629
|
rdoc_options: []
|
|
627
630
|
require_paths:
|
|
628
631
|
- lib
|