dependabot-common 0.95.1 → 0.95.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dependabot.rb +4 -0
- data/lib/dependabot/clients/bitbucket.rb +105 -0
- data/lib/dependabot/clients/github_with_retries.rb +121 -0
- data/lib/dependabot/clients/gitlab.rb +72 -0
- data/lib/dependabot/dependency.rb +115 -0
- data/lib/dependabot/dependency_file.rb +60 -0
- data/lib/dependabot/errors.rb +179 -0
- data/lib/dependabot/file_fetchers.rb +18 -0
- data/lib/dependabot/file_fetchers/README.md +65 -0
- data/lib/dependabot/file_fetchers/base.rb +368 -0
- data/lib/dependabot/file_parsers.rb +18 -0
- data/lib/dependabot/file_parsers/README.md +45 -0
- data/lib/dependabot/file_parsers/base.rb +31 -0
- data/lib/dependabot/file_parsers/base/dependency_set.rb +77 -0
- data/lib/dependabot/file_updaters.rb +18 -0
- data/lib/dependabot/file_updaters/README.md +58 -0
- data/lib/dependabot/file_updaters/base.rb +52 -0
- data/lib/dependabot/git_commit_checker.rb +412 -0
- data/lib/dependabot/metadata_finders.rb +18 -0
- data/lib/dependabot/metadata_finders/README.md +53 -0
- data/lib/dependabot/metadata_finders/base.rb +117 -0
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +321 -0
- data/lib/dependabot/metadata_finders/base/changelog_pruner.rb +177 -0
- data/lib/dependabot/metadata_finders/base/commits_finder.rb +221 -0
- data/lib/dependabot/metadata_finders/base/release_finder.rb +255 -0
- data/lib/dependabot/pull_request_creator.rb +155 -0
- data/lib/dependabot/pull_request_creator/branch_namer.rb +170 -0
- data/lib/dependabot/pull_request_creator/commit_signer.rb +63 -0
- data/lib/dependabot/pull_request_creator/github.rb +277 -0
- data/lib/dependabot/pull_request_creator/gitlab.rb +162 -0
- data/lib/dependabot/pull_request_creator/labeler.rb +373 -0
- data/lib/dependabot/pull_request_creator/message_builder.rb +906 -0
- data/lib/dependabot/pull_request_updater.rb +43 -0
- data/lib/dependabot/pull_request_updater/github.rb +165 -0
- data/lib/dependabot/shared_helpers.rb +224 -0
- data/lib/dependabot/source.rb +120 -0
- data/lib/dependabot/update_checkers.rb +18 -0
- data/lib/dependabot/update_checkers/README.md +67 -0
- data/lib/dependabot/update_checkers/base.rb +220 -0
- data/lib/dependabot/utils.rb +33 -0
- data/lib/dependabot/version.rb +5 -0
- data/lib/rubygems_version_patch.rb +14 -0
- metadata +44 -2
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dependabot
|
4
|
+
module MetadataFinders
|
5
|
+
@metadata_finders = {}
|
6
|
+
|
7
|
+
def self.for_package_manager(package_manager)
|
8
|
+
metadata_finder = @metadata_finders[package_manager]
|
9
|
+
return metadata_finder if metadata_finder
|
10
|
+
|
11
|
+
raise "Unsupported package_manager #{package_manager}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.register(package_manager, metadata_finder)
|
15
|
+
@metadata_finders[package_manager] = metadata_finder
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Metadata finders
|
2
|
+
|
3
|
+
Metadata finders look up metadata about a dependency, such as its GitHub URL.
|
4
|
+
|
5
|
+
There is a `Dependabot::MetadataFinders` class for each language Dependabot
|
6
|
+
supports.
|
7
|
+
|
8
|
+
## Public API
|
9
|
+
|
10
|
+
Each `Dependabot::MetadataFinders` class exposes the following methods:
|
11
|
+
|
12
|
+
| Method | Description |
|
13
|
+
|-----------------------|---------------------------------------------------------------------------------------------|
|
14
|
+
| `#source_url` | A link to the source data for the dependency. |
|
15
|
+
| `#homepage_url` | A link to the homepage for the dependency. |
|
16
|
+
| `#commits_url` | A link to a commit diff between the previous version of the dependency and the new version. |
|
17
|
+
| `#commits` | A list of commits between the previous version of the dependency and the new version. |
|
18
|
+
| `#changelog_url` | A link to the changelog for the dependency. |
|
19
|
+
| `#changelog_text` | The relevant text from the changelog. |
|
20
|
+
| `#release_url` | A link to the release notes for this version of the dependency. |
|
21
|
+
| `#release_text` | The relevant text from the release notes |
|
22
|
+
| `#upgrade_guide_url` | A link to the upgrade guide for this upgrade (if it exists). |
|
23
|
+
| `#upgrade_guide_text` | The text of the upgrade guide for this upgrade (if it exists). |
|
24
|
+
|
25
|
+
An integration might look as follows:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'dependabot/metadata_finders'
|
29
|
+
|
30
|
+
dependency = update_checker.updated_dependency
|
31
|
+
|
32
|
+
metadata_finder_class = Dependabot::MetadataFinders::Ruby::Bundler
|
33
|
+
metadata_finder = metadata_finder_class.new(
|
34
|
+
dependency: dependency,
|
35
|
+
credentials: credentials
|
36
|
+
)
|
37
|
+
|
38
|
+
puts "Changelog for #{dependency.name} is at #{metadata_finder.changelog_url}"
|
39
|
+
```
|
40
|
+
|
41
|
+
## Writing a metadata finder for a new language
|
42
|
+
|
43
|
+
All new metadata finders should inherit from `Dependabot::MetadataFinders::Base`
|
44
|
+
and implement the following methods:
|
45
|
+
|
46
|
+
| Method | Description |
|
47
|
+
|------------------------|-------------------------|
|
48
|
+
| `#look_up_source` | Private method that returns a `Dependabot::Source` object. Generally the source details are extracted from a source code URL provided by the language's dependency registry, but sometimes it's already know from parsing the dependency file. |
|
49
|
+
|
50
|
+
To ensure the above are implemented, you should include
|
51
|
+
`it_behaves_like "a dependency metadata finder"` in your specs for the new
|
52
|
+
metadata finder.
|
53
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dependabot/source"
|
4
|
+
|
5
|
+
module Dependabot
|
6
|
+
module MetadataFinders
|
7
|
+
class Base
|
8
|
+
require "dependabot/metadata_finders/base/changelog_finder"
|
9
|
+
require "dependabot/metadata_finders/base/release_finder"
|
10
|
+
require "dependabot/metadata_finders/base/commits_finder"
|
11
|
+
|
12
|
+
attr_reader :dependency, :credentials
|
13
|
+
|
14
|
+
def initialize(dependency:, credentials:)
|
15
|
+
@dependency = dependency
|
16
|
+
@credentials = credentials
|
17
|
+
end
|
18
|
+
|
19
|
+
def source_url
|
20
|
+
source&.url
|
21
|
+
end
|
22
|
+
|
23
|
+
def homepage_url
|
24
|
+
source_url
|
25
|
+
end
|
26
|
+
|
27
|
+
def changelog_url
|
28
|
+
@changelog_finder ||= ChangelogFinder.new(
|
29
|
+
dependency: dependency,
|
30
|
+
source: source,
|
31
|
+
credentials: credentials
|
32
|
+
)
|
33
|
+
@changelog_finder.changelog_url
|
34
|
+
end
|
35
|
+
|
36
|
+
def changelog_text
|
37
|
+
@changelog_finder ||= ChangelogFinder.new(
|
38
|
+
dependency: dependency,
|
39
|
+
source: source,
|
40
|
+
credentials: credentials
|
41
|
+
)
|
42
|
+
@changelog_finder.changelog_text
|
43
|
+
end
|
44
|
+
|
45
|
+
def upgrade_guide_url
|
46
|
+
@changelog_finder ||= ChangelogFinder.new(
|
47
|
+
dependency: dependency,
|
48
|
+
source: source,
|
49
|
+
credentials: credentials
|
50
|
+
)
|
51
|
+
@changelog_finder.upgrade_guide_url
|
52
|
+
end
|
53
|
+
|
54
|
+
def upgrade_guide_text
|
55
|
+
@changelog_finder ||= ChangelogFinder.new(
|
56
|
+
dependency: dependency,
|
57
|
+
source: source,
|
58
|
+
credentials: credentials
|
59
|
+
)
|
60
|
+
@changelog_finder.upgrade_guide_text
|
61
|
+
end
|
62
|
+
|
63
|
+
def releases_url
|
64
|
+
@release_finder ||= ReleaseFinder.new(
|
65
|
+
dependency: dependency,
|
66
|
+
source: source,
|
67
|
+
credentials: credentials
|
68
|
+
)
|
69
|
+
@release_finder.releases_url
|
70
|
+
end
|
71
|
+
|
72
|
+
def releases_text
|
73
|
+
@release_finder ||= ReleaseFinder.new(
|
74
|
+
dependency: dependency,
|
75
|
+
source: source,
|
76
|
+
credentials: credentials
|
77
|
+
)
|
78
|
+
@release_finder.releases_text
|
79
|
+
end
|
80
|
+
|
81
|
+
def commits_url
|
82
|
+
@commits_finder ||= CommitsFinder.new(
|
83
|
+
dependency: dependency,
|
84
|
+
source: source,
|
85
|
+
credentials: credentials
|
86
|
+
)
|
87
|
+
@commits_finder.commits_url
|
88
|
+
end
|
89
|
+
|
90
|
+
def commits
|
91
|
+
@commits_finder ||= CommitsFinder.new(
|
92
|
+
dependency: dependency,
|
93
|
+
source: source,
|
94
|
+
credentials: credentials
|
95
|
+
)
|
96
|
+
@commits_finder.commits
|
97
|
+
end
|
98
|
+
|
99
|
+
def maintainer_changes
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def source
|
106
|
+
return @source if @source_lookup_attempted
|
107
|
+
|
108
|
+
@source_lookup_attempted = true
|
109
|
+
@source = look_up_source
|
110
|
+
end
|
111
|
+
|
112
|
+
def look_up_source
|
113
|
+
raise NotImplementedError
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "excon"
|
4
|
+
|
5
|
+
require "dependabot/clients/github_with_retries"
|
6
|
+
require "dependabot/clients/gitlab"
|
7
|
+
require "dependabot/clients/bitbucket"
|
8
|
+
require "dependabot/shared_helpers"
|
9
|
+
require "dependabot/metadata_finders/base"
|
10
|
+
|
11
|
+
module Dependabot
|
12
|
+
module MetadataFinders
|
13
|
+
class Base
|
14
|
+
class ChangelogFinder
|
15
|
+
require_relative "changelog_pruner"
|
16
|
+
require_relative "commits_finder"
|
17
|
+
|
18
|
+
# Earlier entries are preferred
|
19
|
+
CHANGELOG_NAMES = %w(changelog history news changes release).freeze
|
20
|
+
|
21
|
+
attr_reader :source, :dependency, :credentials
|
22
|
+
|
23
|
+
def initialize(source:, dependency:, credentials:)
|
24
|
+
@source = source
|
25
|
+
@dependency = dependency
|
26
|
+
@credentials = credentials
|
27
|
+
end
|
28
|
+
|
29
|
+
def changelog_url
|
30
|
+
changelog&.html_url
|
31
|
+
end
|
32
|
+
|
33
|
+
def changelog_text
|
34
|
+
return unless full_changelog_text
|
35
|
+
|
36
|
+
ChangelogPruner.new(
|
37
|
+
dependency: dependency,
|
38
|
+
changelog_text: full_changelog_text
|
39
|
+
).pruned_text
|
40
|
+
end
|
41
|
+
|
42
|
+
def upgrade_guide_url
|
43
|
+
upgrade_guide&.html_url
|
44
|
+
end
|
45
|
+
|
46
|
+
def upgrade_guide_text
|
47
|
+
return unless upgrade_guide
|
48
|
+
|
49
|
+
@upgrade_guide_text ||= fetch_file_text(upgrade_guide)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
55
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
56
|
+
def changelog
|
57
|
+
return unless source
|
58
|
+
|
59
|
+
# Changelog won't be relevant for a git commit bump
|
60
|
+
return if git_source? && !ref_changed?
|
61
|
+
|
62
|
+
# If there is a changelog, and it includes the new version, return it
|
63
|
+
if new_version && default_branch_changelog &&
|
64
|
+
fetch_file_text(default_branch_changelog)&.include?(new_version)
|
65
|
+
return default_branch_changelog
|
66
|
+
end
|
67
|
+
|
68
|
+
# Otherwise, look for a changelog at the tag for this version
|
69
|
+
if new_version && relevant_tag_changelog &&
|
70
|
+
fetch_file_text(relevant_tag_changelog)&.include?(new_version)
|
71
|
+
return relevant_tag_changelog
|
72
|
+
end
|
73
|
+
|
74
|
+
# Fall back to the changelog (or nil) from the default branch
|
75
|
+
default_branch_changelog
|
76
|
+
end
|
77
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
78
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
79
|
+
|
80
|
+
def default_branch_changelog
|
81
|
+
return unless source
|
82
|
+
|
83
|
+
@default_branch_changelog ||= changelog_from_ref(nil)
|
84
|
+
end
|
85
|
+
|
86
|
+
def relevant_tag_changelog
|
87
|
+
return unless source
|
88
|
+
return unless tag_for_new_version
|
89
|
+
|
90
|
+
@relevant_tag_changelog ||= changelog_from_ref(tag_for_new_version)
|
91
|
+
end
|
92
|
+
|
93
|
+
def changelog_from_ref(ref)
|
94
|
+
files =
|
95
|
+
dependency_file_list(ref).
|
96
|
+
select { |f| f.type == "file" }.
|
97
|
+
reject { |f| f.name.end_with?(".sh") }.
|
98
|
+
reject { |f| f.size > 1_000_000 }
|
99
|
+
|
100
|
+
CHANGELOG_NAMES.each do |name|
|
101
|
+
candidates = files.select { |f| f.name =~ /#{name}/i }
|
102
|
+
file = candidates.first if candidates.one?
|
103
|
+
file ||=
|
104
|
+
candidates.find do |f|
|
105
|
+
candidates -= [f] && next if fetch_file_text(f).nil?
|
106
|
+
ChangelogPruner.new(
|
107
|
+
dependency: dependency,
|
108
|
+
changelog_text: fetch_file_text(f)
|
109
|
+
).includes_new_version?
|
110
|
+
end
|
111
|
+
file ||= candidates.max_by(&:size)
|
112
|
+
return file if file
|
113
|
+
end
|
114
|
+
|
115
|
+
nil
|
116
|
+
end
|
117
|
+
|
118
|
+
def tag_for_new_version
|
119
|
+
@tag_for_new_version ||=
|
120
|
+
CommitsFinder.new(
|
121
|
+
dependency: dependency,
|
122
|
+
source: source,
|
123
|
+
credentials: credentials
|
124
|
+
).new_tag
|
125
|
+
end
|
126
|
+
|
127
|
+
def full_changelog_text
|
128
|
+
return unless changelog
|
129
|
+
|
130
|
+
fetch_file_text(changelog)
|
131
|
+
end
|
132
|
+
|
133
|
+
def fetch_file_text(file)
|
134
|
+
@file_text ||= {}
|
135
|
+
|
136
|
+
unless @file_text.key?(file.download_url)
|
137
|
+
@file_text[file.download_url] =
|
138
|
+
case source.provider
|
139
|
+
when "github" then fetch_github_file(file)
|
140
|
+
when "gitlab" then fetch_gitlab_file(file)
|
141
|
+
when "bitbucket" then fetch_bitbucket_file(file)
|
142
|
+
else raise "Unsupported provider '#{source.provider}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
return unless @file_text[file.download_url].valid_encoding?
|
147
|
+
|
148
|
+
@file_text[file.download_url].
|
149
|
+
force_encoding("UTF-8").
|
150
|
+
encode.sub(/\n*\z/, "")
|
151
|
+
end
|
152
|
+
|
153
|
+
def fetch_github_file(file)
|
154
|
+
# Hitting the download URL directly causes encoding problems
|
155
|
+
raw_content = github_client.get(file.url).content
|
156
|
+
Base64.decode64(raw_content).force_encoding("UTF-8").encode
|
157
|
+
end
|
158
|
+
|
159
|
+
def fetch_gitlab_file(file)
|
160
|
+
Excon.get(
|
161
|
+
file.download_url,
|
162
|
+
idempotent: true,
|
163
|
+
**SharedHelpers.excon_defaults
|
164
|
+
).body
|
165
|
+
end
|
166
|
+
|
167
|
+
def fetch_bitbucket_file(file)
|
168
|
+
bitbucket_client.get(file.download_url).body
|
169
|
+
end
|
170
|
+
|
171
|
+
def upgrade_guide
|
172
|
+
return unless source
|
173
|
+
|
174
|
+
# Upgrade guide usually won't be relevant for bumping anything other
|
175
|
+
# than the major version
|
176
|
+
return unless major_version_upgrade?
|
177
|
+
|
178
|
+
dependency_file_list.
|
179
|
+
select { |f| f.type == "file" }.
|
180
|
+
select { |f| f.name.casecmp("upgrade.md").zero? }.
|
181
|
+
reject { |f| f.size > 1_000_000 }.
|
182
|
+
max_by(&:size)
|
183
|
+
end
|
184
|
+
|
185
|
+
def dependency_file_list(ref = nil)
|
186
|
+
@dependency_file_list ||= {}
|
187
|
+
@dependency_file_list[ref] ||= fetch_dependency_file_list(ref)
|
188
|
+
end
|
189
|
+
|
190
|
+
def fetch_dependency_file_list(ref)
|
191
|
+
case source.provider
|
192
|
+
when "github" then fetch_github_file_list(ref)
|
193
|
+
when "bitbucket" then fetch_bitbucket_file_list
|
194
|
+
when "gitlab" then fetch_gitlab_file_list
|
195
|
+
when "azure" then [] # TODO: Fetch files from Azure
|
196
|
+
else raise "Unexpected repo provider '#{source.provider}'"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def fetch_github_file_list(ref)
|
201
|
+
files = []
|
202
|
+
|
203
|
+
if source.directory
|
204
|
+
opts = { path: source.directory, ref: ref }.compact
|
205
|
+
tmp_files = github_client.contents(source.repo, opts)
|
206
|
+
files += tmp_files if tmp_files.is_a?(Array)
|
207
|
+
end
|
208
|
+
|
209
|
+
opts = { ref: ref }.compact
|
210
|
+
files += github_client.contents(source.repo, opts)
|
211
|
+
|
212
|
+
files.uniq.each do |f|
|
213
|
+
next unless %w(doc docs).include?(f.name) && f.type == "dir"
|
214
|
+
|
215
|
+
opts = { path: f.path, ref: ref }.compact
|
216
|
+
files += github_client.contents(source.repo, opts)
|
217
|
+
end
|
218
|
+
|
219
|
+
files
|
220
|
+
rescue Octokit::NotFound
|
221
|
+
[]
|
222
|
+
end
|
223
|
+
|
224
|
+
def fetch_bitbucket_file_list
|
225
|
+
branch = default_bitbucket_branch
|
226
|
+
bitbucket_client.fetch_repo_contents(source.repo).map do |file|
|
227
|
+
OpenStruct.new(
|
228
|
+
name: file.fetch("path").split("/").last,
|
229
|
+
type: file.fetch("type") == "commit_file" ? "file" : file["type"],
|
230
|
+
size: file.fetch("size", 0),
|
231
|
+
html_url: "#{source.url}/src/#{branch}/#{file['path']}",
|
232
|
+
download_url: "#{source.url}/raw/#{branch}/#{file['path']}"
|
233
|
+
)
|
234
|
+
end
|
235
|
+
rescue Dependabot::Clients::Bitbucket::NotFound,
|
236
|
+
Dependabot::Clients::Bitbucket::Unauthorized,
|
237
|
+
Dependabot::Clients::Bitbucket::Forbidden
|
238
|
+
[]
|
239
|
+
end
|
240
|
+
|
241
|
+
def fetch_gitlab_file_list
|
242
|
+
gitlab_client.repo_tree(source.repo).map do |file|
|
243
|
+
OpenStruct.new(
|
244
|
+
name: file.name,
|
245
|
+
type: file.type == "blob" ? "file" : file.type,
|
246
|
+
size: 0, # GitLab doesn't return file size
|
247
|
+
html_url: "#{source.url}/blob/master/#{file.path}",
|
248
|
+
download_url: "#{source.url}/raw/master/#{file.path}"
|
249
|
+
)
|
250
|
+
end
|
251
|
+
rescue Gitlab::Error::NotFound
|
252
|
+
[]
|
253
|
+
end
|
254
|
+
|
255
|
+
def new_version
|
256
|
+
@new_version ||= git_source? ? new_ref : dependency.version
|
257
|
+
@new_version&.gsub(/^v/, "")
|
258
|
+
end
|
259
|
+
|
260
|
+
def previous_ref
|
261
|
+
dependency.previous_requirements.map do |r|
|
262
|
+
r.dig(:source, "ref") || r.dig(:source, :ref)
|
263
|
+
end.compact.first
|
264
|
+
end
|
265
|
+
|
266
|
+
def new_ref
|
267
|
+
dependency.requirements.map do |r|
|
268
|
+
r.dig(:source, "ref") || r.dig(:source, :ref)
|
269
|
+
end.compact.first
|
270
|
+
end
|
271
|
+
|
272
|
+
def ref_changed?
|
273
|
+
previous_ref && new_ref && previous_ref != new_ref
|
274
|
+
end
|
275
|
+
|
276
|
+
# TODO: Refactor me so that Composer doesn't need to be special cased
|
277
|
+
def git_source?
|
278
|
+
# Special case Composer, which uses git as a source but handles tags
|
279
|
+
# internally
|
280
|
+
return false if dependency.package_manager == "composer"
|
281
|
+
|
282
|
+
requirements = dependency.requirements
|
283
|
+
sources = requirements.map { |r| r.fetch(:source) }.uniq.compact
|
284
|
+
return false if sources.empty?
|
285
|
+
raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1
|
286
|
+
|
287
|
+
source_type = sources.first[:type] || sources.first.fetch("type")
|
288
|
+
source_type == "git"
|
289
|
+
end
|
290
|
+
|
291
|
+
def major_version_upgrade?
|
292
|
+
return false unless dependency.version&.match?(/^\d/)
|
293
|
+
return false unless dependency.previous_version&.match?(/^\d/)
|
294
|
+
|
295
|
+
dependency.version.split(".").first.to_i -
|
296
|
+
dependency.previous_version.split(".").first.to_i >= 1
|
297
|
+
end
|
298
|
+
|
299
|
+
def gitlab_client
|
300
|
+
@gitlab_client ||= Dependabot::Clients::Gitlab.
|
301
|
+
for_gitlab_dot_com(credentials: credentials)
|
302
|
+
end
|
303
|
+
|
304
|
+
def github_client
|
305
|
+
@github_client ||= Dependabot::Clients::GithubWithRetries.
|
306
|
+
for_github_dot_com(credentials: credentials)
|
307
|
+
end
|
308
|
+
|
309
|
+
def bitbucket_client
|
310
|
+
@bitbucket_client ||= Dependabot::Clients::Bitbucket.
|
311
|
+
for_bitbucket_dot_org(credentials: credentials)
|
312
|
+
end
|
313
|
+
|
314
|
+
def default_bitbucket_branch
|
315
|
+
@default_bitbucket_branch ||=
|
316
|
+
bitbucket_client.fetch_default_branch(source.repo)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|