dependabot-common 0.239.0 → 0.241.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dependabot/config/file_fetcher.rb +11 -4
- data/lib/dependabot/dependency.rb +2 -2
- data/lib/dependabot/dependency_file.rb +4 -10
- data/lib/dependabot/file_fetchers/base.rb +20 -8
- data/lib/dependabot/file_parsers/base.rb +39 -9
- data/lib/dependabot/git_commit_checker.rb +160 -48
- data/lib/dependabot/metadata_finders/base.rb +94 -40
- data/lib/dependabot/pull_request_creator/branch_namer/base.rb +5 -0
- data/lib/dependabot/pull_request_creator/branch_namer/dependency_group_strategy.rb +32 -6
- data/lib/dependabot/pull_request_creator/branch_namer/solo_strategy.rb +59 -31
- data/lib/dependabot/pull_request_creator/branch_namer.rb +49 -8
- data/lib/dependabot/pull_request_creator/gitlab.rb +1 -1
- data/lib/dependabot/pull_request_creator/labeler.rb +116 -36
- data/lib/dependabot/pull_request_creator.rb +152 -18
- data/lib/dependabot/pull_request_updater.rb +50 -3
- data/lib/dependabot/registry_client.rb +26 -4
- data/lib/dependabot/version.rb +57 -3
- data/lib/dependabot/workspace/git.rb +27 -7
- data/lib/dependabot.rb +1 -1
- metadata +19 -5
@@ -1,20 +1,29 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "octokit"
|
5
|
+
require "sorbet-runtime"
|
5
6
|
require "dependabot/pull_request_creator"
|
7
|
+
|
6
8
|
module Dependabot
|
7
9
|
class PullRequestCreator
|
10
|
+
# rubocop:disable Metrics/ClassLength
|
8
11
|
class Labeler
|
12
|
+
extend T::Sig
|
13
|
+
|
9
14
|
DEPENDENCIES_LABEL_REGEX = %r{^[^/]*dependenc[^/]+$}i
|
10
15
|
DEFAULT_DEPENDENCIES_LABEL = "dependencies"
|
11
16
|
DEFAULT_SECURITY_LABEL = "security"
|
12
17
|
|
13
|
-
@package_manager_labels = {}
|
18
|
+
@package_manager_labels = T.let({}, T::Hash[String, T::Hash[Symbol, String]])
|
14
19
|
|
15
20
|
class << self
|
21
|
+
extend T::Sig
|
22
|
+
|
23
|
+
sig { returns(T::Hash[String, T::Hash[Symbol, String]]) }
|
16
24
|
attr_reader :package_manager_labels
|
17
25
|
|
26
|
+
sig { params(package_manager: String).returns(T::Hash[Symbol, String]) }
|
18
27
|
def label_details_for_package_manager(package_manager)
|
19
28
|
label_details = @package_manager_labels[package_manager]
|
20
29
|
return label_details if label_details
|
@@ -22,11 +31,24 @@ module Dependabot
|
|
22
31
|
raise "Unsupported package_manager #{package_manager}"
|
23
32
|
end
|
24
33
|
|
34
|
+
sig { params(package_manager: String, label_details: T::Hash[Symbol, String]).void }
|
25
35
|
def register_label_details(package_manager, label_details)
|
26
36
|
@package_manager_labels[package_manager] = label_details
|
27
37
|
end
|
28
38
|
end
|
29
39
|
|
40
|
+
sig do
|
41
|
+
params(
|
42
|
+
source: Dependabot::Source,
|
43
|
+
custom_labels: T.nilable(T::Array[String]),
|
44
|
+
credentials: T::Array[T::Hash[String, String]],
|
45
|
+
dependencies: T::Array[Dependency],
|
46
|
+
includes_security_fixes: T::Boolean,
|
47
|
+
label_language: T::Boolean,
|
48
|
+
automerge_candidate: T::Boolean
|
49
|
+
)
|
50
|
+
.void
|
51
|
+
end
|
30
52
|
def initialize(source:, custom_labels:, credentials:, dependencies:,
|
31
53
|
includes_security_fixes:, label_language:,
|
32
54
|
automerge_candidate:)
|
@@ -39,12 +61,14 @@ module Dependabot
|
|
39
61
|
@automerge_candidate = automerge_candidate
|
40
62
|
end
|
41
63
|
|
64
|
+
sig { void }
|
42
65
|
def create_default_labels_if_required
|
43
66
|
create_default_dependencies_label_if_required
|
44
67
|
create_default_security_label_if_required
|
45
68
|
create_default_language_label_if_required
|
46
69
|
end
|
47
70
|
|
71
|
+
sig { returns(T::Array[String]) }
|
48
72
|
def labels_for_pr
|
49
73
|
[
|
50
74
|
*default_labels_for_pr,
|
@@ -54,13 +78,14 @@ module Dependabot
|
|
54
78
|
].compact.uniq
|
55
79
|
end
|
56
80
|
|
81
|
+
sig { params(pull_request_number: Integer).void }
|
57
82
|
def label_pull_request(pull_request_number)
|
58
83
|
create_default_labels_if_required
|
59
84
|
|
60
85
|
return if labels_for_pr.none?
|
61
86
|
raise "Only GitHub!" unless source.provider == "github"
|
62
87
|
|
63
|
-
github_client_for_source.add_labels_to_an_issue(
|
88
|
+
T.unsafe(github_client_for_source).add_labels_to_an_issue(
|
64
89
|
source.repo,
|
65
90
|
pull_request_number,
|
66
91
|
labels_for_pr
|
@@ -76,20 +101,34 @@ module Dependabot
|
|
76
101
|
|
77
102
|
private
|
78
103
|
|
79
|
-
|
104
|
+
sig { returns(Dependabot::Source) }
|
105
|
+
attr_reader :source
|
106
|
+
|
107
|
+
sig { returns(T.nilable(T::Array[String])) }
|
108
|
+
attr_reader :custom_labels
|
80
109
|
|
110
|
+
sig { returns(T::Array[T::Hash[String, String]]) }
|
111
|
+
attr_reader :credentials
|
112
|
+
|
113
|
+
sig { returns(T::Array[Dependency]) }
|
114
|
+
attr_reader :dependencies
|
115
|
+
|
116
|
+
sig { returns(T::Boolean) }
|
81
117
|
def label_language?
|
82
118
|
@label_language
|
83
119
|
end
|
84
120
|
|
121
|
+
sig { returns(T::Boolean) }
|
85
122
|
def includes_security_fixes?
|
86
123
|
@includes_security_fixes
|
87
124
|
end
|
88
125
|
|
126
|
+
sig { returns(T::Boolean) }
|
89
127
|
def automerge_candidate?
|
90
128
|
@automerge_candidate
|
91
129
|
end
|
92
130
|
|
131
|
+
sig { returns(T.nilable(String)) }
|
93
132
|
def update_type
|
94
133
|
return unless dependencies.any?(&:previous_version)
|
95
134
|
|
@@ -101,9 +140,10 @@ module Dependabot
|
|
101
140
|
end
|
102
141
|
end
|
103
142
|
|
143
|
+
sig { returns(Integer) }
|
104
144
|
def precision
|
105
|
-
dependencies.map do |dep|
|
106
|
-
new_version_parts = version(dep).split(/[.+]/)
|
145
|
+
T.must(dependencies.map do |dep|
|
146
|
+
new_version_parts = T.must(version(dep)).split(/[.+]/)
|
107
147
|
old_version_parts = previous_version(dep)&.split(/[.+]/) || []
|
108
148
|
all_parts = new_version_parts.first(3) + old_version_parts.first(3)
|
109
149
|
# rubocop:disable Performance/RedundantEqualityComparisonBlock
|
@@ -113,10 +153,11 @@ module Dependabot
|
|
113
153
|
next 2 if new_version_parts[1] != old_version_parts[1]
|
114
154
|
|
115
155
|
3
|
116
|
-
end.min
|
156
|
+
end.min)
|
117
157
|
end
|
118
158
|
|
119
159
|
# rubocop:disable Metrics/PerceivedComplexity
|
160
|
+
sig { params(dep: Dependabot::Dependency).returns(T.nilable(String)) }
|
120
161
|
def version(dep)
|
121
162
|
return dep.version if version_class.correct?(dep.version)
|
122
163
|
|
@@ -134,12 +175,13 @@ module Dependabot
|
|
134
175
|
# rubocop:enable Metrics/PerceivedComplexity
|
135
176
|
|
136
177
|
# rubocop:disable Metrics/PerceivedComplexity
|
178
|
+
sig { params(dep: Dependabot::Dependency).returns(T.nilable(String)) }
|
137
179
|
def previous_version(dep)
|
138
180
|
version_str = dep.previous_version
|
139
181
|
return version_str if version_class.correct?(version_str)
|
140
182
|
|
141
|
-
source = dep.previous_requirements
|
142
|
-
|
183
|
+
source = T.must(dep.previous_requirements)
|
184
|
+
.find { |r| r.fetch(:source) }&.fetch(:source)
|
143
185
|
type = source&.fetch("type", nil) || source&.fetch(:type)
|
144
186
|
return version_str unless type == "git"
|
145
187
|
|
@@ -152,6 +194,7 @@ module Dependabot
|
|
152
194
|
end
|
153
195
|
# rubocop:enable Metrics/PerceivedComplexity
|
154
196
|
|
197
|
+
sig { returns(T.nilable(T::Array[String])) }
|
155
198
|
def create_default_dependencies_label_if_required
|
156
199
|
return if custom_labels
|
157
200
|
return if dependencies_label_exists?
|
@@ -159,6 +202,7 @@ module Dependabot
|
|
159
202
|
create_dependencies_label
|
160
203
|
end
|
161
204
|
|
205
|
+
sig { returns(T.nilable(T::Array[String])) }
|
162
206
|
def create_default_security_label_if_required
|
163
207
|
return unless includes_security_fixes?
|
164
208
|
return if security_label_exists?
|
@@ -166,6 +210,7 @@ module Dependabot
|
|
166
210
|
create_security_label
|
167
211
|
end
|
168
212
|
|
213
|
+
sig { returns(T.nilable(T::Array[String])) }
|
169
214
|
def create_default_language_label_if_required
|
170
215
|
return unless label_language?
|
171
216
|
return if custom_labels
|
@@ -174,12 +219,13 @@ module Dependabot
|
|
174
219
|
create_language_label
|
175
220
|
end
|
176
221
|
|
222
|
+
sig { returns(T::Array[String]) }
|
177
223
|
def default_labels_for_pr
|
178
224
|
if custom_labels
|
179
225
|
# Azure does not have centralised labels
|
180
|
-
return custom_labels if source.provider == "azure"
|
226
|
+
return T.must(custom_labels) if source.provider == "azure"
|
181
227
|
|
182
|
-
custom_labels & labels
|
228
|
+
T.must(custom_labels) & labels
|
183
229
|
else
|
184
230
|
[
|
185
231
|
default_dependencies_label,
|
@@ -188,26 +234,31 @@ module Dependabot
|
|
188
234
|
end
|
189
235
|
end
|
190
236
|
|
191
|
-
# Find the exact match first and then fallback to *
|
237
|
+
# Find the exact match first and then fallback to *dependency* label
|
238
|
+
sig { returns(T.nilable(String)) }
|
192
239
|
def default_dependencies_label
|
193
240
|
labels.find { |l| l == DEFAULT_DEPENDENCIES_LABEL } ||
|
194
241
|
labels.find { |l| l.match?(DEPENDENCIES_LABEL_REGEX) }
|
195
242
|
end
|
196
243
|
|
244
|
+
sig { returns(T::Boolean) }
|
197
245
|
def dependencies_label_exists?
|
198
246
|
labels.any? { |l| l.match?(DEPENDENCIES_LABEL_REGEX) }
|
199
247
|
end
|
200
248
|
|
249
|
+
sig { returns(T::Boolean) }
|
201
250
|
def security_label_exists?
|
202
251
|
!security_label.nil?
|
203
252
|
end
|
204
253
|
|
205
254
|
# Find the exact match first and then fallback to * security* label
|
255
|
+
sig { returns(T.nilable(String)) }
|
206
256
|
def security_label
|
207
257
|
labels.find { |l| l == DEFAULT_SECURITY_LABEL } ||
|
208
258
|
labels.find { |l| l.match?(/security/i) }
|
209
259
|
end
|
210
260
|
|
261
|
+
sig { returns(T::Boolean) }
|
211
262
|
def label_update_type?
|
212
263
|
# If a `skip-release` label exists then this repo is likely to be using
|
213
264
|
# an auto-releasing service (like auto). We don't want to hijack that
|
@@ -218,46 +269,54 @@ module Dependabot
|
|
218
269
|
(%w(major minor patch) - labels.map(&:downcase)).empty?
|
219
270
|
end
|
220
271
|
|
272
|
+
sig { returns(T.nilable(String)) }
|
221
273
|
def semver_label
|
222
274
|
return unless update_type
|
223
275
|
|
224
276
|
labels.find { |l| l.downcase == update_type.to_s }
|
225
277
|
end
|
226
278
|
|
279
|
+
sig { returns(T.nilable(String)) }
|
227
280
|
def automerge_label
|
228
|
-
labels.find { |l| l.casecmp("automerge")
|
281
|
+
labels.find { |l| l.casecmp("automerge")&.zero? }
|
229
282
|
end
|
230
283
|
|
284
|
+
sig { returns(T::Boolean) }
|
231
285
|
def language_label_exists?
|
232
286
|
!language_label.nil?
|
233
287
|
end
|
234
288
|
|
289
|
+
sig { returns(T.nilable(String)) }
|
235
290
|
def language_label
|
236
291
|
label_name =
|
237
292
|
self.class.label_details_for_package_manager(package_manager)
|
238
293
|
.fetch(:name)
|
239
|
-
labels.find { |l| l.casecmp(label_name)
|
294
|
+
labels.find { |l| l.casecmp(label_name)&.zero? }
|
240
295
|
end
|
241
296
|
|
297
|
+
sig { returns(T::Array[String]) }
|
242
298
|
def labels
|
243
|
-
@labels ||=
|
299
|
+
@labels ||= T.let(
|
244
300
|
case source.provider
|
245
301
|
when "github" then fetch_github_labels
|
246
302
|
when "gitlab" then fetch_gitlab_labels
|
247
303
|
when "azure" then fetch_azure_labels
|
248
304
|
else raise "Unsupported provider #{source.provider}"
|
249
|
-
end
|
305
|
+
end,
|
306
|
+
T.nilable(T::Array[String])
|
307
|
+
)
|
250
308
|
end
|
251
309
|
|
310
|
+
sig { returns(T::Array[String]) }
|
252
311
|
def fetch_github_labels
|
253
312
|
client = github_client_for_source
|
254
313
|
|
255
314
|
labels =
|
256
|
-
client
|
257
|
-
|
258
|
-
|
315
|
+
T.unsafe(client)
|
316
|
+
.labels(source.repo, per_page: 100)
|
317
|
+
.map(&:name)
|
259
318
|
|
260
|
-
next_link = client.last_response.rels[:next]
|
319
|
+
next_link = T.unsafe(client).last_response.rels[:next]
|
261
320
|
|
262
321
|
while next_link
|
263
322
|
next_page = next_link.get
|
@@ -268,13 +327,15 @@ module Dependabot
|
|
268
327
|
labels
|
269
328
|
end
|
270
329
|
|
330
|
+
sig { returns(T::Array[String]) }
|
271
331
|
def fetch_gitlab_labels
|
272
|
-
gitlab_client_for_source
|
273
|
-
|
274
|
-
|
275
|
-
|
332
|
+
T.unsafe(gitlab_client_for_source)
|
333
|
+
.labels(source.repo, per_page: 100)
|
334
|
+
.auto_paginate
|
335
|
+
.map(&:name)
|
276
336
|
end
|
277
337
|
|
338
|
+
sig { returns(T::Array[String]) }
|
278
339
|
def fetch_azure_labels
|
279
340
|
language_name =
|
280
341
|
self.class.label_details_for_package_manager(package_manager)
|
@@ -288,6 +349,7 @@ module Dependabot
|
|
288
349
|
].uniq
|
289
350
|
end
|
290
351
|
|
352
|
+
sig { returns(T.nilable(T::Array[String])) }
|
291
353
|
def create_dependencies_label
|
292
354
|
case source.provider
|
293
355
|
when "github" then create_github_dependencies_label
|
@@ -297,6 +359,7 @@ module Dependabot
|
|
297
359
|
end
|
298
360
|
end
|
299
361
|
|
362
|
+
sig { returns(T.nilable(T::Array[String])) }
|
300
363
|
def create_security_label
|
301
364
|
case source.provider
|
302
365
|
when "github" then create_github_security_label
|
@@ -306,6 +369,7 @@ module Dependabot
|
|
306
369
|
end
|
307
370
|
end
|
308
371
|
|
372
|
+
sig { returns(T.nilable(T::Array[String])) }
|
309
373
|
def create_language_label
|
310
374
|
case source.provider
|
311
375
|
when "github" then create_github_language_label
|
@@ -315,8 +379,9 @@ module Dependabot
|
|
315
379
|
end
|
316
380
|
end
|
317
381
|
|
382
|
+
sig { returns(T::Array[String]) }
|
318
383
|
def create_github_dependencies_label
|
319
|
-
github_client_for_source.add_label(
|
384
|
+
T.unsafe(github_client_for_source).add_label(
|
320
385
|
source.repo, DEFAULT_DEPENDENCIES_LABEL, "0366d6",
|
321
386
|
description: "Pull requests that update a dependency file",
|
322
387
|
accept: "application/vnd.github.symmetra-preview+json"
|
@@ -328,16 +393,18 @@ module Dependabot
|
|
328
393
|
@labels = [*@labels, DEFAULT_DEPENDENCIES_LABEL].uniq
|
329
394
|
end
|
330
395
|
|
396
|
+
sig { returns(T::Array[String]) }
|
331
397
|
def create_gitlab_dependencies_label
|
332
|
-
gitlab_client_for_source.create_label(
|
398
|
+
T.unsafe(gitlab_client_for_source).create_label(
|
333
399
|
source.repo, DEFAULT_DEPENDENCIES_LABEL, "#0366d6",
|
334
400
|
description: "Pull requests that update a dependency file"
|
335
401
|
)
|
336
402
|
@labels = [*@labels, DEFAULT_DEPENDENCIES_LABEL].uniq
|
337
403
|
end
|
338
404
|
|
405
|
+
sig { returns(T::Array[String]) }
|
339
406
|
def create_github_security_label
|
340
|
-
github_client_for_source.add_label(
|
407
|
+
T.unsafe(github_client_for_source).add_label(
|
341
408
|
source.repo, DEFAULT_SECURITY_LABEL, "ee0701",
|
342
409
|
description: "Pull requests that address a security vulnerability",
|
343
410
|
accept: "application/vnd.github.symmetra-preview+json"
|
@@ -349,18 +416,20 @@ module Dependabot
|
|
349
416
|
@labels = [*@labels, DEFAULT_SECURITY_LABEL].uniq
|
350
417
|
end
|
351
418
|
|
419
|
+
sig { returns(T.nilable(T::Array[String])) }
|
352
420
|
def create_gitlab_security_label
|
353
|
-
gitlab_client_for_source.create_label(
|
421
|
+
T.unsafe(gitlab_client_for_source).create_label(
|
354
422
|
source.repo, DEFAULT_SECURITY_LABEL, "#ee0701",
|
355
423
|
description: "Pull requests that address a security vulnerability"
|
356
424
|
)
|
357
425
|
@labels = [*@labels, DEFAULT_SECURITY_LABEL].uniq
|
358
426
|
end
|
359
427
|
|
428
|
+
sig { returns(T::Array[String]) }
|
360
429
|
def create_github_language_label
|
361
430
|
label = self.class.label_details_for_package_manager(package_manager)
|
362
431
|
language_name = label.fetch(:name)
|
363
|
-
github_client_for_source.add_label(
|
432
|
+
T.unsafe(github_client_for_source).add_label(
|
364
433
|
source.repo,
|
365
434
|
language_name,
|
366
435
|
label.fetch(:colour),
|
@@ -371,18 +440,20 @@ module Dependabot
|
|
371
440
|
rescue Octokit::UnprocessableEntity => e
|
372
441
|
raise unless e.errors.first.fetch(:code) == "already_exists"
|
373
442
|
|
374
|
-
@labels = [*@labels, language_name].uniq
|
443
|
+
@labels = [*@labels, language_name].uniq.compact
|
375
444
|
end
|
376
445
|
|
446
|
+
sig { params(language: String).returns(String) }
|
377
447
|
def default_description_for(language)
|
378
448
|
"Pull requests that update #{language.capitalize} code"
|
379
449
|
end
|
380
450
|
|
451
|
+
sig { returns(T::Array[String]) }
|
381
452
|
def create_gitlab_language_label
|
382
453
|
language_name =
|
383
454
|
self.class.label_details_for_package_manager(package_manager)
|
384
455
|
.fetch(:name)
|
385
|
-
gitlab_client_for_source.create_label(
|
456
|
+
T.unsafe(gitlab_client_for_source).create_label(
|
386
457
|
source.repo,
|
387
458
|
language_name,
|
388
459
|
"#" + self.class.label_details_for_package_manager(package_manager)
|
@@ -391,29 +462,38 @@ module Dependabot
|
|
391
462
|
@labels = [*@labels, language_name].uniq
|
392
463
|
end
|
393
464
|
|
465
|
+
sig { returns(Dependabot::Clients::GithubWithRetries) }
|
394
466
|
def github_client_for_source
|
395
|
-
@github_client_for_source ||=
|
467
|
+
@github_client_for_source ||= T.let(
|
396
468
|
Dependabot::Clients::GithubWithRetries.for_source(
|
397
469
|
source: source,
|
398
470
|
credentials: credentials
|
399
|
-
)
|
471
|
+
),
|
472
|
+
T.nilable(Dependabot::Clients::GithubWithRetries)
|
473
|
+
)
|
400
474
|
end
|
401
475
|
|
476
|
+
sig { returns(Dependabot::Clients::GitlabWithRetries) }
|
402
477
|
def gitlab_client_for_source
|
403
|
-
@gitlab_client_for_source ||=
|
478
|
+
@gitlab_client_for_source ||= T.let(
|
404
479
|
Dependabot::Clients::GitlabWithRetries.for_source(
|
405
480
|
source: source,
|
406
481
|
credentials: credentials
|
407
|
-
)
|
482
|
+
),
|
483
|
+
T.nilable(Dependabot::Clients::GitlabWithRetries)
|
484
|
+
)
|
408
485
|
end
|
409
486
|
|
487
|
+
sig { returns(String) }
|
410
488
|
def package_manager
|
411
|
-
@package_manager ||= dependencies.first.package_manager
|
489
|
+
@package_manager ||= T.let(T.must(dependencies.first).package_manager, T.nilable(String))
|
412
490
|
end
|
413
491
|
|
492
|
+
sig { returns(T.class_of(Dependabot::Version)) }
|
414
493
|
def version_class
|
415
494
|
Utils.version_class_for_package_manager(package_manager)
|
416
495
|
end
|
417
496
|
end
|
497
|
+
# rubocop:enable Metrics/ClassLength
|
418
498
|
end
|
419
499
|
end
|