dependabot-common 0.244.0 → 0.246.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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dependabot/clients/bitbucket.rb +113 -5
  3. data/lib/dependabot/clients/bitbucket_with_retries.rb +34 -10
  4. data/lib/dependabot/clients/codecommit.rb +107 -12
  5. data/lib/dependabot/clients/github_with_retries.rb +61 -19
  6. data/lib/dependabot/clients/gitlab_with_retries.rb +60 -7
  7. data/lib/dependabot/dependency.rb +1 -1
  8. data/lib/dependabot/errors.rb +8 -2
  9. data/lib/dependabot/git_commit_checker.rb +4 -3
  10. data/lib/dependabot/metadata_finders/base/changelog_finder.rb +1 -1
  11. data/lib/dependabot/metadata_finders/base/commits_finder.rb +1 -1
  12. data/lib/dependabot/metadata_finders/base/release_finder.rb +1 -1
  13. data/lib/dependabot/pull_request_creator/azure.rb +80 -9
  14. data/lib/dependabot/pull_request_creator/bitbucket.rb +73 -9
  15. data/lib/dependabot/pull_request_creator/codecommit.rb +96 -25
  16. data/lib/dependabot/pull_request_creator/github.rb +162 -49
  17. data/lib/dependabot/pull_request_creator/gitlab.rb +109 -21
  18. data/lib/dependabot/pull_request_creator/message_builder.rb +239 -89
  19. data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +11 -9
  20. data/lib/dependabot/pull_request_creator.rb +32 -27
  21. data/lib/dependabot/pull_request_updater/azure.rb +75 -11
  22. data/lib/dependabot/pull_request_updater/github.rb +89 -28
  23. data/lib/dependabot/pull_request_updater/gitlab.rb +61 -12
  24. data/lib/dependabot/pull_request_updater.rb +1 -1
  25. data/lib/dependabot/shared_helpers.rb +19 -1
  26. data/lib/dependabot/update_checkers/base.rb +121 -31
  27. data/lib/dependabot.rb +1 -1
  28. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7aa21cb81796cffb973cf4ff58644678588c40d9c6efc0cd81d514a3a894cbce
4
- data.tar.gz: b786777a6d7509b002bdef262c441197dad93a31767599885e2202b299040b2e
3
+ metadata.gz: afa14b1e2f804f1713004ae03cf9ba9ac2ed546794d736bbeedef24d18f8be7b
4
+ data.tar.gz: 012a72964c4ae5f6140ab6a81d101f227bd84445a2e04b77395252ae66771bc8
5
5
  SHA512:
6
- metadata.gz: 78eb059c3184e4329102ffb76b91339bb42ec740a97c622f4c1a67d5694c14fb0b44a40c08b6fba5e4712b0a83a9d745b099ec7685e8eb95f667a670625345a5
7
- data.tar.gz: 7c08bebb791070f134fbc4b40c3cff32431fb6342f02137e5803bb6f2439bfdf5f199f5b5b71e99d9398842da38b5f6c84eb5e0c61912f8212352052321da888
6
+ metadata.gz: 367510a477d1b7a1d362f69a8a4a8bdcfb1d89f355f442291d3640c247391e924612b51bbe3393b146dcfb621d1faf53ab7dc364bf4eba134c17389a781d4ba0
7
+ data.tar.gz: ae0d0af76bbea879c4cf4faec7c1be85067cec9918c1c7ad2818b60c160d5da93bcb11a5c3bd9287d4b9f11256de46eb0758f56db98ef2586ec2c3d4e514ed17
@@ -1,12 +1,16 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "dependabot/shared_helpers"
5
4
  require "excon"
5
+ require "sorbet-runtime"
6
+
7
+ require "dependabot/shared_helpers"
6
8
 
7
9
  module Dependabot
8
10
  module Clients
9
11
  class Bitbucket
12
+ extend T::Sig
13
+
10
14
  class NotFound < StandardError; end
11
15
 
12
16
  class Unauthorized < StandardError; end
@@ -19,6 +23,13 @@ module Dependabot
19
23
  # Constructor methods #
20
24
  #######################
21
25
 
26
+ sig do
27
+ params(
28
+ source: Dependabot::Source,
29
+ credentials: T::Array[Dependabot::Credential]
30
+ )
31
+ .returns(Dependabot::Clients::Bitbucket)
32
+ end
22
33
  def self.for_source(source:, credentials:)
23
34
  credential =
24
35
  credentials
@@ -32,11 +43,13 @@ module Dependabot
32
43
  # Client #
33
44
  ##########
34
45
 
46
+ sig { params(credentials: T.nilable(Dependabot::Credential)).void }
35
47
  def initialize(credentials:)
36
48
  @credentials = credentials
37
- @auth_header = auth_header_for(credentials&.fetch("token", nil))
49
+ @auth_header = T.let(auth_header_for(credentials&.fetch("token", nil)), T::Hash[String, String])
38
50
  end
39
51
 
52
+ sig { params(repo: String, branch: String).returns(String) }
40
53
  def fetch_commit(repo, branch)
41
54
  path = "#{repo}/refs/branches/#{branch}"
42
55
  response = get(base_url + path)
@@ -44,12 +57,21 @@ module Dependabot
44
57
  JSON.parse(response.body).fetch("target").fetch("hash")
45
58
  end
46
59
 
60
+ sig { params(repo: String).returns(String) }
47
61
  def fetch_default_branch(repo)
48
62
  response = get(base_url + repo)
49
63
 
50
64
  JSON.parse(response.body).fetch("mainbranch").fetch("name")
51
65
  end
52
66
 
67
+ sig do
68
+ params(
69
+ repo: String,
70
+ commit: T.nilable(String),
71
+ path: T.nilable(String)
72
+ )
73
+ .returns(T::Array[T::Hash[String, T.untyped]])
74
+ end
53
75
  def fetch_repo_contents(repo, commit = nil, path = nil)
54
76
  raise "Commit is required if path provided!" if commit.nil? && path
55
77
 
@@ -62,6 +84,14 @@ module Dependabot
62
84
  JSON.parse(response.body).fetch("values")
63
85
  end
64
86
 
87
+ sig do
88
+ params(
89
+ repo: String,
90
+ commit: String,
91
+ path: String
92
+ )
93
+ .returns(String)
94
+ end
65
95
  def fetch_file_contents(repo, commit, path)
66
96
  path = "#{repo}/src/#{commit}/#{path.gsub(%r{/+$}, '')}"
67
97
  response = get(base_url + path)
@@ -69,12 +99,26 @@ module Dependabot
69
99
  response.body
70
100
  end
71
101
 
102
+ sig do
103
+ params(
104
+ repo: String,
105
+ branch_name: T.nilable(String)
106
+ )
107
+ .returns(T::Enumerator[T::Hash[String, T.untyped]])
108
+ end
72
109
  def commits(repo, branch_name = nil)
73
110
  commits_path = "#{repo}/commits/#{branch_name}?pagelen=100"
74
111
  next_page_url = base_url + commits_path
75
112
  paginate({ "next" => next_page_url })
76
113
  end
77
114
 
115
+ sig do
116
+ params(
117
+ repo: String,
118
+ branch_name: String
119
+ )
120
+ .returns(T::Hash[String, T.untyped])
121
+ end
78
122
  def branch(repo, branch_name)
79
123
  branch_path = "#{repo}/refs/branches/#{branch_name}"
80
124
  response = get(base_url + branch_path)
@@ -82,6 +126,15 @@ module Dependabot
82
126
  JSON.parse(response.body)
83
127
  end
84
128
 
129
+ sig do
130
+ params(
131
+ repo: String,
132
+ source_branch: T.nilable(String),
133
+ target_branch: T.nilable(String),
134
+ status: T::Array[String]
135
+ )
136
+ .returns(T::Array[T::Hash[String, T.untyped]])
137
+ end
85
138
  def pull_requests(repo, source_branch, target_branch, status = %w(OPEN MERGED DECLINED SUPERSEDED))
86
139
  pr_path = "#{repo}/pullrequests?"
87
140
  # Get pull requests with given status
@@ -104,6 +157,17 @@ module Dependabot
104
157
  end
105
158
 
106
159
  # rubocop:disable Metrics/ParameterLists
160
+ sig do
161
+ params(
162
+ repo: String,
163
+ branch_name: String,
164
+ base_commit: String,
165
+ commit_message: String,
166
+ files: T::Array[Dependabot::DependencyFile],
167
+ author_details: T::Hash[Symbol, String]
168
+ )
169
+ .void
170
+ end
107
171
  def create_commit(repo, branch_name, base_commit, commit_message, files,
108
172
  author_details)
109
173
  parameters = {
@@ -125,6 +189,18 @@ module Dependabot
125
189
  # rubocop:enable Metrics/ParameterLists
126
190
 
127
191
  # rubocop:disable Metrics/ParameterLists
192
+ sig do
193
+ params(
194
+ repo: String,
195
+ pr_name: String,
196
+ source_branch: String,
197
+ target_branch: String,
198
+ pr_description: String,
199
+ _labels: T.nilable(T::Array[String]),
200
+ _work_item: T.nilable(Integer)
201
+ )
202
+ .void
203
+ end
128
204
  def create_pull_request(repo, pr_name, source_branch, target_branch,
129
205
  pr_description, _labels, _work_item = nil)
130
206
  reviewers = default_reviewers(repo)
@@ -151,6 +227,7 @@ module Dependabot
151
227
  end
152
228
  # rubocop:enable Metrics/ParameterLists
153
229
 
230
+ sig { params(repo: String, pr_id: Integer, comment: T.nilable(String)).void }
154
231
  def decline_pull_request(repo, pr_id, comment = nil)
155
232
  # https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pullrequests/
156
233
  decline_path = "#{repo}/pullrequests/#{pr_id}/decline"
@@ -168,14 +245,16 @@ module Dependabot
168
245
  post(base_url + comment_path, content.to_json)
169
246
  end
170
247
 
248
+ sig { returns(T.nilable(String)) }
171
249
  def current_user
172
250
  base_url = "https://api.bitbucket.org/2.0/user?fields=uuid"
173
251
  response = get(base_url)
174
252
  JSON.parse(response.body).fetch("uuid")
175
253
  rescue Unauthorized
176
- [nil]
254
+ nil
177
255
  end
178
256
 
257
+ sig { params(repo: String).returns(T::Array[T::Hash[String, String]]) }
179
258
  def default_reviewers(repo)
180
259
  current_uuid = current_user
181
260
  path = "#{repo}/default-reviewers?pagelen=100&fields=values.uuid,next"
@@ -192,6 +271,7 @@ module Dependabot
192
271
  reviewer_data
193
272
  end
194
273
 
274
+ sig { params(repo: String).returns(T::Array[T::Hash[String, String]]) }
195
275
  def tags(repo)
196
276
  path = "#{repo}/refs/tags?pagelen=100"
197
277
  response = get(base_url + path)
@@ -199,6 +279,14 @@ module Dependabot
199
279
  JSON.parse(response.body).fetch("values")
200
280
  end
201
281
 
282
+ sig do
283
+ params(
284
+ repo: String,
285
+ previous_tag: String,
286
+ new_tag: String
287
+ )
288
+ .returns(T::Array[T::Hash[String, T.untyped]])
289
+ end
202
290
  def compare(repo, previous_tag, new_tag)
203
291
  path = "#{repo}/commits/?include=#{new_tag}&exclude=#{previous_tag}"
204
292
  response = get(base_url + path)
@@ -206,6 +294,7 @@ module Dependabot
206
294
  JSON.parse(response.body).fetch("values")
207
295
  end
208
296
 
297
+ sig { params(url: String).returns(Excon::Response) }
209
298
  def get(url)
210
299
  response = Excon.get(
211
300
  URI::DEFAULT_PARSER.escape(url),
@@ -230,6 +319,14 @@ module Dependabot
230
319
  response
231
320
  end
232
321
 
322
+ sig do
323
+ params(
324
+ url: String,
325
+ body: String,
326
+ content_type: String
327
+ )
328
+ .returns(Excon::Response)
329
+ end
233
330
  def post(url, body, content_type = "application/json")
234
331
  headers = auth_header
235
332
 
@@ -259,12 +356,14 @@ module Dependabot
259
356
 
260
357
  private
261
358
 
359
+ sig { params(token: T.nilable(String)).returns(T::Hash[String, String]) }
262
360
  def auth_header_for(token)
263
361
  return {} unless token
264
362
 
265
363
  { "Authorization" => "Bearer #{token}" }
266
364
  end
267
365
 
366
+ sig { params(parameters: T::Hash[String, String]).returns(String) }
268
367
  def encode_form_parameters(parameters)
269
368
  parameters.map do |key, value|
270
369
  URI.encode_www_form_component(key.to_s) + "=" + URI.encode_www_form_component(value.to_s)
@@ -284,6 +383,11 @@ module Dependabot
284
383
  # response = post(url, body)
285
384
  # first_page = JSON.parse(response.body)
286
385
  # paginate(first_page)
386
+ sig do
387
+ type_parameters(:T)
388
+ .params(page: T.all(T.type_parameter(:T), T::Hash[String, T.untyped]))
389
+ .returns(T::Enumerator[T.type_parameter(:T)])
390
+ end
287
391
  def paginate(page)
288
392
  Enumerator.new do |yielder|
289
393
  loop do
@@ -291,14 +395,18 @@ module Dependabot
291
395
  break unless page.key?("next")
292
396
 
293
397
  next_page_url = page.fetch("next")
294
- page = JSON.parse(get(next_page_url).body)
398
+ page = T.cast(JSON.parse(get(next_page_url).body), T.all(T::Hash[String, T.untyped], T.type_parameter(:T)))
295
399
  end
296
400
  end
297
401
  end
298
402
 
403
+ sig { returns(T::Hash[String, String]) }
299
404
  attr_reader :auth_header
405
+
406
+ sig { returns(T.nilable(Dependabot::Credential)) }
300
407
  attr_reader :credentials
301
408
 
409
+ sig { returns(String) }
302
410
  def base_url
303
411
  # TODO: Make this configurable when we support enterprise Bitbucket
304
412
  "https://api.bitbucket.org/2.0/repositories/"
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require_relative "bitbucket"
@@ -6,15 +6,18 @@ require_relative "bitbucket"
6
6
  module Dependabot
7
7
  module Clients
8
8
  class BitbucketWithRetries
9
- RETRYABLE_ERRORS = [
10
- Excon::Error::Timeout,
11
- Excon::Error::Socket
12
- ].freeze
9
+ extend T::Sig
10
+
11
+ RETRYABLE_ERRORS = T.let(
12
+ [Excon::Error::Timeout, Excon::Error::Socket].freeze,
13
+ T::Array[T.class_of(Excon::Error)]
14
+ )
13
15
 
14
16
  #######################
15
17
  # Constructor methods #
16
18
  #######################
17
19
 
20
+ sig { params(credentials: T::Array[Dependabot::Credential]).returns(BitbucketWithRetries) }
18
21
  def self.for_bitbucket_dot_org(credentials:)
19
22
  credential =
20
23
  credentials
@@ -28,27 +31,48 @@ module Dependabot
28
31
  # Proxying #
29
32
  ############
30
33
 
31
- def initialize(max_retries: 3, **args)
32
- @max_retries = max_retries || 3
33
- @client = Bitbucket.new(**T.unsafe(args))
34
+ sig { params(credentials: T.nilable(Dependabot::Credential), max_retries: T.nilable(Integer)).void }
35
+ def initialize(credentials:, max_retries: 3)
36
+ @max_retries = T.let(max_retries || 3, Integer)
37
+ @client = T.let(Bitbucket.new(credentials: credentials), Dependabot::Clients::Bitbucket)
34
38
  end
35
39
 
40
+ sig do
41
+ params(
42
+ method_name: T.any(Symbol, String),
43
+ args: T.untyped,
44
+ block: T.nilable(T.proc.returns(T.untyped))
45
+ )
46
+ .returns(T.untyped)
47
+ end
36
48
  def method_missing(method_name, *args, &block)
37
49
  retry_connection_failures do
38
50
  if @client.respond_to?(method_name)
39
51
  mutatable_args = args.map(&:dup)
40
- @client.public_send(method_name, *mutatable_args, &block)
52
+ T.unsafe(@client).public_send(method_name, *mutatable_args, &block)
41
53
  else
42
54
  super
43
55
  end
44
56
  end
45
57
  end
46
58
 
59
+ sig do
60
+ params(
61
+ method_name: Symbol,
62
+ include_private: T::Boolean
63
+ )
64
+ .returns(T::Boolean)
65
+ end
47
66
  def respond_to_missing?(method_name, include_private = false)
48
67
  @client.respond_to?(method_name) || super
49
68
  end
50
69
 
51
- def retry_connection_failures
70
+ sig do
71
+ type_parameters(:T)
72
+ .params(_blk: T.proc.returns(T.type_parameter(:T)))
73
+ .returns(T.type_parameter(:T))
74
+ end
75
+ def retry_connection_failures(&_blk)
52
76
  retry_attempt = 0
53
77
 
54
78
  begin
@@ -1,7 +1,9 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "aws-sdk-codecommit"
5
+ require "sorbet-runtime"
6
+
5
7
  require "dependabot/shared_helpers"
6
8
 
7
9
  module Dependabot
@@ -15,6 +17,13 @@ module Dependabot
15
17
  # Constructor methods #
16
18
  #######################
17
19
 
20
+ sig do
21
+ params(
22
+ source: Dependabot::Source,
23
+ credentials: T::Array[Dependabot::Credential]
24
+ )
25
+ .returns(Dependabot::Clients::CodeCommit)
26
+ end
18
27
  def self.for_source(source:, credentials:)
19
28
  credential =
20
29
  credentials
@@ -28,20 +37,32 @@ module Dependabot
28
37
  # Client #
29
38
  ##########
30
39
 
40
+ sig do
41
+ params(
42
+ source: Dependabot::Source,
43
+ credentials: T.nilable(Dependabot::Credential)
44
+ )
45
+ .void
46
+ end
31
47
  def initialize(source, credentials)
32
48
  @source = source
33
49
  @cc_client =
34
- if credentials
35
- Aws::CodeCommit::Client.new(
36
- access_key_id: credentials.fetch("username"),
37
- secret_access_key: credentials.fetch("password"),
38
- region: credentials.fetch("region")
39
- )
40
- else
41
- Aws::CodeCommit::Client.new
42
- end
50
+ T.let(
51
+ if credentials
52
+ Aws::CodeCommit::Client.new(
53
+ access_key_id: credentials.fetch("username"),
54
+ secret_access_key: credentials.fetch("password"),
55
+ region: credentials.fetch("region")
56
+ )
57
+ else
58
+ Aws::CodeCommit::Client.new
59
+ end,
60
+ Aws::CodeCommit::Client
61
+ )
43
62
  end
44
63
 
64
+ # TODO: Should repo be required?
65
+ sig { params(repo: T.nilable(String), branch: String).returns(String) }
45
66
  def fetch_commit(repo, branch)
46
67
  cc_client.get_branch(
47
68
  branch_name: branch,
@@ -49,12 +70,20 @@ module Dependabot
49
70
  ).branch.commit_id
50
71
  end
51
72
 
73
+ sig { params(repo: String).returns(String) }
52
74
  def fetch_default_branch(repo)
53
75
  cc_client.get_repository(
54
76
  repository_name: repo
55
77
  ).repository_metadata.default_branch
56
78
  end
57
79
 
80
+ sig do
81
+ params(
82
+ repo: String, commit: T.nilable(String),
83
+ path: T.nilable(String)
84
+ )
85
+ .returns(Aws::CodeCommit::Types::GetFolderOutput)
86
+ end
58
87
  def fetch_repo_contents(repo, commit = nil, path = nil)
59
88
  actual_path = path
60
89
  actual_path = "/" if path.to_s.empty?
@@ -66,6 +95,14 @@ module Dependabot
66
95
  )
67
96
  end
68
97
 
98
+ sig do
99
+ params(
100
+ repo: String,
101
+ commit: String,
102
+ path: String
103
+ )
104
+ .returns(String)
105
+ end
69
106
  def fetch_file_contents(repo, commit, path)
70
107
  cc_client.get_file(
71
108
  repository_name: repo,
@@ -76,6 +113,12 @@ module Dependabot
76
113
  raise NotFound
77
114
  end
78
115
 
116
+ sig do
117
+ params(
118
+ branch_name: String
119
+ )
120
+ .returns(String)
121
+ end
79
122
  def branch(branch_name)
80
123
  cc_client.get_branch(
81
124
  repository_name: source.unscoped_repo,
@@ -84,6 +127,14 @@ module Dependabot
84
127
  end
85
128
 
86
129
  # work around b/c codecommit doesn't have a 'get all commits' api..
130
+ sig do
131
+ params(
132
+ repo: String,
133
+ branch_name: String,
134
+ result_count: Integer
135
+ )
136
+ .returns(T::Array[String])
137
+ end
87
138
  def fetch_commits(repo, branch_name, result_count)
88
139
  top_commit = fetch_commit(repo, branch_name)
89
140
  retrieved_commits = []
@@ -123,7 +174,14 @@ module Dependabot
123
174
  result
124
175
  end
125
176
 
126
- def commits(repo, branch_name = source.branch)
177
+ sig do
178
+ params(
179
+ repo: String,
180
+ branch_name: String
181
+ )
182
+ .returns(Aws::CodeCommit::Types::Commit)
183
+ end
184
+ def commits(repo, branch_name = T.must(source.branch))
127
185
  retrieved_commits = fetch_commits(repo, branch_name, 5)
128
186
 
129
187
  result = @cc_client.batch_get_commits(
@@ -136,6 +194,14 @@ module Dependabot
136
194
  result
137
195
  end
138
196
 
197
+ sig do
198
+ params(
199
+ repo: String,
200
+ state: String,
201
+ branch: String
202
+ )
203
+ .returns(T::Array[Aws::CodeCommit::Types::PullRequest])
204
+ end
139
205
  def pull_requests(repo, state, branch)
140
206
  pull_request_ids = @cc_client.list_pull_requests(
141
207
  repository_name: repo,
@@ -158,6 +224,14 @@ module Dependabot
158
224
  result
159
225
  end
160
226
 
227
+ sig do
228
+ params(
229
+ repo: String,
230
+ branch_name: String,
231
+ commit_id: String
232
+ )
233
+ .returns(Aws::CodeCommit::Types::BranchInfo)
234
+ end
161
235
  def create_branch(repo, branch_name, commit_id)
162
236
  cc_client.create_branch(
163
237
  repository_name: repo,
@@ -166,6 +240,16 @@ module Dependabot
166
240
  )
167
241
  end
168
242
 
243
+ sig do
244
+ params(
245
+ branch_name: String,
246
+ author_name: String,
247
+ base_commit: String,
248
+ commit_message: String,
249
+ files: T::Array[Dependabot::DependencyFile]
250
+ )
251
+ .returns(Aws::CodeCommit::Types::CreateCommitOutput)
252
+ end
169
253
  def create_commit(branch_name, author_name, base_commit, commit_message,
170
254
  files)
171
255
  cc_client.create_commit(
@@ -184,6 +268,15 @@ module Dependabot
184
268
  )
185
269
  end
186
270
 
271
+ sig do
272
+ params(
273
+ pr_name: String,
274
+ target_branch: String,
275
+ source_branch: String,
276
+ pr_description: String
277
+ )
278
+ .returns(T.nilable(Aws::CodeCommit::Types::CreatePullRequestOutput))
279
+ end
187
280
  def create_pull_request(pr_name, target_branch, source_branch,
188
281
  pr_description)
189
282
  cc_client.create_pull_request(
@@ -199,8 +292,10 @@ module Dependabot
199
292
 
200
293
  private
201
294
 
202
- attr_reader :credentials
295
+ sig { returns(Dependabot::Source) }
203
296
  attr_reader :source
297
+
298
+ sig { returns(Aws::CodeCommit::Client) }
204
299
  attr_reader :cc_client
205
300
  end
206
301
  end