dependabot-common 0.244.0 → 0.246.0

Sign up to get free protection for your applications and to get access to all the features.
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