dependabot-common 0.392.0 → 0.393.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dependabot/clients/azure.rb +42 -22
  3. data/lib/dependabot/clients/bitbucket.rb +52 -26
  4. data/lib/dependabot/clients/bitbucket_with_retries.rb +11 -12
  5. data/lib/dependabot/clients/codecommit.rb +73 -53
  6. data/lib/dependabot/clients/github_resource_parser.rb +70 -0
  7. data/lib/dependabot/clients/github_with_retries.rb +63 -23
  8. data/lib/dependabot/clients/gitlab_with_retries.rb +19 -17
  9. data/lib/dependabot/clients/json_response_parser.rb +103 -0
  10. data/lib/dependabot/command_helpers.rb +79 -11
  11. data/lib/dependabot/credential.rb +12 -3
  12. data/lib/dependabot/file_fetchers/base.rb +196 -140
  13. data/lib/dependabot/file_updaters/vendor_updater.rb +8 -2
  14. data/lib/dependabot/git_tag_details.rb +8 -14
  15. data/lib/dependabot/metadata_finders/base/changelog_finder.rb +211 -110
  16. data/lib/dependabot/metadata_finders/base/commit_response_parser.rb +68 -0
  17. data/lib/dependabot/metadata_finders/base/commits_finder.rb +44 -38
  18. data/lib/dependabot/pull_request_creator/azure.rb +1 -1
  19. data/lib/dependabot/pull_request_creator/codecommit.rb +10 -12
  20. data/lib/dependabot/pull_request_creator/github.rb +55 -35
  21. data/lib/dependabot/pull_request_creator/gitlab.rb +37 -11
  22. data/lib/dependabot/pull_request_creator/labeler.rb +65 -15
  23. data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +179 -78
  24. data/lib/dependabot/pull_request_updater/azure.rb +63 -11
  25. data/lib/dependabot/pull_request_updater/github.rb +44 -34
  26. data/lib/dependabot/pull_request_updater/gitlab.rb +23 -12
  27. data/lib/dependabot/pull_request_updater.rb +3 -3
  28. data/lib/dependabot/shared_helpers.rb +77 -32
  29. data/lib/dependabot/update_checkers/base.rb +9 -5
  30. data/lib/dependabot/update_checkers/version_filters.rb +5 -0
  31. data/lib/dependabot/update_checkers/vulnerability_audit.rb +282 -0
  32. data/lib/dependabot/workspace/git.rb +35 -4
  33. data/lib/dependabot.rb +1 -1
  34. metadata +6 -2
@@ -0,0 +1,282 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ module Dependabot
7
+ module UpdateCheckers
8
+ Conflict = T.type_alias { T::Hash[String, Object] }
9
+
10
+ class VulnerabilityAudit < T::ImmutableStruct
11
+ extend T::Sig
12
+
13
+ module ValueParser
14
+ extend T::Sig
15
+
16
+ sig { params(value: Object, context: String).returns(T::Hash[String, Object]) }
17
+ def self.object_hash(value, context)
18
+ raise TypeError, "#{context} must be an object" unless value.is_a?(Hash)
19
+
20
+ result = T.let({}, T::Hash[String, Object])
21
+ value.each do |raw_key, raw_value|
22
+ key = T.cast(raw_key, Object)
23
+ raise TypeError, "#{context} keys must be strings" unless key.is_a?(String)
24
+
25
+ result[key] = T.cast(raw_value, Object)
26
+ end
27
+ result
28
+ end
29
+
30
+ sig { params(hash: T::Hash[String, Object], key: String, context: T.nilable(String)).returns(String) }
31
+ def self.string(hash, key, context: nil)
32
+ value = hash[key]
33
+ return value if value.is_a?(String)
34
+
35
+ raise TypeError, "#{field_name(context, key)} must be a string"
36
+ end
37
+
38
+ sig do
39
+ params(
40
+ hash: T::Hash[String, Object],
41
+ key: String,
42
+ context: T.nilable(String)
43
+ ).returns(T.nilable(String))
44
+ end
45
+ def self.optional_string(hash, key, context: nil)
46
+ value = hash[key]
47
+ return if value.nil?
48
+ return value if value.is_a?(String)
49
+
50
+ raise TypeError, "#{field_name(context, key)} must be a string or nil"
51
+ end
52
+
53
+ sig { params(hash: T::Hash[String, Object], key: String, context: T.nilable(String)).returns(T::Boolean) }
54
+ def self.boolean(hash, key, context: nil)
55
+ value = hash[key]
56
+ return value if value == true || value == false
57
+
58
+ raise TypeError, "#{field_name(context, key)} must be a boolean"
59
+ end
60
+
61
+ sig { params(value: Object, context: String).returns(T::Array[String]) }
62
+ def self.string_array(value, context)
63
+ raise TypeError, "#{context} must be an array" unless value.is_a?(Array)
64
+
65
+ value.map do |item|
66
+ item = T.cast(item, Object)
67
+ raise TypeError, "#{context} must contain only strings" unless item.is_a?(String)
68
+
69
+ item
70
+ end
71
+ end
72
+
73
+ sig { params(context: T.nilable(String), key: String).returns(String) }
74
+ def self.field_name(context, key)
75
+ [context, key].compact.join(" ")
76
+ end
77
+ private_class_method :field_name
78
+ end
79
+ private_constant :ValueParser
80
+
81
+ class FixUpdate < T::ImmutableStruct
82
+ extend T::Sig
83
+
84
+ const :dependency_name, String
85
+ const :current_version, String
86
+ const :target_version, T.nilable(String), default: nil
87
+ const :target_version_provided, T::Boolean, default: false
88
+ const :top_level_ancestors, T::Array[String], default: []
89
+ const :top_level_ancestors_provided, T::Boolean, default: false
90
+
91
+ sig { params(value: Object).returns(FixUpdate) }
92
+ def self.from_object(value)
93
+ hash = ValueParser.object_hash(value, "fix update")
94
+ target_version_provided = hash.key?("target_version")
95
+ top_level_ancestors_provided = hash.key?("top_level_ancestors")
96
+ top_level_ancestors =
97
+ if top_level_ancestors_provided
98
+ ValueParser.string_array(hash["top_level_ancestors"], "fix update top_level_ancestors")
99
+ else
100
+ []
101
+ end
102
+
103
+ new(
104
+ dependency_name: ValueParser.string(hash, "dependency_name", context: "fix update"),
105
+ current_version: ValueParser.string(hash, "current_version", context: "fix update"),
106
+ target_version: ValueParser.optional_string(hash, "target_version", context: "fix update"),
107
+ target_version_provided: target_version_provided,
108
+ top_level_ancestors: top_level_ancestors,
109
+ top_level_ancestors_provided: top_level_ancestors_provided
110
+ )
111
+ end
112
+
113
+ sig { returns(T::Boolean) }
114
+ def target_version_provided?
115
+ target_version_provided
116
+ end
117
+
118
+ sig { returns(Conflict) }
119
+ def to_h
120
+ result = T.let(
121
+ {
122
+ "dependency_name" => dependency_name,
123
+ "current_version" => current_version
124
+ },
125
+ Conflict
126
+ )
127
+ result["target_version"] = target_version if target_version_provided?
128
+ result["top_level_ancestors"] = top_level_ancestors if top_level_ancestors_provided
129
+ result
130
+ end
131
+ end
132
+
133
+ class BlockingDependency < T::ImmutableStruct
134
+ extend T::Sig
135
+
136
+ const :name, String
137
+ const :version, String
138
+ const :requirement, String
139
+ const :top_level_ancestor, String
140
+
141
+ sig { params(value: Object).returns(BlockingDependency) }
142
+ def self.from_object(value)
143
+ hash = ValueParser.object_hash(value, "blocking dependency")
144
+ new(
145
+ name: ValueParser.string(hash, "name", context: "blocking dependency"),
146
+ version: ValueParser.string(hash, "version", context: "blocking dependency"),
147
+ requirement: ValueParser.string(hash, "requirement", context: "blocking dependency"),
148
+ top_level_ancestor: ValueParser.string(hash, "top_level_ancestor", context: "blocking dependency")
149
+ )
150
+ end
151
+
152
+ sig { returns(Conflict) }
153
+ def to_h
154
+ {
155
+ "name" => name,
156
+ "version" => version,
157
+ "requirement" => requirement,
158
+ "top_level_ancestor" => top_level_ancestor
159
+ }
160
+ end
161
+ end
162
+
163
+ const :dependency_name, String
164
+ const :current_version, T.nilable(String), default: nil
165
+ const :current_version_provided, T::Boolean, default: false
166
+ const :target_version, T.nilable(String), default: nil
167
+ const :target_version_provided, T::Boolean, default: false
168
+ const :fix_available, T::Boolean
169
+ const :fix_updates, T::Array[FixUpdate]
170
+ const :top_level_ancestors, T::Array[String]
171
+ const :blocking_dependencies, T.nilable(T::Array[BlockingDependency]), default: nil
172
+ const :blocking_dependencies_provided, T::Boolean, default: false
173
+ const :explanation, T.nilable(String), default: nil
174
+
175
+ sig { params(value: Object).returns(VulnerabilityAudit) }
176
+ def self.from_object(value)
177
+ hash = ValueParser.object_hash(value, "audit result")
178
+ current_version_provided = hash.key?("current_version")
179
+ target_version_provided = hash.key?("target_version")
180
+ blocking_dependencies_provided = hash.key?("blocking_dependencies")
181
+
182
+ new(
183
+ dependency_name: ValueParser.string(hash, "dependency_name"),
184
+ current_version: ValueParser.optional_string(hash, "current_version"),
185
+ current_version_provided: current_version_provided,
186
+ target_version: ValueParser.optional_string(hash, "target_version"),
187
+ target_version_provided: target_version_provided,
188
+ fix_available: ValueParser.boolean(hash, "fix_available"),
189
+ fix_updates: parse_fix_updates(hash["fix_updates"]),
190
+ top_level_ancestors: ValueParser.string_array(hash["top_level_ancestors"], "top_level_ancestors"),
191
+ blocking_dependencies: parse_blocking_dependencies(hash["blocking_dependencies"]),
192
+ blocking_dependencies_provided: blocking_dependencies_provided
193
+ )
194
+ end
195
+
196
+ sig do
197
+ params(
198
+ dependency_name: String,
199
+ explanation: T.nilable(String),
200
+ blocking_dependencies: T.nilable(T::Array[BlockingDependency]),
201
+ blocking_dependencies_provided: T::Boolean
202
+ ).returns(VulnerabilityAudit)
203
+ end
204
+ def self.unavailable(
205
+ dependency_name:,
206
+ explanation: nil,
207
+ blocking_dependencies: nil,
208
+ blocking_dependencies_provided: false
209
+ )
210
+ new(
211
+ dependency_name: dependency_name,
212
+ fix_available: false,
213
+ fix_updates: [],
214
+ top_level_ancestors: [],
215
+ blocking_dependencies: blocking_dependencies,
216
+ blocking_dependencies_provided: blocking_dependencies_provided,
217
+ explanation: explanation
218
+ )
219
+ end
220
+
221
+ sig { returns(T::Boolean) }
222
+ def current_version_provided?
223
+ current_version_provided
224
+ end
225
+
226
+ sig { returns(T::Boolean) }
227
+ def target_version_provided?
228
+ target_version_provided
229
+ end
230
+
231
+ sig { returns(T::Boolean) }
232
+ def blocking_dependencies_provided?
233
+ blocking_dependencies_provided
234
+ end
235
+
236
+ sig { params(message: String).returns(VulnerabilityAudit) }
237
+ def unavailable_with_explanation(message)
238
+ VulnerabilityAudit.unavailable(
239
+ dependency_name: dependency_name,
240
+ explanation: message,
241
+ blocking_dependencies: blocking_dependencies,
242
+ blocking_dependencies_provided: blocking_dependencies_provided?
243
+ )
244
+ end
245
+
246
+ sig { returns(Conflict) }
247
+ def to_h
248
+ result = T.let(
249
+ {
250
+ "dependency_name" => dependency_name,
251
+ "fix_available" => fix_available,
252
+ "fix_updates" => fix_updates.map(&:to_h),
253
+ "top_level_ancestors" => top_level_ancestors
254
+ },
255
+ Conflict
256
+ )
257
+ result["current_version"] = current_version if current_version_provided?
258
+ result["target_version"] = target_version if target_version_provided?
259
+ result["blocking_dependencies"] = blocking_dependencies&.map(&:to_h) if blocking_dependencies_provided?
260
+ result["explanation"] = explanation if explanation
261
+ result
262
+ end
263
+
264
+ sig { params(value: Object).returns(T::Array[FixUpdate]) }
265
+ def self.parse_fix_updates(value)
266
+ raise TypeError, "fix_updates must be an array" unless value.is_a?(Array)
267
+
268
+ value.map { |update| FixUpdate.from_object(T.cast(update, Object)) }
269
+ end
270
+ private_class_method :parse_fix_updates
271
+
272
+ sig { params(value: Object).returns(T.nilable(T::Array[BlockingDependency])) }
273
+ def self.parse_blocking_dependencies(value)
274
+ return if value.nil?
275
+ raise TypeError, "blocking_dependencies must be an array or nil" unless value.is_a?(Array)
276
+
277
+ value.map { |dependency| BlockingDependency.from_object(T.cast(dependency, Object)) }
278
+ end
279
+ private_class_method :parse_blocking_dependencies
280
+ end
281
+ end
282
+ end
@@ -1,4 +1,4 @@
1
- # typed: strict
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -152,9 +152,40 @@ module Dependabot
152
152
  run_shell_command("git clean -fx .")
153
153
  end
154
154
 
155
- sig { params(args: SharedHelpers::Command, kwargs: T.any(T::Boolean, String)).returns(String) }
156
- def run_shell_command(*args, **kwargs)
157
- Dir.chdir(path) { T.unsafe(SharedHelpers).run_shell_command(*args, **kwargs) }
155
+ sig do
156
+ params(
157
+ command: SharedHelpers::Command,
158
+ allow_unsafe_shell_command: T::Boolean,
159
+ cwd: T.nilable(String),
160
+ env: T.nilable(T::Hash[String, String]),
161
+ fingerprint: T.nilable(String),
162
+ stderr_to_stdout: T::Boolean,
163
+ timeout: Integer,
164
+ output_observer: CommandHelpers::OutputObserver
165
+ ).returns(String)
166
+ end
167
+ def run_shell_command(
168
+ command,
169
+ allow_unsafe_shell_command: false,
170
+ cwd: nil,
171
+ env: {},
172
+ fingerprint: nil,
173
+ stderr_to_stdout: true,
174
+ timeout: CommandHelpers::TIMEOUTS::DEFAULT,
175
+ output_observer: nil
176
+ )
177
+ Dir.chdir(path) do
178
+ SharedHelpers.run_shell_command(
179
+ command,
180
+ allow_unsafe_shell_command: allow_unsafe_shell_command,
181
+ cwd: cwd,
182
+ env: env,
183
+ fingerprint: fingerprint,
184
+ stderr_to_stdout: stderr_to_stdout,
185
+ timeout: timeout,
186
+ output_observer: output_observer
187
+ )
188
+ end
158
189
  end
159
190
 
160
191
  sig { params(message: String).void }
data/lib/dependabot.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Dependabot
5
- VERSION = "0.392.0"
5
+ VERSION = "0.393.0"
6
6
  end
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.392.0
4
+ version: 0.393.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -519,8 +519,10 @@ files:
519
519
  - lib/dependabot/clients/bitbucket_with_retries.rb
520
520
  - lib/dependabot/clients/codecommit.rb
521
521
  - lib/dependabot/clients/github_release.rb
522
+ - lib/dependabot/clients/github_resource_parser.rb
522
523
  - lib/dependabot/clients/github_with_retries.rb
523
524
  - lib/dependabot/clients/gitlab_with_retries.rb
525
+ - lib/dependabot/clients/json_response_parser.rb
524
526
  - lib/dependabot/command_helpers.rb
525
527
  - lib/dependabot/config.rb
526
528
  - lib/dependabot/config/file.rb
@@ -566,6 +568,7 @@ files:
566
568
  - lib/dependabot/metadata_finders/base.rb
567
569
  - lib/dependabot/metadata_finders/base/changelog_finder.rb
568
570
  - lib/dependabot/metadata_finders/base/changelog_pruner.rb
571
+ - lib/dependabot/metadata_finders/base/commit_response_parser.rb
569
572
  - lib/dependabot/metadata_finders/base/commits_finder.rb
570
573
  - lib/dependabot/metadata_finders/base/release_finder.rb
571
574
  - lib/dependabot/notices.rb
@@ -613,6 +616,7 @@ files:
613
616
  - lib/dependabot/update_checkers/base.rb
614
617
  - lib/dependabot/update_checkers/cooldown_calculation.rb
615
618
  - lib/dependabot/update_checkers/version_filters.rb
619
+ - lib/dependabot/update_checkers/vulnerability_audit.rb
616
620
  - lib/dependabot/utils.rb
617
621
  - lib/dependabot/version.rb
618
622
  - lib/dependabot/workspace.rb
@@ -625,7 +629,7 @@ licenses:
625
629
  - MIT
626
630
  metadata:
627
631
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
628
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.392.0
632
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.393.0
629
633
  rdoc_options: []
630
634
  require_paths:
631
635
  - lib