dependabot-common 0.382.0 → 0.384.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/config/file.rb +48 -13
- data/lib/dependabot/config/ignore_condition.rb +1 -1
- data/lib/dependabot/dependency_group.rb +62 -7
- data/lib/dependabot/errors.rb +74 -3
- data/lib/dependabot/git_cooldown_date_resolver.rb +114 -0
- data/lib/dependabot/notices.rb +1 -1
- data/lib/dependabot/package/package_latest_version_finder.rb +0 -1
- data/lib/dependabot/pull_request_creator/branch_namer/base.rb +5 -3
- data/lib/dependabot/pull_request_creator/commit_message_options.rb +70 -0
- data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +6 -3
- data/lib/dependabot/pull_request_creator/message_builder/title_builder.rb +14 -10
- data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +14 -10
- data/lib/dependabot/pull_request_creator.rb +1 -1
- data/lib/dependabot/pull_request_updater.rb +4 -4
- data/lib/dependabot/requirements_updater/base.rb +3 -1
- data/lib/dependabot/version.rb +13 -0
- data/lib/dependabot.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4011821492cf0ae915acc4d9b0783f699f5522946eac07bbef8973e8692df1f9
|
|
4
|
+
data.tar.gz: 7502e7687e79b39ec94fad1c9318e1b40b7cdf7965c8c1818ebda3a7a914b8ee
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c5f9708f6197bf0fe6e6dd22b971e41522f7deb6af1963786276dd5246d3177741768e4065d437c4ad3906ff0d0d91afd10b41a0108c0e553a14be2ae1dfde5f
|
|
7
|
+
data.tar.gz: 1e9ebca6d67ec61d619f36e71cfd02cd92c1aca3d6701b47ff4a94c95f2abcdb05277de57902d4dea2b1d5bb6410cabbc027c81bb0e8884bbee84d31cd43e2f4
|
|
@@ -102,33 +102,68 @@ module Dependabot
|
|
|
102
102
|
T::Hash[String, String]
|
|
103
103
|
)
|
|
104
104
|
|
|
105
|
-
sig { params(cfg: T.nilable(T::Hash[Symbol, T.
|
|
105
|
+
sig { params(cfg: T.nilable(T::Hash[Symbol, T.anything])).returns(T::Array[IgnoreCondition]) }
|
|
106
106
|
def ignore_conditions(cfg)
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
array_values(cfg&.dig(:ignore)).map do |raw|
|
|
108
|
+
ic = hash_values(raw)
|
|
109
109
|
IgnoreCondition.new(
|
|
110
|
-
dependency_name: ic[:"dependency-name"],
|
|
111
|
-
versions: ic[:versions],
|
|
112
|
-
update_types: ic[:"update-types"]
|
|
110
|
+
dependency_name: T.must(string_value(ic[:"dependency-name"])),
|
|
111
|
+
versions: string_array(ic[:versions]),
|
|
112
|
+
update_types: string_array(ic[:"update-types"])
|
|
113
113
|
)
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
sig do
|
|
118
|
-
params(cfg: T.nilable(T::Hash[Symbol, T.
|
|
118
|
+
params(cfg: T.nilable(T::Hash[Symbol, T.anything])).returns(UpdateConfig::CommitMessageOptions)
|
|
119
119
|
end
|
|
120
120
|
def commit_message_options(cfg)
|
|
121
|
-
commit_message = cfg&.dig(:"commit-message")
|
|
121
|
+
commit_message = hash_values(cfg&.dig(:"commit-message"))
|
|
122
|
+
prefix = string_value(commit_message[:prefix])
|
|
122
123
|
UpdateConfig::CommitMessageOptions.new(
|
|
123
|
-
prefix:
|
|
124
|
-
prefix_development: commit_message[:"prefix-development"] ||
|
|
125
|
-
include: commit_message[:include]
|
|
124
|
+
prefix: prefix,
|
|
125
|
+
prefix_development: string_value(commit_message[:"prefix-development"]) || prefix,
|
|
126
|
+
include: string_value(commit_message[:include])
|
|
126
127
|
)
|
|
127
128
|
end
|
|
128
129
|
|
|
129
|
-
sig { params(cfg: T.nilable(T::Hash[Symbol, T.
|
|
130
|
+
sig { params(cfg: T.nilable(T::Hash[Symbol, T.anything])).returns(T::Array[String]) }
|
|
130
131
|
def exclude_paths(cfg)
|
|
131
|
-
|
|
132
|
+
string_array(cfg&.dig(:"exclude-paths")) || []
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# The methods below narrow the loosely typed, parsed-YAML config values
|
|
136
|
+
# (Symbol-keyed hashes whose values are arbitrary) into the specific
|
|
137
|
+
# types the config objects expect.
|
|
138
|
+
|
|
139
|
+
sig { params(value: T.anything).returns(T.nilable(String)) }
|
|
140
|
+
def string_value(value)
|
|
141
|
+
case value
|
|
142
|
+
when String then value
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
sig { params(value: T.anything).returns(T::Hash[Symbol, T.anything]) }
|
|
147
|
+
def hash_values(value)
|
|
148
|
+
case value
|
|
149
|
+
when Hash then value
|
|
150
|
+
else {}
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
sig { params(value: T.anything).returns(T::Array[T.anything]) }
|
|
155
|
+
def array_values(value)
|
|
156
|
+
case value
|
|
157
|
+
when Array then value
|
|
158
|
+
else []
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
sig { params(value: T.anything).returns(T.nilable(T::Array[String])) }
|
|
163
|
+
def string_array(value)
|
|
164
|
+
case value
|
|
165
|
+
when Array then value.map(&:to_s)
|
|
166
|
+
end
|
|
132
167
|
end
|
|
133
168
|
end
|
|
134
169
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "dependabot/experiments"
|
|
@@ -28,10 +28,23 @@ module Dependabot
|
|
|
28
28
|
sig { returns(T.nilable(String)) }
|
|
29
29
|
attr_reader :group_by
|
|
30
30
|
|
|
31
|
+
# The following readers are parsed once from the raw rules hash so callers
|
|
32
|
+
# get typed access instead of repeatedly casting rules["patterns"] and
|
|
33
|
+
# friends at every use site. A nil value means the rule is absent (which the
|
|
34
|
+
# matching logic treats differently from an empty list).
|
|
35
|
+
sig { returns(T.nilable(T::Array[String])) }
|
|
36
|
+
attr_reader :patterns
|
|
37
|
+
|
|
38
|
+
sig { returns(T.nilable(T::Array[String])) }
|
|
39
|
+
attr_reader :exclude_patterns
|
|
40
|
+
|
|
41
|
+
sig { returns(T.nilable(T::Array[String])) }
|
|
42
|
+
attr_reader :update_types
|
|
43
|
+
|
|
31
44
|
sig do
|
|
32
45
|
params(
|
|
33
46
|
name: String,
|
|
34
|
-
rules: T::Hash[String, T.
|
|
47
|
+
rules: T::Hash[String, T.any(String, T::Array[String])],
|
|
35
48
|
applies_to: T.nilable(String)
|
|
36
49
|
)
|
|
37
50
|
.void
|
|
@@ -41,7 +54,10 @@ module Dependabot
|
|
|
41
54
|
# For backwards compatibility, if no applies_to is provided, default to "version-updates"
|
|
42
55
|
@applies_to = T.let(applies_to || "version-updates", String)
|
|
43
56
|
@rules = rules
|
|
44
|
-
@group_by = T.let(rules
|
|
57
|
+
@group_by = T.let(string_rule(rules, "group-by"), T.nilable(String))
|
|
58
|
+
@patterns = T.let(string_array_rule(rules, "patterns"), T.nilable(T::Array[String]))
|
|
59
|
+
@exclude_patterns = T.let(string_array_rule(rules, "exclude-patterns"), T.nilable(T::Array[String]))
|
|
60
|
+
@update_types = T.let(string_array_rule(rules, "update-types"), T.nilable(T::Array[String]))
|
|
45
61
|
@dependencies = T.let([], T::Array[Dependabot::Dependency])
|
|
46
62
|
end
|
|
47
63
|
|
|
@@ -75,16 +91,18 @@ module Dependabot
|
|
|
75
91
|
|
|
76
92
|
sig { params(dependency_name: String).returns(T::Boolean) }
|
|
77
93
|
def matches_pattern?(dependency_name)
|
|
78
|
-
|
|
94
|
+
patterns = self.patterns
|
|
95
|
+
return true if patterns.nil? # If no patterns are defined, we pass this check by default
|
|
79
96
|
|
|
80
|
-
|
|
97
|
+
patterns.any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
|
|
81
98
|
end
|
|
82
99
|
|
|
83
100
|
sig { params(dependency_name: String).returns(T::Boolean) }
|
|
84
101
|
def matches_excluded_pattern?(dependency_name)
|
|
85
|
-
|
|
102
|
+
exclude_patterns = self.exclude_patterns
|
|
103
|
+
return false if exclude_patterns.nil? # If there are no exclusions, fail by default
|
|
86
104
|
|
|
87
|
-
|
|
105
|
+
exclude_patterns.any? { |rule| WildcardMatcher.match?(rule, dependency_name) }
|
|
88
106
|
end
|
|
89
107
|
|
|
90
108
|
sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
|
|
@@ -102,5 +120,42 @@ module Dependabot
|
|
|
102
120
|
def experimental_rules_enabled?
|
|
103
121
|
Dependabot::Experiments.enabled?(:grouped_updates_experimental_rules)
|
|
104
122
|
end
|
|
123
|
+
|
|
124
|
+
# Reads a rule whose value is expected to be a single string (e.g.
|
|
125
|
+
# "group-by"), returning nil when the key is absent or the value is not a
|
|
126
|
+
# string.
|
|
127
|
+
sig do
|
|
128
|
+
params(
|
|
129
|
+
rules: T::Hash[String, T.any(String, T::Array[String])],
|
|
130
|
+
key: String
|
|
131
|
+
)
|
|
132
|
+
.returns(T.nilable(String))
|
|
133
|
+
end
|
|
134
|
+
def string_rule(rules, key)
|
|
135
|
+
value = rules[key]
|
|
136
|
+
value.is_a?(String) ? value : nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Reads a rule whose value is expected to be a list of strings (e.g.
|
|
140
|
+
# "patterns", "exclude-patterns", "update-types"). Returns nil when the key
|
|
141
|
+
# is absent so callers can distinguish "rule not set" from "empty list", and
|
|
142
|
+
# coerces a lone string into a single-element list.
|
|
143
|
+
sig do
|
|
144
|
+
params(
|
|
145
|
+
rules: T::Hash[String, T.any(String, T::Array[String])],
|
|
146
|
+
key: String
|
|
147
|
+
)
|
|
148
|
+
.returns(T.nilable(T::Array[String]))
|
|
149
|
+
end
|
|
150
|
+
def string_array_rule(rules, key)
|
|
151
|
+
return nil unless rules.key?(key)
|
|
152
|
+
|
|
153
|
+
value = rules[key]
|
|
154
|
+
case value
|
|
155
|
+
when Array then value.grep(String)
|
|
156
|
+
when String then [value]
|
|
157
|
+
else []
|
|
158
|
+
end
|
|
159
|
+
end
|
|
105
160
|
end
|
|
106
161
|
end
|
data/lib/dependabot/errors.rb
CHANGED
|
@@ -97,6 +97,11 @@ module Dependabot
|
|
|
97
97
|
"error-type": "path_dependencies_not_reachable",
|
|
98
98
|
"error-detail": { dependencies: error.dependencies }
|
|
99
99
|
}
|
|
100
|
+
when Dependabot::PrivateRegistryConfigNotFound
|
|
101
|
+
{
|
|
102
|
+
"error-type": "private_registry_config_not_found",
|
|
103
|
+
"error-detail": { source: error.source }
|
|
104
|
+
}
|
|
100
105
|
when Dependabot::PrivateSourceAuthenticationFailure
|
|
101
106
|
{
|
|
102
107
|
"error-type": "private_source_authentication_failure",
|
|
@@ -238,6 +243,16 @@ module Dependabot
|
|
|
238
243
|
"error-type": "dependency_file_not_resolvable",
|
|
239
244
|
"error-detail": { message: error.message }
|
|
240
245
|
}
|
|
246
|
+
when Dependabot::BlockedDependencyVersion
|
|
247
|
+
{
|
|
248
|
+
"error-type": "blocked_dependency_version",
|
|
249
|
+
"error-detail": {
|
|
250
|
+
"dependency-name": error.dependency_name,
|
|
251
|
+
"blocked-version": error.blocked_version,
|
|
252
|
+
"version-requirement": error.version_requirement,
|
|
253
|
+
reason: error.reason
|
|
254
|
+
}.compact
|
|
255
|
+
}
|
|
241
256
|
when Dependabot::DependencyFileNotEvaluatable
|
|
242
257
|
{
|
|
243
258
|
"error-type": "dependency_file_not_evaluatable",
|
|
@@ -687,6 +702,22 @@ module Dependabot
|
|
|
687
702
|
# Source level errors #
|
|
688
703
|
#######################
|
|
689
704
|
|
|
705
|
+
class PrivateRegistryConfigNotFound < DependabotError
|
|
706
|
+
extend T::Sig
|
|
707
|
+
|
|
708
|
+
sig { returns(String) }
|
|
709
|
+
attr_reader :source
|
|
710
|
+
|
|
711
|
+
sig { params(source: String).void }
|
|
712
|
+
def initialize(source)
|
|
713
|
+
@source = T.let(sanitize_source(source), String)
|
|
714
|
+
msg = "Private npm registries require either a .npmrc file in your repository, " \
|
|
715
|
+
"or explicit `scope`/`replaces-base` configuration in dependabot.yml. " \
|
|
716
|
+
"Registry: #{@source}"
|
|
717
|
+
super(msg)
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
|
|
690
721
|
class PrivateSourceAuthenticationFailure < DependabotError
|
|
691
722
|
extend T::Sig
|
|
692
723
|
|
|
@@ -709,10 +740,10 @@ module Dependabot
|
|
|
709
740
|
sig { returns(String) }
|
|
710
741
|
attr_reader :source
|
|
711
742
|
|
|
712
|
-
sig { params(source: T.nilable(String)).void }
|
|
713
|
-
def initialize(source)
|
|
743
|
+
sig { params(source: T.nilable(String), error_message: T.nilable(String)).void }
|
|
744
|
+
def initialize(source, error_message = nil)
|
|
714
745
|
@source = T.let(sanitize_source(T.must(source)), String)
|
|
715
|
-
msg = "Bad response error while accessing source: #{@source}"
|
|
746
|
+
msg = error_message ? sanitize_source(error_message) : "Bad response error while accessing source: #{@source}"
|
|
716
747
|
super(msg)
|
|
717
748
|
end
|
|
718
749
|
end
|
|
@@ -901,6 +932,46 @@ module Dependabot
|
|
|
901
932
|
# Raised by UpdateChecker if all candidate updates are ignored
|
|
902
933
|
class AllVersionsIgnored < DependabotError; end
|
|
903
934
|
|
|
935
|
+
# Raised when regenerating a lockfile would introduce or change a transitive
|
|
936
|
+
# (indirect) dependency to a version that matches a configured blocked version.
|
|
937
|
+
# The offending change is rejected so the blocked version is never shipped,
|
|
938
|
+
# while other dependencies are still allowed to update.
|
|
939
|
+
class BlockedDependencyVersion < DependabotError
|
|
940
|
+
extend T::Sig
|
|
941
|
+
|
|
942
|
+
sig { returns(String) }
|
|
943
|
+
attr_reader :dependency_name
|
|
944
|
+
|
|
945
|
+
sig { returns(String) }
|
|
946
|
+
attr_reader :blocked_version
|
|
947
|
+
|
|
948
|
+
sig { returns(String) }
|
|
949
|
+
attr_reader :version_requirement
|
|
950
|
+
|
|
951
|
+
sig { returns(T.nilable(String)) }
|
|
952
|
+
attr_reader :reason
|
|
953
|
+
|
|
954
|
+
sig do
|
|
955
|
+
params(
|
|
956
|
+
dependency_name: String,
|
|
957
|
+
blocked_version: String,
|
|
958
|
+
version_requirement: String,
|
|
959
|
+
reason: T.nilable(String)
|
|
960
|
+
).void
|
|
961
|
+
end
|
|
962
|
+
def initialize(dependency_name:, blocked_version:, version_requirement:, reason: nil)
|
|
963
|
+
@dependency_name = dependency_name
|
|
964
|
+
@blocked_version = blocked_version
|
|
965
|
+
@version_requirement = version_requirement
|
|
966
|
+
@reason = reason
|
|
967
|
+
|
|
968
|
+
msg = "Update blocked: transitive dependency #{dependency_name} #{blocked_version} " \
|
|
969
|
+
"matches blocked version requirement '#{version_requirement}'"
|
|
970
|
+
msg += " (reason: #{reason})" if reason && !reason.empty?
|
|
971
|
+
super(msg)
|
|
972
|
+
end
|
|
973
|
+
end
|
|
974
|
+
|
|
904
975
|
# Raised by FileParser if processing may execute external code in the update context
|
|
905
976
|
class UnexpectedExternalCode < DependabotError; end
|
|
906
977
|
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
require "dependabot/clients/github_with_retries"
|
|
6
|
+
require "dependabot/shared_helpers"
|
|
7
|
+
require "dependabot/source"
|
|
8
|
+
|
|
9
|
+
module Dependabot
|
|
10
|
+
# Shared logic for resolving release dates from git-based sources for cooldown
|
|
11
|
+
# purposes. Used by ecosystems that rely on git tags (pre-commit, GitHub Actions)
|
|
12
|
+
# rather than package registries.
|
|
13
|
+
#
|
|
14
|
+
# Priority: GitHub Release published_at > tag creation date (for-each-ref) > commit date.
|
|
15
|
+
#
|
|
16
|
+
# Including classes must implement:
|
|
17
|
+
# - `cooldown_source_url` — returns the git source URL
|
|
18
|
+
# - `cooldown_credentials` — returns the credentials array
|
|
19
|
+
module GitCooldownDateResolver
|
|
20
|
+
extend T::Sig
|
|
21
|
+
extend T::Helpers
|
|
22
|
+
|
|
23
|
+
abstract!
|
|
24
|
+
|
|
25
|
+
# The git source URL for the dependency (e.g. "https://github.com/owner/repo")
|
|
26
|
+
sig { abstract.returns(T.nilable(String)) }
|
|
27
|
+
def cooldown_source_url; end
|
|
28
|
+
|
|
29
|
+
# Credentials for GitHub API access
|
|
30
|
+
sig { abstract.returns(T::Array[Dependabot::Credential]) }
|
|
31
|
+
def cooldown_credentials; end
|
|
32
|
+
|
|
33
|
+
# Strips the `tags/` prefix that GitCommitChecker may add when the pinned
|
|
34
|
+
# ref starts with `tags/`, preventing construction of invalid refs like
|
|
35
|
+
# `refs/tags/tags/v1.0.0`.
|
|
36
|
+
sig { params(tag_name: String).returns(String) }
|
|
37
|
+
def normalize_tag_name(tag_name)
|
|
38
|
+
tag_name.delete_prefix("tags/")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Resolves the best available date for a candidate tag.
|
|
42
|
+
# Priority: GitHub Release published_at > tag creation date > commit date.
|
|
43
|
+
sig { params(tag_name: String, commit_sha: String).returns(Time) }
|
|
44
|
+
def resolve_candidate_date(tag_name, commit_sha)
|
|
45
|
+
releases = cached_github_releases
|
|
46
|
+
unless releases.empty?
|
|
47
|
+
release = releases.find { |r| r.tag_name == tag_name }
|
|
48
|
+
return release.published_at if release&.published_at
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
tag_creation_date(tag_name, commit_sha)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Looks up the GitHub Release published_at date for a given tag name.
|
|
55
|
+
# Returns nil if no release exists for this tag.
|
|
56
|
+
sig { params(tag_name: String).returns(T.nilable(Time)) }
|
|
57
|
+
def github_release_published_at(tag_name)
|
|
58
|
+
releases = cached_github_releases
|
|
59
|
+
return nil if releases.empty?
|
|
60
|
+
|
|
61
|
+
release = releases.find { |r| r.tag_name == tag_name }
|
|
62
|
+
return nil unless release&.published_at
|
|
63
|
+
|
|
64
|
+
release.published_at
|
|
65
|
+
rescue StandardError => e
|
|
66
|
+
Dependabot.logger.debug("Error fetching GitHub release date for #{tag_name}: #{e.message}")
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns the tag creation date for cooldown purposes (used inside bare clone).
|
|
71
|
+
# Priority: tag creation date from for-each-ref > commit date fallback.
|
|
72
|
+
sig { params(tag_name: String, commit_sha: String).returns(Time) }
|
|
73
|
+
def tag_creation_date(tag_name, commit_sha)
|
|
74
|
+
tag_date_str = SharedHelpers.run_shell_command(
|
|
75
|
+
"git for-each-ref --format=\"%(creatordate:iso)\" \"refs/tags/#{tag_name}\"",
|
|
76
|
+
fingerprint: "git for-each-ref --format=\"%(creatordate:iso)\" \"refs/tags/<tag_name>\""
|
|
77
|
+
).strip
|
|
78
|
+
|
|
79
|
+
if tag_date_str.empty?
|
|
80
|
+
tag_date_str = SharedHelpers.run_shell_command(
|
|
81
|
+
"git show --no-patch --format=\"%cd\" --date=iso #{commit_sha}",
|
|
82
|
+
fingerprint: "git show --no-patch --format=\"%cd\" --date=iso <commit_sha>"
|
|
83
|
+
).strip
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
Time.parse(tag_date_str)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Fetches and caches GitHub releases for the dependency source.
|
|
90
|
+
# Returns an empty array for non-GitHub sources.
|
|
91
|
+
sig { returns(T::Array[T.untyped]) } # rubocop:disable Sorbet/ForbidTUntyped
|
|
92
|
+
def cached_github_releases
|
|
93
|
+
@cached_github_releases ||= T.let(
|
|
94
|
+
begin
|
|
95
|
+
url = cooldown_source_url
|
|
96
|
+
source = Source.from_url(url)
|
|
97
|
+
if source&.provider == "github"
|
|
98
|
+
client = Dependabot::Clients::GithubWithRetries.for_source(
|
|
99
|
+
source: T.must(source),
|
|
100
|
+
credentials: cooldown_credentials
|
|
101
|
+
)
|
|
102
|
+
client.releases(T.must(source).repo, per_page: 100)
|
|
103
|
+
else
|
|
104
|
+
[]
|
|
105
|
+
end
|
|
106
|
+
rescue StandardError => e
|
|
107
|
+
Dependabot.logger.debug("Error fetching GitHub releases: #{e.message}")
|
|
108
|
+
[]
|
|
109
|
+
end,
|
|
110
|
+
T.nilable(T::Array[T.untyped]) # rubocop:disable Sorbet/ForbidTUntyped
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
data/lib/dependabot/notices.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "digest"
|
|
4
5
|
require "sorbet-runtime"
|
|
5
6
|
|
|
6
7
|
module Dependabot
|
|
@@ -70,9 +71,10 @@ module Dependabot
|
|
|
70
71
|
sanitized_name = sanitized_name.gsub("/", separator)
|
|
71
72
|
|
|
72
73
|
# Shorten the ref in case users refs have length limits
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
branch_name_max_length = max_length
|
|
75
|
+
if branch_name_max_length && (sanitized_name.length > branch_name_max_length)
|
|
76
|
+
sha = T.must(Digest::SHA1.hexdigest(sanitized_name)[0, branch_name_max_length])
|
|
77
|
+
sanitized_name[[branch_name_max_length - sha.size, 0].max..] = sha
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
sanitized_name
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
module Dependabot
|
|
7
|
+
class PullRequestCreator
|
|
8
|
+
# Typed view over the `commit_message_options` hash threaded into the PR
|
|
9
|
+
# creator's title and prefix builders. The raw options arrive as a loosely
|
|
10
|
+
# typed hash sourced from user config, so this parses the known keys once at
|
|
11
|
+
# the boundary and lets downstream builders use typed readers instead of
|
|
12
|
+
# digging an untyped hash.
|
|
13
|
+
class CommitMessageOptions
|
|
14
|
+
extend T::Sig
|
|
15
|
+
|
|
16
|
+
sig { returns(T.nilable(String)) }
|
|
17
|
+
attr_reader :prefix
|
|
18
|
+
|
|
19
|
+
sig { returns(T.nilable(String)) }
|
|
20
|
+
attr_reader :prefix_development
|
|
21
|
+
|
|
22
|
+
sig { returns(T::Boolean) }
|
|
23
|
+
attr_reader :include_scope
|
|
24
|
+
|
|
25
|
+
sig do
|
|
26
|
+
params(
|
|
27
|
+
prefix: T.nilable(String),
|
|
28
|
+
prefix_development: T.nilable(String),
|
|
29
|
+
include_scope: T::Boolean
|
|
30
|
+
).void
|
|
31
|
+
end
|
|
32
|
+
def initialize(prefix: nil, prefix_development: nil, include_scope: false)
|
|
33
|
+
@prefix = prefix
|
|
34
|
+
@prefix_development = prefix_development
|
|
35
|
+
@include_scope = include_scope
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Parses a raw options hash. Unknown keys are ignored, and absent or
|
|
39
|
+
# non-string prefixes become nil.
|
|
40
|
+
sig { params(options: T::Hash[Symbol, T.anything]).returns(CommitMessageOptions) }
|
|
41
|
+
def self.from_hash(options)
|
|
42
|
+
new(
|
|
43
|
+
prefix: coerce_string(options[:prefix]),
|
|
44
|
+
prefix_development: coerce_string(options[:prefix_development]),
|
|
45
|
+
include_scope: options[:include_scope] ? true : false
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
sig { params(value: T.anything).returns(T.nilable(String)) }
|
|
50
|
+
def self.coerce_string(value)
|
|
51
|
+
case value
|
|
52
|
+
when String then value
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
private_class_method :coerce_string
|
|
56
|
+
|
|
57
|
+
# True when an explicit (non-nil) prefix was provided.
|
|
58
|
+
sig { returns(T::Boolean) }
|
|
59
|
+
def prefix?
|
|
60
|
+
!prefix.nil?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# True when an explicit (non-nil) development prefix was provided.
|
|
64
|
+
sig { returns(T::Boolean) }
|
|
65
|
+
def prefix_development?
|
|
66
|
+
!prefix_development.nil?
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -247,7 +247,7 @@ module Dependabot
|
|
|
247
247
|
end
|
|
248
248
|
end
|
|
249
249
|
|
|
250
|
-
sig { params(details: T::Hash[String, T.
|
|
250
|
+
sig { params(details: T::Hash[String, T.anything]).returns(String) }
|
|
251
251
|
def vulnerability_version_range_lines(details)
|
|
252
252
|
msg = ""
|
|
253
253
|
%w(
|
|
@@ -256,9 +256,12 @@ module Dependabot
|
|
|
256
256
|
affected_versions
|
|
257
257
|
).each do |tp|
|
|
258
258
|
type = T.must(tp.split("_").first).capitalize
|
|
259
|
-
|
|
259
|
+
versions = case (value = details[tp])
|
|
260
|
+
when Array then value
|
|
261
|
+
end
|
|
262
|
+
next unless versions
|
|
260
263
|
|
|
261
|
-
versions_string =
|
|
264
|
+
versions_string = versions.any? ? versions.join("; ") : "none"
|
|
262
265
|
versions_string = versions_string.gsub(/(?<!\\)~/, '\~')
|
|
263
266
|
msg += "> #{type} versions: #{versions_string}\n"
|
|
264
267
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
5
5
|
require "dependabot/dependency"
|
|
6
6
|
require "dependabot/logger"
|
|
7
|
+
require "dependabot/pull_request_creator/commit_message_options"
|
|
7
8
|
require "dependabot/pull_request_creator/pr_name_prefixer"
|
|
8
9
|
|
|
9
10
|
module Dependabot
|
|
@@ -25,7 +26,7 @@ module Dependabot
|
|
|
25
26
|
sig { returns(T.nilable(Dependabot::PullRequestCreator::PrNamePrefixer)) }
|
|
26
27
|
attr_reader :prefixer
|
|
27
28
|
|
|
28
|
-
sig { returns(T.nilable(
|
|
29
|
+
sig { returns(T.nilable(CommitMessageOptions)) }
|
|
29
30
|
attr_reader :commit_message_options
|
|
30
31
|
|
|
31
32
|
sig { returns(T.nilable(T::Array[Dependabot::Dependency])) }
|
|
@@ -35,14 +36,17 @@ module Dependabot
|
|
|
35
36
|
params(
|
|
36
37
|
base_title: String,
|
|
37
38
|
prefixer: T.nilable(Dependabot::PullRequestCreator::PrNamePrefixer),
|
|
38
|
-
commit_message_options: T.nilable(T::Hash[Symbol, T.
|
|
39
|
+
commit_message_options: T.nilable(T::Hash[Symbol, T.anything]),
|
|
39
40
|
dependencies: T.nilable(T::Array[Dependabot::Dependency])
|
|
40
41
|
).void
|
|
41
42
|
end
|
|
42
43
|
def initialize(base_title:, prefixer: nil, commit_message_options: nil, dependencies: nil)
|
|
43
44
|
@base_title = base_title
|
|
44
45
|
@prefixer = prefixer
|
|
45
|
-
@commit_message_options =
|
|
46
|
+
@commit_message_options = T.let(
|
|
47
|
+
commit_message_options && CommitMessageOptions.from_hash(commit_message_options),
|
|
48
|
+
T.nilable(CommitMessageOptions)
|
|
49
|
+
)
|
|
46
50
|
@dependencies = dependencies
|
|
47
51
|
end
|
|
48
52
|
|
|
@@ -85,12 +89,12 @@ module Dependabot
|
|
|
85
89
|
# but without requiring source/credentials.
|
|
86
90
|
sig { returns(String) }
|
|
87
91
|
def build_explicit_prefix
|
|
88
|
-
return "" unless commit_message_options&.
|
|
92
|
+
return "" unless commit_message_options&.prefix?
|
|
89
93
|
|
|
90
94
|
prefix = explicit_prefix_string
|
|
91
95
|
return "" if prefix.empty?
|
|
92
96
|
|
|
93
|
-
prefix += "(#{scope})" if commit_message_options&.
|
|
97
|
+
prefix += "(#{scope})" if commit_message_options&.include_scope
|
|
94
98
|
# Append colon after alphanumeric or closing bracket to follow
|
|
95
99
|
# conventional commit format (e.g., "chore: ..." or "fix(deps): ...")
|
|
96
100
|
prefix += ":" if prefix.match?(/[A-Za-z0-9\)\]]\Z/)
|
|
@@ -101,11 +105,11 @@ module Dependabot
|
|
|
101
105
|
sig { returns(String) }
|
|
102
106
|
def explicit_prefix_string
|
|
103
107
|
if production_dependencies?
|
|
104
|
-
commit_message_options&.
|
|
105
|
-
elsif commit_message_options&.
|
|
106
|
-
commit_message_options&.
|
|
108
|
+
commit_message_options&.prefix.to_s
|
|
109
|
+
elsif commit_message_options&.prefix_development?
|
|
110
|
+
commit_message_options&.prefix_development.to_s
|
|
107
111
|
else
|
|
108
|
-
commit_message_options&.
|
|
112
|
+
commit_message_options&.prefix.to_s
|
|
109
113
|
end
|
|
110
114
|
end
|
|
111
115
|
|
|
@@ -9,6 +9,7 @@ require "dependabot/clients/codecommit"
|
|
|
9
9
|
require "dependabot/clients/github_with_retries"
|
|
10
10
|
require "dependabot/clients/gitlab_with_retries"
|
|
11
11
|
require "dependabot/pull_request_creator"
|
|
12
|
+
require "dependabot/pull_request_creator/commit_message_options"
|
|
12
13
|
|
|
13
14
|
module Dependabot
|
|
14
15
|
class PullRequestCreator
|
|
@@ -39,7 +40,7 @@ module Dependabot
|
|
|
39
40
|
dependencies: T::Array[Dependency],
|
|
40
41
|
credentials: T::Array[Dependabot::Credential],
|
|
41
42
|
security_fix: T::Boolean,
|
|
42
|
-
commit_message_options: T.nilable(T::Hash[Symbol, T.
|
|
43
|
+
commit_message_options: T.nilable(T::Hash[Symbol, T.anything])
|
|
43
44
|
)
|
|
44
45
|
.void
|
|
45
46
|
end
|
|
@@ -54,7 +55,10 @@ module Dependabot
|
|
|
54
55
|
@source = source
|
|
55
56
|
@credentials = credentials
|
|
56
57
|
@security_fix = security_fix
|
|
57
|
-
@commit_message_options =
|
|
58
|
+
@commit_message_options = T.let(
|
|
59
|
+
commit_message_options && CommitMessageOptions.from_hash(commit_message_options),
|
|
60
|
+
T.nilable(CommitMessageOptions)
|
|
61
|
+
)
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
sig { returns(String) }
|
|
@@ -85,7 +89,7 @@ module Dependabot
|
|
|
85
89
|
sig { returns(T::Array[Dependabot::Credential]) }
|
|
86
90
|
attr_reader :credentials
|
|
87
91
|
|
|
88
|
-
sig { returns(T.nilable(
|
|
92
|
+
sig { returns(T.nilable(CommitMessageOptions)) }
|
|
89
93
|
attr_reader :commit_message_options
|
|
90
94
|
|
|
91
95
|
sig { returns(T::Boolean) }
|
|
@@ -96,7 +100,7 @@ module Dependabot
|
|
|
96
100
|
sig { returns(T.nilable(String)) }
|
|
97
101
|
def commit_prefix
|
|
98
102
|
# If a preferred prefix has been explicitly provided, use it
|
|
99
|
-
return prefix_from_explicitly_provided_details if commit_message_options&.
|
|
103
|
+
return prefix_from_explicitly_provided_details if commit_message_options&.prefix?
|
|
100
104
|
|
|
101
105
|
# Otherwise, if there is a previous Dependabot commit and it used a
|
|
102
106
|
# known style, use that as our model for subsequent commits
|
|
@@ -112,7 +116,7 @@ module Dependabot
|
|
|
112
116
|
prefix = explicitly_provided_prefix_string
|
|
113
117
|
return if prefix.empty?
|
|
114
118
|
|
|
115
|
-
prefix += "(#{scope})" if commit_message_options&.
|
|
119
|
+
prefix += "(#{scope})" if commit_message_options&.include_scope
|
|
116
120
|
prefix += ":" if prefix.match?(/[A-Za-z0-9\)\]]\Z/)
|
|
117
121
|
prefix += " " unless prefix.end_with?(" ")
|
|
118
122
|
prefix
|
|
@@ -121,14 +125,14 @@ module Dependabot
|
|
|
121
125
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
122
126
|
sig { returns(String) }
|
|
123
127
|
def explicitly_provided_prefix_string
|
|
124
|
-
raise "No explicitly provided prefix!" unless commit_message_options&.
|
|
128
|
+
raise "No explicitly provided prefix!" unless commit_message_options&.prefix?
|
|
125
129
|
|
|
126
130
|
if dependencies.any?(&:production?)
|
|
127
|
-
commit_message_options&.
|
|
128
|
-
elsif commit_message_options&.
|
|
129
|
-
commit_message_options&.
|
|
131
|
+
commit_message_options&.prefix.to_s
|
|
132
|
+
elsif commit_message_options&.prefix_development?
|
|
133
|
+
commit_message_options&.prefix_development.to_s
|
|
130
134
|
else
|
|
131
|
-
commit_message_options&.
|
|
135
|
+
commit_message_options&.prefix.to_s
|
|
132
136
|
end
|
|
133
137
|
end
|
|
134
138
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
@@ -197,7 +197,7 @@ module Dependabot
|
|
|
197
197
|
milestone: nil,
|
|
198
198
|
branch_name_separator: "/",
|
|
199
199
|
branch_name_prefix: "dependabot",
|
|
200
|
-
branch_name_max_length:
|
|
200
|
+
branch_name_max_length: 100,
|
|
201
201
|
label_language: false,
|
|
202
202
|
automerge_candidate: false,
|
|
203
203
|
github_redirection_service: DEFAULT_GITHUB_REDIRECTION_SERVICE,
|
|
@@ -40,7 +40,7 @@ module Dependabot
|
|
|
40
40
|
sig { returns(T.nilable(String)) }
|
|
41
41
|
attr_reader :commit_message
|
|
42
42
|
|
|
43
|
-
sig { returns(T::Hash[Symbol,
|
|
43
|
+
sig { returns(T::Hash[Symbol, Integer]) }
|
|
44
44
|
attr_reader :provider_metadata
|
|
45
45
|
|
|
46
46
|
sig do
|
|
@@ -54,7 +54,7 @@ module Dependabot
|
|
|
54
54
|
author_details: T.nilable(T::Hash[Symbol, String]),
|
|
55
55
|
signature_key: T.nilable(String),
|
|
56
56
|
commit_message: T.nilable(String),
|
|
57
|
-
provider_metadata: T::Hash[Symbol,
|
|
57
|
+
provider_metadata: T::Hash[Symbol, Integer]
|
|
58
58
|
)
|
|
59
59
|
.void
|
|
60
60
|
end
|
|
@@ -84,7 +84,7 @@ module Dependabot
|
|
|
84
84
|
|
|
85
85
|
# TODO: Each implementation returns a client-specific type.
|
|
86
86
|
# We should standardise this to return a `Dependabot::Branch` type instead.
|
|
87
|
-
sig { returns(T.untyped) }
|
|
87
|
+
sig { returns(T.untyped) } # rubocop:disable Sorbet/ForbidTUntyped
|
|
88
88
|
def update
|
|
89
89
|
case source.provider
|
|
90
90
|
when "github" then github_updater.update
|
|
@@ -120,7 +120,7 @@ module Dependabot
|
|
|
120
120
|
files: files,
|
|
121
121
|
credentials: credentials,
|
|
122
122
|
pull_request_number: pull_request_number,
|
|
123
|
-
target_project_id:
|
|
123
|
+
target_project_id: provider_metadata[:target_project_id]
|
|
124
124
|
)
|
|
125
125
|
end
|
|
126
126
|
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
5
5
|
|
|
6
|
+
require "dependabot/dependency_requirement"
|
|
7
|
+
|
|
6
8
|
module Dependabot
|
|
7
9
|
module RequirementsUpdater
|
|
8
10
|
module Base
|
|
@@ -15,7 +17,7 @@ module Dependabot
|
|
|
15
17
|
|
|
16
18
|
interface!
|
|
17
19
|
|
|
18
|
-
sig { abstract.returns(T::Array[
|
|
20
|
+
sig { abstract.returns(T::Array[Dependabot::DependencyRequirement]) }
|
|
19
21
|
def updated_requirements; end
|
|
20
22
|
|
|
21
23
|
private
|
data/lib/dependabot/version.rb
CHANGED
|
@@ -32,6 +32,19 @@ module Dependabot
|
|
|
32
32
|
version.to_s.match?(ANCHORED_VERSION_PATTERN)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
# RubyGems 4 eagerly computes a numeric sort key in Gem::Version#initialize and
|
|
36
|
+
# skips it for prereleases. Dependabot's subclasses override #prerelease? with
|
|
37
|
+
# ecosystem-specific semantics, so a version with alphabetic segments (e.g.
|
|
38
|
+
# "1.0.0.RELEASE" or "2.0.0.post1") can report prerelease? == false and reach
|
|
39
|
+
# RubyGems' radix comparison, which raises when a segment is a String. Returning
|
|
40
|
+
# nil for those versions falls back to the segment-by-segment comparison.
|
|
41
|
+
sig { override.overridable.returns(T.nilable(Integer)) }
|
|
42
|
+
def compute_sort_key
|
|
43
|
+
return if canonical_segments.any?(String)
|
|
44
|
+
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
|
|
35
48
|
sig { overridable.returns(String) }
|
|
36
49
|
def to_semver
|
|
37
50
|
@original_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.384.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -552,6 +552,7 @@ files:
|
|
|
552
552
|
- lib/dependabot/file_updaters/base.rb
|
|
553
553
|
- lib/dependabot/file_updaters/vendor_updater.rb
|
|
554
554
|
- lib/dependabot/git_commit_checker.rb
|
|
555
|
+
- lib/dependabot/git_cooldown_date_resolver.rb
|
|
555
556
|
- lib/dependabot/git_metadata_fetcher.rb
|
|
556
557
|
- lib/dependabot/git_ref.rb
|
|
557
558
|
- lib/dependabot/git_tag_details.rb
|
|
@@ -579,6 +580,7 @@ files:
|
|
|
579
580
|
- lib/dependabot/pull_request_creator/branch_namer/multi_ecosystem_strategy.rb
|
|
580
581
|
- lib/dependabot/pull_request_creator/branch_namer/solo_strategy.rb
|
|
581
582
|
- lib/dependabot/pull_request_creator/codecommit.rb
|
|
583
|
+
- lib/dependabot/pull_request_creator/commit_message_options.rb
|
|
582
584
|
- lib/dependabot/pull_request_creator/commit_signer.rb
|
|
583
585
|
- lib/dependabot/pull_request_creator/github.rb
|
|
584
586
|
- lib/dependabot/pull_request_creator/gitlab.rb
|
|
@@ -619,7 +621,7 @@ licenses:
|
|
|
619
621
|
- MIT
|
|
620
622
|
metadata:
|
|
621
623
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
622
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
624
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.384.0
|
|
623
625
|
rdoc_options: []
|
|
624
626
|
require_paths:
|
|
625
627
|
- lib
|
|
@@ -634,7 +636,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
634
636
|
- !ruby/object:Gem::Version
|
|
635
637
|
version: 3.3.7
|
|
636
638
|
requirements: []
|
|
637
|
-
rubygems_version:
|
|
639
|
+
rubygems_version: 4.0.14
|
|
638
640
|
specification_version: 4
|
|
639
641
|
summary: Shared code used across Dependabot Core
|
|
640
642
|
test_files: []
|