dependabot-common 0.245.0 → 0.246.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbc9b9fbba7549f6bdbb7dafec2f3d3111bd2e8263e966b3eaf1bfce19be3a01
4
- data.tar.gz: 2e396338454b56410104329634792a20076533cadf2418f15e74d591612969eb
3
+ metadata.gz: afa14b1e2f804f1713004ae03cf9ba9ac2ed546794d736bbeedef24d18f8be7b
4
+ data.tar.gz: 012a72964c4ae5f6140ab6a81d101f227bd84445a2e04b77395252ae66771bc8
5
5
  SHA512:
6
- metadata.gz: 2cc3166e278f88f679a7d177b74d77ba9d8cd48ac22694db65a61a36bf5386efb7fd459e430f971cad2e21f33253e67f1e264137fcfc48b57d3d41480c71f9f9
7
- data.tar.gz: fc85175d8dfe6020bc3737fec46342fe529371e984d0f1d806195c697124ff6c63418edc7a1135a30c1c2ceff6caf28be2a715463c466c6bfa3267b5b0249b8a
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,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
@@ -1,42 +1,61 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "octokit"
5
+ require "sorbet-runtime"
6
+ require "dependabot/credential"
5
7
 
6
8
  module Dependabot
7
9
  module Clients
8
10
  class GithubWithRetries
11
+ extend T::Sig
12
+
9
13
  DEFAULT_OPEN_TIMEOUT_IN_SECONDS = 2
10
14
  DEFAULT_READ_TIMEOUT_IN_SECONDS = 5
11
15
 
16
+ sig { returns(Integer) }
12
17
  def self.open_timeout_in_seconds
13
18
  ENV.fetch("DEPENDABOT_OPEN_TIMEOUT_IN_SECONDS", DEFAULT_OPEN_TIMEOUT_IN_SECONDS).to_i
14
19
  end
15
20
 
21
+ sig { returns(Integer) }
16
22
  def self.read_timeout_in_seconds
17
23
  ENV.fetch("DEPENDABOT_READ_TIMEOUT_IN_SECONDS", DEFAULT_READ_TIMEOUT_IN_SECONDS).to_i
18
24
  end
19
25
 
20
- DEFAULT_CLIENT_ARGS = {
21
- connection_options: {
22
- request: {
23
- open_timeout: open_timeout_in_seconds,
24
- timeout: read_timeout_in_seconds
26
+ DEFAULT_CLIENT_ARGS = T.let(
27
+ {
28
+ connection_options: {
29
+ request: {
30
+ open_timeout: open_timeout_in_seconds,
31
+ timeout: read_timeout_in_seconds
32
+ }
25
33
  }
26
- }
27
- }.freeze
28
-
29
- RETRYABLE_ERRORS = [
30
- Faraday::ConnectionFailed,
31
- Faraday::TimeoutError,
32
- Octokit::InternalServerError,
33
- Octokit::BadGateway
34
- ].freeze
34
+ }.freeze,
35
+ T::Hash[Symbol, T.untyped]
36
+ )
37
+
38
+ RETRYABLE_ERRORS = T.let(
39
+ [
40
+ Faraday::ConnectionFailed,
41
+ Faraday::TimeoutError,
42
+ Octokit::InternalServerError,
43
+ Octokit::BadGateway
44
+ ].freeze,
45
+ T::Array[T.class_of(StandardError)]
46
+ )
35
47
 
36
48
  #######################
37
49
  # Constructor methods #
38
50
  #######################
39
51
 
52
+ sig do
53
+ params(
54
+ source: Dependabot::Source,
55
+ credentials: T::Array[Dependabot::Credential]
56
+ )
57
+ .returns(Dependabot::Clients::GithubWithRetries)
58
+ end
40
59
  def self.for_source(source:, credentials:)
41
60
  access_tokens =
42
61
  credentials
@@ -51,6 +70,7 @@ module Dependabot
51
70
  )
52
71
  end
53
72
 
73
+ sig { params(credentials: T::Array[Dependabot::Credential]).returns(Dependabot::Clients::GithubWithRetries) }
54
74
  def self.for_github_dot_com(credentials:)
55
75
  access_tokens =
56
76
  credentials
@@ -66,6 +86,7 @@ module Dependabot
66
86
  # VCS Interface #
67
87
  #################
68
88
 
89
+ sig { params(repo: String, branch: String).returns(String) }
69
90
  def fetch_commit(repo, branch)
70
91
  response = T.unsafe(self).ref(repo, "heads/#{branch}")
71
92
 
@@ -74,6 +95,7 @@ module Dependabot
74
95
  response.object.sha
75
96
  end
76
97
 
98
+ sig { params(repo: String).returns(String) }
77
99
  def fetch_default_branch(repo)
78
100
  T.unsafe(self).repository(repo).default_branch
79
101
  end
@@ -82,6 +104,7 @@ module Dependabot
82
104
  # Proxying #
83
105
  ############
84
106
 
107
+ sig { params(max_retries: T.nilable(Integer), args: T.untyped).void }
85
108
  def initialize(max_retries: 3, **args)
86
109
  args = DEFAULT_CLIENT_ARGS.merge(args)
87
110
 
@@ -106,11 +129,23 @@ module Dependabot
106
129
  end
107
130
  end
108
131
 
109
- @clients = access_tokens.map do |token|
110
- Octokit::Client.new(args.merge(access_token: token))
111
- end
132
+ @clients = T.let(
133
+ access_tokens.map do |token|
134
+ Octokit::Client.new(args.merge(access_token: token))
135
+ end,
136
+ T::Array[Octokit::Client]
137
+ )
112
138
  end
113
139
 
140
+ # TODO: Create all the methods that are called on the client
141
+ sig do
142
+ params(
143
+ method_name: T.any(Symbol, String),
144
+ args: T.untyped,
145
+ block: T.nilable(T.proc.returns(T.untyped))
146
+ )
147
+ .returns(T.untyped)
148
+ end
114
149
  def method_missing(method_name, *args, &block)
115
150
  untried_clients = @clients.dup
116
151
  client = untried_clients.pop
@@ -118,7 +153,7 @@ module Dependabot
118
153
  begin
119
154
  if client.respond_to?(method_name)
120
155
  mutatable_args = args.map(&:dup)
121
- client.public_send(method_name, *mutatable_args, &block)
156
+ T.unsafe(client).public_send(method_name, *mutatable_args, &block)
122
157
  else
123
158
  super
124
159
  end
@@ -129,6 +164,13 @@ module Dependabot
129
164
  end
130
165
  end
131
166
 
167
+ sig do
168
+ params(
169
+ method_name: Symbol,
170
+ include_private: T::Boolean
171
+ )
172
+ .returns(T::Boolean)
173
+ end
132
174
  def respond_to_missing?(method_name, include_private = false)
133
175
  @clients.first.respond_to?(method_name) || super
134
176
  end