dependabot-common 0.245.0 → 0.247.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/clients/bitbucket.rb +113 -5
- data/lib/dependabot/clients/codecommit.rb +107 -12
- data/lib/dependabot/clients/github_with_retries.rb +61 -19
- data/lib/dependabot/clients/gitlab_with_retries.rb +60 -7
- data/lib/dependabot/dependency.rb +1 -1
- data/lib/dependabot/errors.rb +20 -2
- data/lib/dependabot/file_fetchers/base.rb +8 -19
- data/lib/dependabot/file_updaters/base.rb +2 -0
- data/lib/dependabot/git_commit_checker.rb +3 -2
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +1 -1
- data/lib/dependabot/metadata_finders/base/commits_finder.rb +1 -1
- data/lib/dependabot/metadata_finders/base/release_finder.rb +1 -1
- data/lib/dependabot/pull_request_creator/azure.rb +80 -9
- data/lib/dependabot/pull_request_creator/bitbucket.rb +73 -9
- data/lib/dependabot/pull_request_creator/branch_namer/solo_strategy.rb +1 -1
- data/lib/dependabot/pull_request_creator/codecommit.rb +96 -25
- data/lib/dependabot/pull_request_creator/github.rb +162 -49
- data/lib/dependabot/pull_request_creator/gitlab.rb +109 -21
- data/lib/dependabot/pull_request_creator/message_builder/issue_linker.rb +13 -4
- data/lib/dependabot/pull_request_creator/message_builder.rb +246 -89
- data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +11 -9
- data/lib/dependabot/pull_request_creator.rb +32 -27
- data/lib/dependabot/pull_request_updater/azure.rb +75 -11
- data/lib/dependabot/pull_request_updater/github.rb +89 -28
- data/lib/dependabot/pull_request_updater/gitlab.rb +61 -12
- data/lib/dependabot/pull_request_updater.rb +1 -1
- data/lib/dependabot/registry_client.rb +2 -2
- data/lib/dependabot/requirements_update_strategy.rb +13 -0
- data/lib/dependabot/update_checkers/base.rb +123 -32
- data/lib/dependabot/update_checkers/version_filters.rb +15 -5
- data/lib/dependabot/version.rb +6 -43
- data/lib/dependabot.rb +1 -1
- metadata +18 -3
@@ -1,12 +1,20 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "gitlab"
|
5
|
+
require "sorbet-runtime"
|
6
|
+
|
7
|
+
require "dependabot/credential"
|
5
8
|
|
6
9
|
module Dependabot
|
7
10
|
module Clients
|
8
11
|
class GitlabWithRetries
|
9
|
-
|
12
|
+
extend T::Sig
|
13
|
+
|
14
|
+
RETRYABLE_ERRORS = T.let(
|
15
|
+
[Gitlab::Error::BadGateway].freeze,
|
16
|
+
T::Array[T.class_of(Gitlab::Error::ResponseError)]
|
17
|
+
)
|
10
18
|
|
11
19
|
class ContentEncoding
|
12
20
|
BASE64 = "base64"
|
@@ -17,6 +25,13 @@ module Dependabot
|
|
17
25
|
# Constructor methods #
|
18
26
|
#######################
|
19
27
|
|
28
|
+
sig do
|
29
|
+
params(
|
30
|
+
source: Dependabot::Source,
|
31
|
+
credentials: T::Array[Dependabot::Credential]
|
32
|
+
)
|
33
|
+
.returns(Dependabot::Clients::GitlabWithRetries)
|
34
|
+
end
|
20
35
|
def self.for_source(source:, credentials:)
|
21
36
|
access_token =
|
22
37
|
credentials
|
@@ -31,6 +46,7 @@ module Dependabot
|
|
31
46
|
)
|
32
47
|
end
|
33
48
|
|
49
|
+
sig { params(credentials: T::Array[Dependabot::Credential]).returns(Dependabot::Clients::GitlabWithRetries) }
|
34
50
|
def self.for_gitlab_dot_com(credentials:)
|
35
51
|
access_token =
|
36
52
|
credentials
|
@@ -49,10 +65,12 @@ module Dependabot
|
|
49
65
|
# VCS Interface #
|
50
66
|
#################
|
51
67
|
|
68
|
+
sig { params(repo: String, branch: String).returns(String) }
|
52
69
|
def fetch_commit(repo, branch)
|
53
70
|
T.unsafe(self).branch(repo, branch).commit.id
|
54
71
|
end
|
55
72
|
|
73
|
+
sig { params(repo: String).returns(String) }
|
56
74
|
def fetch_default_branch(repo)
|
57
75
|
T.unsafe(self).project(repo).default_branch
|
58
76
|
end
|
@@ -61,9 +79,10 @@ module Dependabot
|
|
61
79
|
# Proxying #
|
62
80
|
############
|
63
81
|
|
82
|
+
sig { params(max_retries: T.nilable(Integer), args: T.untyped).void }
|
64
83
|
def initialize(max_retries: 3, **args)
|
65
|
-
@max_retries = max_retries || 3
|
66
|
-
@client = ::Gitlab::Client.new(args)
|
84
|
+
@max_retries = T.let(max_retries || 3, Integer)
|
85
|
+
@client = T.let(::Gitlab::Client.new(args), ::Gitlab::Client)
|
67
86
|
end
|
68
87
|
|
69
88
|
# Create commit in gitlab repo with correctly mapped file actions
|
@@ -74,32 +93,63 @@ module Dependabot
|
|
74
93
|
# @param [Array<Dependabot::DependencyFile>] files
|
75
94
|
# @param [Hash] options
|
76
95
|
# @return [Gitlab::ObjectifiedHash]
|
96
|
+
sig do
|
97
|
+
params(
|
98
|
+
repo: String,
|
99
|
+
branch_name: String,
|
100
|
+
commit_message: String,
|
101
|
+
files: T::Array[Dependabot::DependencyFile],
|
102
|
+
options: T.untyped
|
103
|
+
)
|
104
|
+
.returns(Gitlab::ObjectifiedHash)
|
105
|
+
end
|
77
106
|
def create_commit(repo, branch_name, commit_message, files, **options)
|
78
107
|
@client.create_commit(
|
79
108
|
repo,
|
80
109
|
branch_name,
|
81
110
|
commit_message,
|
82
111
|
file_actions(files),
|
83
|
-
|
112
|
+
options
|
84
113
|
)
|
85
114
|
end
|
86
115
|
|
116
|
+
# TODO: Create all the methods that are called on the client
|
117
|
+
sig do
|
118
|
+
params(
|
119
|
+
method_name: T.any(Symbol, String),
|
120
|
+
args: T.untyped,
|
121
|
+
block: T.nilable(T.proc.returns(T.untyped))
|
122
|
+
)
|
123
|
+
.returns(T.untyped)
|
124
|
+
end
|
87
125
|
def method_missing(method_name, *args, &block)
|
88
126
|
retry_connection_failures do
|
89
127
|
if @client.respond_to?(method_name)
|
90
128
|
mutatable_args = args.map(&:dup)
|
91
|
-
@client.public_send(method_name, *mutatable_args, &block)
|
129
|
+
T.unsafe(@client).public_send(method_name, *mutatable_args, &block)
|
92
130
|
else
|
93
131
|
super
|
94
132
|
end
|
95
133
|
end
|
96
134
|
end
|
97
135
|
|
136
|
+
sig do
|
137
|
+
params(
|
138
|
+
method_name: Symbol,
|
139
|
+
include_private: T::Boolean
|
140
|
+
)
|
141
|
+
.returns(T::Boolean)
|
142
|
+
end
|
98
143
|
def respond_to_missing?(method_name, include_private = false)
|
99
144
|
@client.respond_to?(method_name) || super
|
100
145
|
end
|
101
146
|
|
102
|
-
|
147
|
+
sig do
|
148
|
+
type_parameters(:T)
|
149
|
+
.params(_blk: T.proc.returns(T.type_parameter(:T)))
|
150
|
+
.returns(T.type_parameter(:T))
|
151
|
+
end
|
152
|
+
def retry_connection_failures(&_blk)
|
103
153
|
retry_attempt = 0
|
104
154
|
|
105
155
|
begin
|
@@ -116,6 +166,7 @@ module Dependabot
|
|
116
166
|
#
|
117
167
|
# @param [Array<Dependabot::DependencyFile>] files
|
118
168
|
# @return [Array<Hash>]
|
169
|
+
sig { params(files: T::Array[Dependabot::DependencyFile]).returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
119
170
|
def file_actions(files)
|
120
171
|
files.map do |file|
|
121
172
|
{
|
@@ -131,6 +182,7 @@ module Dependabot
|
|
131
182
|
#
|
132
183
|
# @param [Dependabot::DependencyFile] file
|
133
184
|
# @return [String]
|
185
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
134
186
|
def file_action(file)
|
135
187
|
if file.operation == Dependabot::DependencyFile::Operation::DELETE
|
136
188
|
"delete"
|
@@ -145,6 +197,7 @@ module Dependabot
|
|
145
197
|
#
|
146
198
|
# @param [Dependabot::DependencyFile] file
|
147
199
|
# @return [String]
|
200
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
148
201
|
def file_encoding(file)
|
149
202
|
return ContentEncoding::BASE64 if file.content_encoding == Dependabot::DependencyFile::ContentEncoding::BASE64
|
150
203
|
|
@@ -93,7 +93,7 @@ module Dependabot
|
|
93
93
|
# TODO: Make version a Dependabot::Version everywhere
|
94
94
|
version: T.nilable(T.any(String, Dependabot::Version)),
|
95
95
|
previous_version: T.nilable(String),
|
96
|
-
previous_requirements: T.nilable(T::Array[T::Hash[String,
|
96
|
+
previous_requirements: T.nilable(T::Array[T::Hash[T.any(Symbol, String), T.untyped]]),
|
97
97
|
subdependency_metadata: T.nilable(T::Array[T::Hash[T.any(Symbol, String), String]]),
|
98
98
|
removed: T::Boolean,
|
99
99
|
metadata: T.nilable(T::Hash[T.any(Symbol, String), String])
|
data/lib/dependabot/errors.rb
CHANGED
@@ -7,6 +7,18 @@ require "dependabot/utils"
|
|
7
7
|
module Dependabot
|
8
8
|
extend T::Sig
|
9
9
|
|
10
|
+
module ErrorAttributes
|
11
|
+
BACKTRACE = "error-backtrace"
|
12
|
+
CLASS = "error-class"
|
13
|
+
DETAILS = "error-details"
|
14
|
+
FINGERPRINT = "fingerprint"
|
15
|
+
MESSAGE = "error-message"
|
16
|
+
DEPENDENCIES = "job-dependencies"
|
17
|
+
DEPENDENCY_GROUPS = "job-dependency-groups"
|
18
|
+
JOB_ID = "job-id"
|
19
|
+
PACKAGE_MANAGER = "package-manager"
|
20
|
+
end
|
21
|
+
|
10
22
|
# rubocop:disable Metrics/MethodLength
|
11
23
|
sig { params(error: StandardError).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
12
24
|
def self.fetcher_error_details(error)
|
@@ -48,7 +60,10 @@ module Dependabot
|
|
48
60
|
when Dependabot::DependencyFileNotFound
|
49
61
|
{
|
50
62
|
"error-type": "dependency_file_not_found",
|
51
|
-
"error-detail": {
|
63
|
+
"error-detail": {
|
64
|
+
message: error.message,
|
65
|
+
"file-path": error.file_path
|
66
|
+
}
|
52
67
|
}
|
53
68
|
when Dependabot::OutOfDisk
|
54
69
|
{
|
@@ -108,7 +123,10 @@ module Dependabot
|
|
108
123
|
when Dependabot::DependencyFileNotFound
|
109
124
|
{
|
110
125
|
"error-type": "dependency_file_not_found",
|
111
|
-
"error-detail": {
|
126
|
+
"error-detail": {
|
127
|
+
message: error.message,
|
128
|
+
"file-path": error.file_path
|
129
|
+
}
|
112
130
|
}
|
113
131
|
when Dependabot::PathDependenciesNotReachable
|
114
132
|
{
|
@@ -354,11 +354,6 @@ module Dependabot
|
|
354
354
|
end
|
355
355
|
end
|
356
356
|
|
357
|
-
sig { returns(T::Boolean) }
|
358
|
-
def recurse_submodules_when_cloning?
|
359
|
-
false
|
360
|
-
end
|
361
|
-
|
362
357
|
sig do
|
363
358
|
returns(
|
364
359
|
T.any(
|
@@ -776,7 +771,6 @@ module Dependabot
|
|
776
771
|
# rubocop:disable Metrics/MethodLength
|
777
772
|
# rubocop:disable Metrics/PerceivedComplexity
|
778
773
|
# rubocop:disable Metrics/BlockLength
|
779
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
780
774
|
sig { params(target_directory: T.nilable(String)).returns(String) }
|
781
775
|
def _clone_repo_contents(target_directory:)
|
782
776
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
@@ -789,11 +783,7 @@ module Dependabot
|
|
789
783
|
|
790
784
|
clone_options = StringIO.new
|
791
785
|
clone_options << "--no-tags --depth 1"
|
792
|
-
clone_options <<
|
793
|
-
" --recurse-submodules --shallow-submodules"
|
794
|
-
else
|
795
|
-
" --no-recurse-submodules"
|
796
|
-
end
|
786
|
+
clone_options << " --recurse-submodules --shallow-submodules"
|
797
787
|
clone_options << " --branch #{source.branch} --single-branch" if source.branch
|
798
788
|
|
799
789
|
submodule_cloning_failed = false
|
@@ -805,7 +795,7 @@ module Dependabot
|
|
805
795
|
CMD
|
806
796
|
)
|
807
797
|
|
808
|
-
@submodules = find_submodules(path)
|
798
|
+
@submodules = find_submodules(path)
|
809
799
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
810
800
|
if GIT_RETRYABLE_ERRORS.any? { |error| error.match?(e.message) } && retries < 5
|
811
801
|
retries += 1
|
@@ -835,20 +825,20 @@ module Dependabot
|
|
835
825
|
Dir.chdir(path) do
|
836
826
|
fetch_options = StringIO.new
|
837
827
|
fetch_options << "--depth 1"
|
838
|
-
fetch_options << if
|
839
|
-
" --recurse-submodules=on-demand"
|
840
|
-
else
|
828
|
+
fetch_options << if submodule_cloning_failed
|
841
829
|
" --no-recurse-submodules"
|
830
|
+
else
|
831
|
+
" --recurse-submodules=on-demand"
|
842
832
|
end
|
843
833
|
# Need to fetch the commit due to the --depth 1 above.
|
844
834
|
SharedHelpers.run_shell_command("git fetch #{fetch_options.string} origin #{source.commit}")
|
845
835
|
|
846
836
|
reset_options = StringIO.new
|
847
837
|
reset_options << "--hard"
|
848
|
-
reset_options << if
|
849
|
-
" --recurse-submodules"
|
850
|
-
else
|
838
|
+
reset_options << if submodule_cloning_failed
|
851
839
|
" --no-recurse-submodules"
|
840
|
+
else
|
841
|
+
" --recurse-submodules"
|
852
842
|
end
|
853
843
|
# Set HEAD to this commit so later calls so git reset HEAD will work.
|
854
844
|
SharedHelpers.run_shell_command("git reset #{reset_options.string} #{source.commit}")
|
@@ -862,7 +852,6 @@ module Dependabot
|
|
862
852
|
# rubocop:enable Metrics/MethodLength
|
863
853
|
# rubocop:enable Metrics/PerceivedComplexity
|
864
854
|
# rubocop:enable Metrics/BlockLength
|
865
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
866
855
|
|
867
856
|
sig { params(str: String).returns(String) }
|
868
857
|
def decode_binary_string(str)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
5
|
+
|
5
6
|
require "dependabot/credential"
|
6
7
|
|
7
8
|
module Dependabot
|
@@ -9,6 +10,7 @@ module Dependabot
|
|
9
10
|
class Base
|
10
11
|
extend T::Sig
|
11
12
|
extend T::Helpers
|
13
|
+
|
12
14
|
abstract!
|
13
15
|
|
14
16
|
sig { returns(T::Array[Dependabot::Dependency]) }
|
@@ -367,7 +367,8 @@ module Dependabot
|
|
367
367
|
client = Clients::GithubWithRetries
|
368
368
|
.for_github_dot_com(credentials: credentials)
|
369
369
|
|
370
|
-
|
370
|
+
# TODO: create this method instead of relying on method_missing
|
371
|
+
T.unsafe(client).compare(listing_source_repo, ref1, ref2).status
|
371
372
|
end
|
372
373
|
|
373
374
|
sig { params(ref1: String, ref2: String).returns(String) }
|
@@ -375,7 +376,7 @@ module Dependabot
|
|
375
376
|
client = Clients::GitlabWithRetries
|
376
377
|
.for_gitlab_dot_com(credentials: credentials)
|
377
378
|
|
378
|
-
comparison = client.compare(listing_source_repo, ref1, ref2)
|
379
|
+
comparison = T.unsafe(client).compare(listing_source_repo, ref1, ref2)
|
379
380
|
|
380
381
|
if comparison.commits.none? then "behind"
|
381
382
|
elsif comparison.compare_same_ref then "identical"
|
@@ -460,7 +460,7 @@ module Dependabot
|
|
460
460
|
def github_client
|
461
461
|
@github_client ||=
|
462
462
|
T.let(
|
463
|
-
Dependabot::Clients::GithubWithRetries.for_source(source: source, credentials: credentials),
|
463
|
+
Dependabot::Clients::GithubWithRetries.for_source(source: T.must(source), credentials: credentials),
|
464
464
|
T.nilable(Dependabot::Clients::GithubWithRetries)
|
465
465
|
)
|
466
466
|
end
|
@@ -373,7 +373,7 @@ module Dependabot
|
|
373
373
|
def github_client
|
374
374
|
@github_client ||=
|
375
375
|
T.let(
|
376
|
-
Dependabot::Clients::GithubWithRetries.for_source(source: source, credentials: credentials),
|
376
|
+
Dependabot::Clients::GithubWithRetries.for_source(source: T.must(source), credentials: credentials),
|
377
377
|
T.nilable(Dependabot::Clients::GithubWithRetries)
|
378
378
|
)
|
379
379
|
end
|
@@ -359,7 +359,7 @@ module Dependabot
|
|
359
359
|
def github_client
|
360
360
|
@github_client ||=
|
361
361
|
T.let(
|
362
|
-
Dependabot::Clients::GithubWithRetries.for_source(source: source, credentials: credentials),
|
362
|
+
Dependabot::Clients::GithubWithRetries.for_source(source: T.must(source), credentials: credentials),
|
363
363
|
T.nilable(Dependabot::Clients::GithubWithRetries)
|
364
364
|
)
|
365
365
|
end
|
@@ -1,21 +1,79 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
require "dependabot/credential"
|
4
7
|
require "dependabot/clients/azure"
|
5
8
|
require "dependabot/pull_request_creator"
|
6
9
|
|
7
10
|
module Dependabot
|
8
11
|
class PullRequestCreator
|
9
12
|
class Azure
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
extend T::Sig
|
14
|
+
|
15
|
+
sig { returns(Dependabot::Source) }
|
16
|
+
attr_reader :source
|
17
|
+
|
18
|
+
sig { returns(String) }
|
19
|
+
attr_reader :branch_name
|
20
|
+
|
21
|
+
sig { returns(String) }
|
22
|
+
attr_reader :base_commit
|
23
|
+
|
24
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
25
|
+
attr_reader :credentials
|
26
|
+
|
27
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
28
|
+
attr_reader :files
|
29
|
+
|
30
|
+
sig { returns(String) }
|
31
|
+
attr_reader :commit_message
|
32
|
+
|
33
|
+
sig { returns(String) }
|
34
|
+
attr_reader :pr_description
|
35
|
+
|
36
|
+
sig { returns(String) }
|
37
|
+
attr_reader :pr_name
|
38
|
+
|
39
|
+
sig { returns(T.nilable(T::Hash[Symbol, String])) }
|
40
|
+
attr_reader :author_details
|
41
|
+
|
42
|
+
sig { returns(Dependabot::PullRequestCreator::Labeler) }
|
43
|
+
attr_reader :labeler
|
44
|
+
|
45
|
+
sig { returns(T.nilable(T::Array[String])) }
|
46
|
+
attr_reader :reviewers
|
47
|
+
|
48
|
+
sig { returns(T.nilable(T::Array[String])) }
|
49
|
+
attr_reader :assignees
|
50
|
+
|
51
|
+
sig { returns(T.nilable(Integer)) }
|
52
|
+
attr_reader :work_item
|
13
53
|
|
14
54
|
# Azure DevOps limits PR descriptions to a max of 4,000 characters in UTF-16 encoding:
|
15
55
|
# https://developercommunity.visualstudio.com/content/problem/608770/remove-4000-character-limit-on-pull-request-descri.html
|
16
56
|
PR_DESCRIPTION_MAX_LENGTH = 3_999 # 0 based count
|
17
57
|
PR_DESCRIPTION_ENCODING = Encoding::UTF_16
|
18
58
|
|
59
|
+
sig do
|
60
|
+
params(
|
61
|
+
source: Dependabot::Source,
|
62
|
+
branch_name: String,
|
63
|
+
base_commit: String,
|
64
|
+
credentials: T::Array[Dependabot::Credential],
|
65
|
+
files: T::Array[Dependabot::DependencyFile],
|
66
|
+
commit_message: String,
|
67
|
+
pr_description: String,
|
68
|
+
pr_name: String,
|
69
|
+
author_details: T.nilable(T::Hash[Symbol, String]),
|
70
|
+
labeler: Dependabot::PullRequestCreator::Labeler,
|
71
|
+
reviewers: T.nilable(T::Array[String]),
|
72
|
+
assignees: T.nilable(T::Array[String]),
|
73
|
+
work_item: T.nilable(Integer)
|
74
|
+
)
|
75
|
+
.void
|
76
|
+
end
|
19
77
|
def initialize(source:, branch_name:, base_commit:, credentials:,
|
20
78
|
files:, commit_message:, pr_description:, pr_name:,
|
21
79
|
author_details:, labeler:, reviewers: nil, assignees: nil, work_item: nil)
|
@@ -34,6 +92,7 @@ module Dependabot
|
|
34
92
|
@work_item = work_item
|
35
93
|
end
|
36
94
|
|
95
|
+
sig { returns(T.nilable(Excon::Response)) }
|
37
96
|
def create
|
38
97
|
return if branch_exists? && pull_request_exists?
|
39
98
|
|
@@ -46,20 +105,26 @@ module Dependabot
|
|
46
105
|
|
47
106
|
private
|
48
107
|
|
108
|
+
sig { returns(Dependabot::Clients::Azure) }
|
49
109
|
def azure_client_for_source
|
50
110
|
@azure_client_for_source ||=
|
51
|
-
|
52
|
-
|
53
|
-
|
111
|
+
T.let(
|
112
|
+
Dependabot::Clients::Azure.for_source(
|
113
|
+
source: source,
|
114
|
+
credentials: credentials
|
115
|
+
),
|
116
|
+
T.nilable(Dependabot::Clients::Azure)
|
54
117
|
)
|
55
118
|
end
|
56
119
|
|
120
|
+
sig { returns(T::Boolean) }
|
57
121
|
def branch_exists?
|
58
|
-
azure_client_for_source.branch(branch_name)
|
122
|
+
!azure_client_for_source.branch(branch_name).nil?
|
59
123
|
rescue ::Dependabot::Clients::Azure::NotFound
|
60
124
|
false
|
61
125
|
end
|
62
126
|
|
127
|
+
sig { returns(T::Boolean) }
|
63
128
|
def pull_request_exists?
|
64
129
|
azure_client_for_source.pull_requests(
|
65
130
|
branch_name,
|
@@ -67,6 +132,7 @@ module Dependabot
|
|
67
132
|
).any?
|
68
133
|
end
|
69
134
|
|
135
|
+
sig { void }
|
70
136
|
def create_commit
|
71
137
|
author = author_details&.slice(:name, :email, :date)
|
72
138
|
author = nil unless author&.any?
|
@@ -80,6 +146,7 @@ module Dependabot
|
|
80
146
|
)
|
81
147
|
end
|
82
148
|
|
149
|
+
sig { returns(Excon::Response) }
|
83
150
|
def create_pull_request
|
84
151
|
azure_client_for_source.create_pull_request(
|
85
152
|
pr_name,
|
@@ -93,9 +160,13 @@ module Dependabot
|
|
93
160
|
)
|
94
161
|
end
|
95
162
|
|
163
|
+
sig { returns(String) }
|
96
164
|
def default_branch
|
97
165
|
@default_branch ||=
|
98
|
-
|
166
|
+
T.let(
|
167
|
+
azure_client_for_source.fetch_default_branch(source.repo),
|
168
|
+
T.nilable(String)
|
169
|
+
)
|
99
170
|
end
|
100
171
|
end
|
101
172
|
end
|
@@ -1,19 +1,70 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
4
6
|
require "dependabot/clients/bitbucket"
|
7
|
+
require "dependabot/credential"
|
8
|
+
require "dependabot/dependency_file"
|
5
9
|
require "dependabot/pull_request_creator"
|
6
10
|
|
7
11
|
module Dependabot
|
8
12
|
class PullRequestCreator
|
9
13
|
class Bitbucket
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
extend T::Sig
|
15
|
+
|
16
|
+
sig { returns(Dependabot::Source) }
|
17
|
+
attr_reader :source
|
18
|
+
|
19
|
+
sig { returns(String) }
|
20
|
+
attr_reader :branch_name
|
21
|
+
|
22
|
+
sig { returns(String) }
|
23
|
+
attr_reader :base_commit
|
24
|
+
|
25
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
26
|
+
attr_reader :credentials
|
27
|
+
|
28
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
29
|
+
attr_reader :files
|
30
|
+
|
31
|
+
sig { returns(String) }
|
32
|
+
attr_reader :commit_message
|
33
|
+
|
34
|
+
sig { returns(String) }
|
35
|
+
attr_reader :pr_description
|
36
|
+
|
37
|
+
sig { returns(String) }
|
38
|
+
attr_reader :pr_name
|
39
|
+
|
40
|
+
sig { returns(T.nilable(T::Hash[Symbol, String])) }
|
41
|
+
attr_reader :author_details
|
42
|
+
|
43
|
+
sig { returns(T.nilable(Dependabot::PullRequestCreator::Labeler)) }
|
44
|
+
attr_reader :labeler
|
45
|
+
|
46
|
+
sig { returns(T.nilable(Integer)) }
|
47
|
+
attr_reader :work_item
|
13
48
|
|
14
49
|
# BitBucket Cloud accepts > 1MB characters, but they display poorly in the UI, so limiting to 4x 65,536
|
15
50
|
PR_DESCRIPTION_MAX_LENGTH = 262_143 # 0 based count
|
16
51
|
|
52
|
+
sig do
|
53
|
+
params(
|
54
|
+
source: Dependabot::Source,
|
55
|
+
branch_name: String,
|
56
|
+
base_commit: String,
|
57
|
+
credentials: T::Array[Dependabot::Credential],
|
58
|
+
files: T::Array[Dependabot::DependencyFile],
|
59
|
+
commit_message: String,
|
60
|
+
pr_description: String,
|
61
|
+
pr_name: String,
|
62
|
+
author_details: T.nilable(T::Hash[Symbol, String]),
|
63
|
+
labeler: T.nilable(Dependabot::PullRequestCreator::Labeler),
|
64
|
+
work_item: T.nilable(Integer)
|
65
|
+
)
|
66
|
+
.void
|
67
|
+
end
|
17
68
|
def initialize(source:, branch_name:, base_commit:, credentials:,
|
18
69
|
files:, commit_message:, pr_description:, pr_name:,
|
19
70
|
author_details:, labeler: nil, work_item: nil)
|
@@ -30,6 +81,7 @@ module Dependabot
|
|
30
81
|
@work_item = work_item
|
31
82
|
end
|
32
83
|
|
84
|
+
sig { void }
|
33
85
|
def create
|
34
86
|
return if branch_exists? && pull_request_exists?
|
35
87
|
|
@@ -43,20 +95,26 @@ module Dependabot
|
|
43
95
|
|
44
96
|
private
|
45
97
|
|
98
|
+
sig { returns(Dependabot::Clients::Bitbucket) }
|
46
99
|
def bitbucket_client_for_source
|
47
100
|
@bitbucket_client_for_source ||=
|
48
|
-
|
49
|
-
|
50
|
-
|
101
|
+
T.let(
|
102
|
+
Dependabot::Clients::Bitbucket.for_source(
|
103
|
+
source: source,
|
104
|
+
credentials: credentials
|
105
|
+
),
|
106
|
+
T.nilable(Dependabot::Clients::Bitbucket)
|
51
107
|
)
|
52
108
|
end
|
53
109
|
|
110
|
+
sig { returns(T::Boolean) }
|
54
111
|
def branch_exists?
|
55
|
-
bitbucket_client_for_source.branch(source.repo, branch_name)
|
112
|
+
!bitbucket_client_for_source.branch(source.repo, branch_name).nil?
|
56
113
|
rescue Clients::Bitbucket::NotFound
|
57
114
|
false
|
58
115
|
end
|
59
116
|
|
117
|
+
sig { returns(T::Boolean) }
|
60
118
|
def pull_request_exists?
|
61
119
|
bitbucket_client_for_source.pull_requests(
|
62
120
|
source.repo,
|
@@ -65,6 +123,7 @@ module Dependabot
|
|
65
123
|
).any?
|
66
124
|
end
|
67
125
|
|
126
|
+
sig { void }
|
68
127
|
def create_commit
|
69
128
|
author = author_details&.slice(:name, :email)
|
70
129
|
author = nil unless author&.any?
|
@@ -79,6 +138,7 @@ module Dependabot
|
|
79
138
|
)
|
80
139
|
end
|
81
140
|
|
141
|
+
sig { void }
|
82
142
|
def create_pull_request
|
83
143
|
bitbucket_client_for_source.create_pull_request(
|
84
144
|
source.repo,
|
@@ -91,9 +151,13 @@ module Dependabot
|
|
91
151
|
)
|
92
152
|
end
|
93
153
|
|
154
|
+
sig { returns(String) }
|
94
155
|
def default_branch
|
95
156
|
@default_branch ||=
|
96
|
-
|
157
|
+
T.let(
|
158
|
+
bitbucket_client_for_source.fetch_default_branch(source.repo),
|
159
|
+
T.nilable(String)
|
160
|
+
)
|
97
161
|
end
|
98
162
|
end
|
99
163
|
end
|