dependabot-common 0.215.0 → 0.216.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.
- checksums.yaml +4 -4
- data/lib/dependabot/clients/azure.rb +69 -0
- data/lib/dependabot/clients/bitbucket.rb +3 -1
- data/lib/dependabot/clients/github_with_retries.rb +6 -0
- data/lib/dependabot/config/file_fetcher.rb +1 -1
- data/lib/dependabot/config/ignore_condition.rb +20 -13
- data/lib/dependabot/dependency.rb +63 -2
- data/lib/dependabot/dependency_file.rb +1 -1
- data/lib/dependabot/errors.rb +1 -1
- data/lib/dependabot/file_fetchers/base.rb +15 -4
- data/lib/dependabot/file_parsers/base/dependency_set.rb +19 -12
- data/lib/dependabot/file_parsers/base.rb +0 -2
- data/lib/dependabot/git_metadata_fetcher.rb +30 -25
- data/lib/dependabot/group_rule.rb +11 -0
- data/lib/dependabot/metadata_finders/README.md +1 -1
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +53 -11
- data/lib/dependabot/metadata_finders/base/commits_finder.rb +40 -3
- data/lib/dependabot/metadata_finders/base/release_finder.rb +1 -1
- data/lib/dependabot/pull_request_creator/branch_namer/group_rule_strategy.rb +28 -0
- data/lib/dependabot/pull_request_creator/branch_namer/solo_strategy.rb +208 -0
- data/lib/dependabot/pull_request_creator/branch_namer.rb +28 -179
- data/lib/dependabot/pull_request_creator/labeler.rb +5 -1
- data/lib/dependabot/pull_request_creator/message_builder/link_and_mention_sanitizer.rb +3 -1
- data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +1 -1
- data/lib/dependabot/pull_request_creator/message_builder.rb +22 -81
- data/lib/dependabot/pull_request_creator.rb +1 -0
- data/lib/dependabot/security_advisory.rb +1 -1
- data/lib/dependabot/shared_helpers.rb +16 -3
- data/lib/dependabot/simple_instrumentor.rb +19 -0
- data/lib/dependabot/source.rb +7 -7
- data/lib/dependabot/version.rb +18 -1
- data/lib/dependabot.rb +1 -0
- metadata +46 -62
- data/lib/dependabot/notifications.rb +0 -18
- data/lib/rubygems_version_patch.rb +0 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 645d08a2a5cfd122e1ec0bb4302d7c4e80bd0348e0c0e52d28dc210d196b963b
|
|
4
|
+
data.tar.gz: 25d81216a7b48d60b332d241e06f3a7dcc384b06ea3f5fac1dcc02949da226dc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ef726592da7c2ff04784322801d12902ab42613e53b084687acdbfb479982e60a5303cb6e7f249e5525547a7b7681af48c3afe9df16cfda435b771e5e3f84ad
|
|
7
|
+
data.tar.gz: ef3a1010b2dd5736c9595754b1eb1cf1cca4cd7eecdfae551b97a2d84c71952ccad43bedafab0f9b6cea07892afbff41b766d9d8941ae10bcd7eedb434970aa3
|
|
@@ -192,6 +192,32 @@ module Dependabot
|
|
|
192
192
|
"/pullrequests?api-version=5.0", content.to_json)
|
|
193
193
|
end
|
|
194
194
|
|
|
195
|
+
def autocomplete_pull_request(pull_request_id, auto_complete_set_by, merge_commit_message,
|
|
196
|
+
delete_source_branch = true, squash_merge = true, merge_strategy = "squash",
|
|
197
|
+
trans_work_items = true, ignore_config_ids = [])
|
|
198
|
+
|
|
199
|
+
content = {
|
|
200
|
+
autoCompleteSetBy: {
|
|
201
|
+
id: auto_complete_set_by
|
|
202
|
+
},
|
|
203
|
+
completionOptions: {
|
|
204
|
+
mergeCommitMessage: merge_commit_message,
|
|
205
|
+
deleteSourceBranch: delete_source_branch,
|
|
206
|
+
squashMerge: squash_merge,
|
|
207
|
+
mergeStrategy: merge_strategy,
|
|
208
|
+
transitionWorkItems: trans_work_items,
|
|
209
|
+
autoCompleteIgnoreConfigIds: ignore_config_ids
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
response = patch(source.api_endpoint +
|
|
214
|
+
source.organization + "/" + source.project +
|
|
215
|
+
"/_apis/git/repositories/" + source.unscoped_repo +
|
|
216
|
+
"/pullrequests/" + pull_request_id.to_s + "?api-version=5.1", content.to_json)
|
|
217
|
+
|
|
218
|
+
JSON.parse(response.body)
|
|
219
|
+
end
|
|
220
|
+
|
|
195
221
|
def pull_request(pull_request_id)
|
|
196
222
|
response = get(source.api_endpoint +
|
|
197
223
|
source.organization + "/" + source.project +
|
|
@@ -217,6 +243,18 @@ module Dependabot
|
|
|
217
243
|
end
|
|
218
244
|
# rubocop:enable Metrics/ParameterLists
|
|
219
245
|
|
|
246
|
+
def compare(previous_tag, new_tag, type)
|
|
247
|
+
response = get(source.api_endpoint +
|
|
248
|
+
source.organization + "/" + source.project +
|
|
249
|
+
"/_apis/git/repositories/" + source.unscoped_repo +
|
|
250
|
+
"/commits?searchCriteria.itemVersion.versionType=#{type}" \
|
|
251
|
+
"&searchCriteria.itemVersion.version=#{previous_tag}" \
|
|
252
|
+
"&searchCriteria.compareVersion.versionType=#{type}" \
|
|
253
|
+
"&searchCriteria.compareVersion.version=#{new_tag}")
|
|
254
|
+
|
|
255
|
+
JSON.parse(response.body).fetch("value")
|
|
256
|
+
end
|
|
257
|
+
|
|
220
258
|
def get(url)
|
|
221
259
|
response = nil
|
|
222
260
|
|
|
@@ -279,6 +317,37 @@ module Dependabot
|
|
|
279
317
|
response
|
|
280
318
|
end
|
|
281
319
|
|
|
320
|
+
def patch(url, json)
|
|
321
|
+
response = nil
|
|
322
|
+
|
|
323
|
+
retry_connection_failures do
|
|
324
|
+
response = Excon.patch(
|
|
325
|
+
url,
|
|
326
|
+
body: json,
|
|
327
|
+
user: credentials&.fetch("username", nil),
|
|
328
|
+
password: credentials&.fetch("password", nil),
|
|
329
|
+
idempotent: true,
|
|
330
|
+
**SharedHelpers.excon_defaults(
|
|
331
|
+
headers: auth_header.merge(
|
|
332
|
+
{
|
|
333
|
+
"Content-Type" => "application/json"
|
|
334
|
+
}
|
|
335
|
+
)
|
|
336
|
+
)
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
raise InternalServerError if response.status == 500
|
|
340
|
+
raise BadGateway if response.status == 502
|
|
341
|
+
raise ServiceNotAvailable if response.status == 503
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
raise Unauthorized if response.status == 401
|
|
345
|
+
raise Forbidden if response.status == 403
|
|
346
|
+
raise NotFound if response.status == 404
|
|
347
|
+
|
|
348
|
+
response
|
|
349
|
+
end
|
|
350
|
+
|
|
282
351
|
private
|
|
283
352
|
|
|
284
353
|
def retry_connection_failures
|
|
@@ -171,6 +171,8 @@ module Dependabot
|
|
|
171
171
|
base_url = "https://api.bitbucket.org/2.0/user?fields=uuid"
|
|
172
172
|
response = get(base_url)
|
|
173
173
|
JSON.parse(response.body).fetch("uuid")
|
|
174
|
+
rescue Unauthorized
|
|
175
|
+
[nil]
|
|
174
176
|
end
|
|
175
177
|
|
|
176
178
|
def default_reviewers(repo)
|
|
@@ -205,7 +207,7 @@ module Dependabot
|
|
|
205
207
|
|
|
206
208
|
def get(url)
|
|
207
209
|
response = Excon.get(
|
|
208
|
-
url,
|
|
210
|
+
URI::DEFAULT_PARSER.escape(url),
|
|
209
211
|
user: credentials&.fetch("username", nil),
|
|
210
212
|
password: credentials&.fetch("password", nil),
|
|
211
213
|
# Setting to false to prevent Excon retries, use BitbucketWithRetries for retries.
|
|
@@ -89,6 +89,12 @@ module Dependabot
|
|
|
89
89
|
access_tokens << nil if access_tokens.empty?
|
|
90
90
|
access_tokens.uniq!
|
|
91
91
|
|
|
92
|
+
# Explicitly set the proxy if one is set in the environment
|
|
93
|
+
# as Faraday's find_proxy is very slow.
|
|
94
|
+
Octokit.configure do |c|
|
|
95
|
+
c.proxy = ENV["HTTPS_PROXY"] if ENV["HTTPS_PROXY"]
|
|
96
|
+
end
|
|
97
|
+
|
|
92
98
|
Octokit.middleware = Faraday::RackBuilder.new do |builder|
|
|
93
99
|
builder.use Faraday::Retry::Middleware, exceptions: RETRYABLE_ERRORS, max: max_retries || 3
|
|
94
100
|
|
|
@@ -40,7 +40,7 @@ module Dependabot
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
unless self.class.required_files_in?(fetched_files.map(&:name))
|
|
43
|
-
raise Dependabot::DependencyFileNotFound, self.class.required_files_message
|
|
43
|
+
raise Dependabot::DependencyFileNotFound.new(nil, self.class.required_files_message)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
fetched_files
|
|
@@ -32,16 +32,19 @@ module Dependabot
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def versions_by_type(dependency)
|
|
35
|
-
|
|
35
|
+
version = correct_version_for(dependency)
|
|
36
|
+
return [] unless version
|
|
37
|
+
|
|
38
|
+
semver = version.to_semver
|
|
36
39
|
|
|
37
40
|
transformed_update_types.flat_map do |t|
|
|
38
41
|
case t
|
|
39
42
|
when PATCH_VERSION_TYPE
|
|
40
|
-
ignore_patch(
|
|
43
|
+
ignore_patch(semver)
|
|
41
44
|
when MINOR_VERSION_TYPE
|
|
42
|
-
ignore_minor(
|
|
45
|
+
ignore_minor(semver)
|
|
43
46
|
when MAJOR_VERSION_TYPE
|
|
44
|
-
ignore_major(
|
|
47
|
+
ignore_major(semver)
|
|
45
48
|
else
|
|
46
49
|
[]
|
|
47
50
|
end
|
|
@@ -49,8 +52,6 @@ module Dependabot
|
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
def ignore_patch(version)
|
|
52
|
-
return [] unless rubygems_compatible?(version)
|
|
53
|
-
|
|
54
55
|
parts = version.split(".")
|
|
55
56
|
version_parts = parts.fill(0, parts.length...2)
|
|
56
57
|
upper_parts = version_parts.first(1) + [version_parts[1].to_i + 1]
|
|
@@ -61,8 +62,6 @@ module Dependabot
|
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
def ignore_minor(version)
|
|
64
|
-
return [] unless rubygems_compatible?(version)
|
|
65
|
-
|
|
66
65
|
parts = version.split(".")
|
|
67
66
|
version_parts = parts.fill(0, parts.length...2)
|
|
68
67
|
lower_parts = version_parts.first(1) + [version_parts[1].to_i + 1] + ["a"]
|
|
@@ -74,8 +73,6 @@ module Dependabot
|
|
|
74
73
|
end
|
|
75
74
|
|
|
76
75
|
def ignore_major(version)
|
|
77
|
-
return [] unless rubygems_compatible?(version)
|
|
78
|
-
|
|
79
76
|
version_parts = version.split(".")
|
|
80
77
|
lower_parts = [version_parts[0].to_i + 1] + ["a"]
|
|
81
78
|
lower_bound = ">= #{lower_parts.join('.')}"
|
|
@@ -83,10 +80,20 @@ module Dependabot
|
|
|
83
80
|
[lower_bound]
|
|
84
81
|
end
|
|
85
82
|
|
|
86
|
-
def
|
|
87
|
-
|
|
83
|
+
def correct_version_for(dependency)
|
|
84
|
+
version = dependency.version
|
|
85
|
+
return if version.nil? || version.empty?
|
|
86
|
+
|
|
87
|
+
version_class = version_class_for(dependency.package_manager)
|
|
88
|
+
return unless version_class.correct?(version)
|
|
89
|
+
|
|
90
|
+
version_class.new(version)
|
|
91
|
+
end
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
def version_class_for(package_manager)
|
|
94
|
+
Utils.version_class_for_package_manager(package_manager)
|
|
95
|
+
rescue StandardError
|
|
96
|
+
Dependabot::Version
|
|
90
97
|
end
|
|
91
98
|
end
|
|
92
99
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "dependabot/version"
|
|
4
4
|
|
|
5
5
|
module Dependabot
|
|
6
6
|
class Dependency
|
|
@@ -110,6 +110,67 @@ module Dependabot
|
|
|
110
110
|
display_name_builder.call(name)
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
+
def humanized_previous_version
|
|
114
|
+
# If we don't have a previous version, we *may* still be able to figure
|
|
115
|
+
# one out if a ref was provided and has been changed (in which case the
|
|
116
|
+
# previous ref was essentially the version).
|
|
117
|
+
if previous_version.nil?
|
|
118
|
+
return ref_changed? ? previous_ref : nil
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if previous_version.match?(/^[0-9a-f]{40}/)
|
|
122
|
+
return previous_ref if ref_changed? && previous_ref
|
|
123
|
+
|
|
124
|
+
"`#{previous_version[0..6]}`"
|
|
125
|
+
elsif version == previous_version &&
|
|
126
|
+
package_manager == "docker"
|
|
127
|
+
digest = docker_digest_from_reqs(previous_requirements)
|
|
128
|
+
"`#{digest.split(':').last[0..6]}`"
|
|
129
|
+
else
|
|
130
|
+
previous_version
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def humanized_version
|
|
135
|
+
return if removed?
|
|
136
|
+
|
|
137
|
+
if version.match?(/^[0-9a-f]{40}/)
|
|
138
|
+
return new_ref if ref_changed? && new_ref
|
|
139
|
+
|
|
140
|
+
"`#{version[0..6]}`"
|
|
141
|
+
elsif version == previous_version &&
|
|
142
|
+
package_manager == "docker"
|
|
143
|
+
digest = docker_digest_from_reqs(requirements)
|
|
144
|
+
"`#{digest.split(':').last[0..6]}`"
|
|
145
|
+
else
|
|
146
|
+
version
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def docker_digest_from_reqs(requirements)
|
|
151
|
+
requirements.
|
|
152
|
+
filter_map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) }.
|
|
153
|
+
first
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def previous_ref
|
|
157
|
+
previous_refs = previous_requirements.filter_map do |r|
|
|
158
|
+
r.dig(:source, "ref") || r.dig(:source, :ref)
|
|
159
|
+
end.uniq
|
|
160
|
+
return previous_refs.first if previous_refs.count == 1
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def new_ref
|
|
164
|
+
new_refs = requirements.filter_map do |r|
|
|
165
|
+
r.dig(:source, "ref") || r.dig(:source, :ref)
|
|
166
|
+
end.uniq
|
|
167
|
+
return new_refs.first if new_refs.count == 1
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def ref_changed?
|
|
171
|
+
previous_ref != new_ref
|
|
172
|
+
end
|
|
173
|
+
|
|
113
174
|
# Returns all detected versions of the dependency. Only ecosystems that
|
|
114
175
|
# support this feature will return more than the current version.
|
|
115
176
|
def all_versions
|
|
@@ -135,7 +196,7 @@ module Dependabot
|
|
|
135
196
|
end
|
|
136
197
|
|
|
137
198
|
def eql?(other)
|
|
138
|
-
self
|
|
199
|
+
self == other
|
|
139
200
|
end
|
|
140
201
|
|
|
141
202
|
private
|
data/lib/dependabot/errors.rb
CHANGED
|
@@ -95,11 +95,17 @@ module Dependabot
|
|
|
95
95
|
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
|
|
96
96
|
if e.message.include?("fatal: Remote branch #{target_branch} not found in upstream origin")
|
|
97
97
|
raise Dependabot::BranchNotFound, target_branch
|
|
98
|
+
elsif e.message.include?("No space left on device")
|
|
99
|
+
raise Dependabot::OutOfDisk
|
|
98
100
|
end
|
|
99
101
|
|
|
100
102
|
raise Dependabot::RepoNotFound, source
|
|
101
103
|
end
|
|
102
104
|
|
|
105
|
+
def package_manager_version
|
|
106
|
+
nil
|
|
107
|
+
end
|
|
108
|
+
|
|
103
109
|
private
|
|
104
110
|
|
|
105
111
|
def fetch_file_if_present(filename, fetch_submodules: false)
|
|
@@ -498,7 +504,7 @@ module Dependabot
|
|
|
498
504
|
_fetch_file_content_from_github(path, repo, commit)
|
|
499
505
|
when "gitlab"
|
|
500
506
|
tmp = gitlab_client.get_file(repo, path, commit).content
|
|
501
|
-
|
|
507
|
+
decode_binary_string(tmp)
|
|
502
508
|
when "azure"
|
|
503
509
|
azure_client.fetch_file_contents(commit, path)
|
|
504
510
|
when "bitbucket"
|
|
@@ -534,7 +540,7 @@ module Dependabot
|
|
|
534
540
|
# see https://github.blog/changelog/2022-05-03-increased-file-size-limit-when-retrieving-file-contents-via-rest-api/
|
|
535
541
|
github_client.contents(repo, path: path, ref: commit, accept: "application/vnd.github.v3.raw")
|
|
536
542
|
else
|
|
537
|
-
|
|
543
|
+
decode_binary_string(tmp.content)
|
|
538
544
|
end
|
|
539
545
|
rescue Octokit::Forbidden => e
|
|
540
546
|
raise unless e.message.include?("too_large")
|
|
@@ -549,7 +555,7 @@ module Dependabot
|
|
|
549
555
|
tmp = github_client.blob(repo, file_details.sha)
|
|
550
556
|
return tmp.content if tmp.encoding == "utf-8"
|
|
551
557
|
|
|
552
|
-
|
|
558
|
+
decode_binary_string(tmp.content)
|
|
553
559
|
end
|
|
554
560
|
# rubocop:enable Metrics/AbcSize
|
|
555
561
|
|
|
@@ -607,7 +613,7 @@ module Dependabot
|
|
|
607
613
|
CMD
|
|
608
614
|
)
|
|
609
615
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
|
610
|
-
raise unless GIT_SUBMODULE_ERROR_REGEX && e.message.downcase.include?("submodule")
|
|
616
|
+
raise unless e.message.match(GIT_SUBMODULE_ERROR_REGEX) && e.message.downcase.include?("submodule")
|
|
611
617
|
|
|
612
618
|
submodule_cloning_failed = true
|
|
613
619
|
match = e.message.match(GIT_SUBMODULE_ERROR_REGEX)
|
|
@@ -652,6 +658,11 @@ module Dependabot
|
|
|
652
658
|
# rubocop:enable Metrics/MethodLength
|
|
653
659
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
654
660
|
# rubocop:enable Metrics/BlockLength
|
|
661
|
+
|
|
662
|
+
def decode_binary_string(str)
|
|
663
|
+
bom = (+"\xEF\xBB\xBF").force_encoding(Encoding::BINARY)
|
|
664
|
+
Base64.decode64(str).delete_prefix(bom).force_encoding("UTF-8").encode
|
|
665
|
+
end
|
|
655
666
|
end
|
|
656
667
|
end
|
|
657
668
|
end
|
|
@@ -117,19 +117,10 @@ module Dependabot
|
|
|
117
117
|
|
|
118
118
|
# Produces a new dependency by merging the attributes of `old_dep` with those of
|
|
119
119
|
# `new_dep`. Requirements and subdependency metadata will be combined and deduped.
|
|
120
|
-
# The version of the combined dependency is determined by the
|
|
120
|
+
# The version of the combined dependency is determined by the
|
|
121
|
+
# `#combined_version` method below.
|
|
121
122
|
def combined_dependency(old_dep, new_dep)
|
|
122
|
-
version =
|
|
123
|
-
old_dep.version || new_dep.version
|
|
124
|
-
elsif !version_class.correct?(new_dep.version)
|
|
125
|
-
old_dep.version
|
|
126
|
-
elsif !version_class.correct?(old_dep.version)
|
|
127
|
-
new_dep.version
|
|
128
|
-
elsif version_class.new(new_dep.version) > version_class.new(old_dep.version)
|
|
129
|
-
old_dep.version
|
|
130
|
-
else
|
|
131
|
-
new_dep.version
|
|
132
|
-
end
|
|
123
|
+
version = combined_version(old_dep, new_dep)
|
|
133
124
|
requirements = (old_dep.requirements + new_dep.requirements).uniq
|
|
134
125
|
subdependency_metadata = (
|
|
135
126
|
(old_dep.subdependency_metadata || []) +
|
|
@@ -145,6 +136,22 @@ module Dependabot
|
|
|
145
136
|
)
|
|
146
137
|
end
|
|
147
138
|
|
|
139
|
+
def combined_version(old_dep, new_dep)
|
|
140
|
+
if old_dep.version.nil? ^ new_dep.version.nil?
|
|
141
|
+
[old_dep, new_dep].find(&:version).version
|
|
142
|
+
elsif old_dep.top_level? ^ new_dep.top_level? # Prefer a direct dependency over a transitive one
|
|
143
|
+
[old_dep, new_dep].find(&:top_level?).version
|
|
144
|
+
elsif !version_class.correct?(new_dep.version)
|
|
145
|
+
old_dep.version
|
|
146
|
+
elsif !version_class.correct?(old_dep.version)
|
|
147
|
+
new_dep.version
|
|
148
|
+
elsif version_class.new(new_dep.version) > version_class.new(old_dep.version)
|
|
149
|
+
old_dep.version
|
|
150
|
+
else
|
|
151
|
+
new_dep.version
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
148
155
|
def version_class
|
|
149
156
|
@version_class ||= Utils.version_class_for_package_manager(@combined.package_manager)
|
|
150
157
|
end
|
|
@@ -106,7 +106,7 @@ module Dependabot
|
|
|
106
106
|
|
|
107
107
|
def fetch_raw_upload_pack_with_git_for(uri)
|
|
108
108
|
service_pack_uri = uri
|
|
109
|
-
service_pack_uri += ".git" unless service_pack_uri.end_with?(".git")
|
|
109
|
+
service_pack_uri += ".git" unless service_pack_uri.end_with?(".git") || skip_git_suffix(uri)
|
|
110
110
|
|
|
111
111
|
env = { "PATH" => ENV.fetch("PATH", nil) }
|
|
112
112
|
command = "git ls-remote #{service_pack_uri}"
|
|
@@ -158,40 +158,45 @@ module Dependabot
|
|
|
158
158
|
def service_pack_uri(uri)
|
|
159
159
|
service_pack_uri = uri_with_auth(uri)
|
|
160
160
|
service_pack_uri = service_pack_uri.gsub(%r{/$}, "")
|
|
161
|
-
service_pack_uri += ".git" unless service_pack_uri.end_with?(".git")
|
|
161
|
+
service_pack_uri += ".git" unless service_pack_uri.end_with?(".git") || skip_git_suffix(uri)
|
|
162
162
|
service_pack_uri + "/info/refs?service=git-upload-pack"
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
+
def skip_git_suffix(uri)
|
|
166
|
+
# TODO: Unlike the other providers (GitHub, GitLab, BitBucket), as of 2023-01-18 Azure DevOps does not support the
|
|
167
|
+
# ".git" suffix. It will return a 404.
|
|
168
|
+
# So skip adding ".git" if looks like an ADO URI.
|
|
169
|
+
# There's no access to the source object here, so have to check the URI instead.
|
|
170
|
+
# Even if we had the current source object, the URI may be for a dependency hosted elsewhere.
|
|
171
|
+
# Unfortunately as a consequence, urls pointing to Azure DevOps Server will not work.
|
|
172
|
+
# Only alternative is to remove the addition of ".git" suffix since the other providers
|
|
173
|
+
# (GitHub, GitLab, BitBucket) work with or without the suffix.
|
|
174
|
+
# That change has other ramifications, so it'd be better if Azure started supporting ".git"
|
|
175
|
+
# like all the other providers.
|
|
176
|
+
uri = "https://#{uri.split('git@').last.sub(%r{:/?}, '/')}" if uri.start_with?("git@")
|
|
177
|
+
uri = URI(uri)
|
|
178
|
+
hostname = uri.hostname.to_s
|
|
179
|
+
hostname == "dev.azure.com" || hostname.end_with?(".visualstudio.com")
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Add in username and password if present in credentials.
|
|
183
|
+
# Credentials are never present for production Dependabot.
|
|
165
184
|
def uri_with_auth(uri)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
uri.sub(%r{.*?://}, "")
|
|
170
|
-
end
|
|
185
|
+
# Handle SCP-style git URIs
|
|
186
|
+
uri = "https://#{uri.split('git@').last.sub(%r{:/?}, '/')}" if uri.start_with?("git@")
|
|
187
|
+
uri = URI(uri)
|
|
171
188
|
cred = credentials.select { |c| c["type"] == "git_source" }.
|
|
172
|
-
find { |c|
|
|
189
|
+
find { |c| uri.host == c["host"] }
|
|
173
190
|
|
|
174
|
-
scheme =
|
|
191
|
+
uri.scheme = "https" if uri.scheme != "http"
|
|
175
192
|
|
|
176
|
-
if
|
|
177
|
-
# URI already has authentication details
|
|
178
|
-
"#{scheme}://#{bare_uri}"
|
|
179
|
-
elsif cred&.fetch("username", nil) && cred&.fetch("password", nil)
|
|
193
|
+
if !uri.password && cred&.fetch("username", nil) && cred&.fetch("password", nil)
|
|
180
194
|
# URI doesn't have authentication details, but we have credentials
|
|
181
|
-
|
|
182
|
-
"
|
|
183
|
-
else
|
|
184
|
-
# No credentials, so just return the http(s) URI
|
|
185
|
-
"#{scheme}://#{bare_uri}"
|
|
195
|
+
uri.user = URI.encode_www_form_component(cred["username"])
|
|
196
|
+
uri.password = URI.encode_www_form_component(cred["password"])
|
|
186
197
|
end
|
|
187
|
-
end
|
|
188
198
|
|
|
189
|
-
|
|
190
|
-
if uri.match?(%r{^http://})
|
|
191
|
-
"http"
|
|
192
|
-
else
|
|
193
|
-
"https"
|
|
194
|
-
end
|
|
199
|
+
uri.to_s
|
|
195
200
|
end
|
|
196
201
|
|
|
197
202
|
def sha_for_update_pack_line(line)
|
|
@@ -45,7 +45,7 @@ and implement the following methods:
|
|
|
45
45
|
|
|
46
46
|
| Method | Description |
|
|
47
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
|
|
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 available from parsing the dependency file. |
|
|
49
49
|
|
|
50
50
|
To ensure the above are implemented, you should include
|
|
51
51
|
`it_behaves_like "a dependency metadata finder"` in your specs for the new
|
|
@@ -82,11 +82,12 @@ module Dependabot
|
|
|
82
82
|
return unless suggested_changelog_url
|
|
83
83
|
|
|
84
84
|
# TODO: Support other providers
|
|
85
|
-
|
|
86
|
-
return unless
|
|
85
|
+
suggested_source = Source.from_url(suggested_changelog_url)
|
|
86
|
+
return unless suggested_source&.provider == "github"
|
|
87
87
|
|
|
88
|
-
opts = { path:
|
|
89
|
-
|
|
88
|
+
opts = { path: suggested_source.directory, ref: suggested_source.branch }.compact
|
|
89
|
+
suggested_source_client = github_client_for_source(suggested_source)
|
|
90
|
+
tmp_files = suggested_source_client.contents(suggested_source.repo, opts)
|
|
90
91
|
|
|
91
92
|
filename = suggested_changelog_url.split("/").last.split("#").first
|
|
92
93
|
@changelog_from_suggested_url =
|
|
@@ -161,12 +162,13 @@ module Dependabot
|
|
|
161
162
|
@file_text ||= {}
|
|
162
163
|
|
|
163
164
|
unless @file_text.key?(file.download_url)
|
|
164
|
-
|
|
165
|
+
file_source = Source.from_url(file.html_url)
|
|
165
166
|
@file_text[file.download_url] =
|
|
166
|
-
case provider
|
|
167
|
-
when "github" then fetch_github_file(file)
|
|
167
|
+
case file_source.provider
|
|
168
|
+
when "github" then fetch_github_file(file_source, file)
|
|
168
169
|
when "gitlab" then fetch_gitlab_file(file)
|
|
169
170
|
when "bitbucket" then fetch_bitbucket_file(file)
|
|
171
|
+
when "azure" then fetch_azure_file(file)
|
|
170
172
|
when "codecommit" then nil # TODO: git file from codecommit
|
|
171
173
|
else raise "Unsupported provider '#{provider}'"
|
|
172
174
|
end
|
|
@@ -177,9 +179,9 @@ module Dependabot
|
|
|
177
179
|
@file_text[file.download_url].sub(/\n*\z/, "")
|
|
178
180
|
end
|
|
179
181
|
|
|
180
|
-
def fetch_github_file(file)
|
|
182
|
+
def fetch_github_file(file_source, file)
|
|
181
183
|
# Hitting the download URL directly causes encoding problems
|
|
182
|
-
raw_content =
|
|
184
|
+
raw_content = github_client_for_source(file_source).get(file.url).content
|
|
183
185
|
Base64.decode64(raw_content).force_encoding("UTF-8").encode
|
|
184
186
|
end
|
|
185
187
|
|
|
@@ -196,6 +198,11 @@ module Dependabot
|
|
|
196
198
|
force_encoding("UTF-8").encode
|
|
197
199
|
end
|
|
198
200
|
|
|
201
|
+
def fetch_azure_file(file)
|
|
202
|
+
azure_client.get(file.download_url).body.
|
|
203
|
+
force_encoding("UTF-8").encode
|
|
204
|
+
end
|
|
205
|
+
|
|
199
206
|
def upgrade_guide
|
|
200
207
|
return unless source
|
|
201
208
|
|
|
@@ -220,7 +227,7 @@ module Dependabot
|
|
|
220
227
|
when "github" then fetch_github_file_list(ref)
|
|
221
228
|
when "bitbucket" then fetch_bitbucket_file_list
|
|
222
229
|
when "gitlab" then fetch_gitlab_file_list
|
|
223
|
-
when "azure" then
|
|
230
|
+
when "azure" then fetch_azure_file_list
|
|
224
231
|
when "codecommit" then [] # TODO: Fetch Files from Codecommit
|
|
225
232
|
else raise "Unexpected repo provider '#{source.provider}'"
|
|
226
233
|
end
|
|
@@ -292,6 +299,29 @@ module Dependabot
|
|
|
292
299
|
[]
|
|
293
300
|
end
|
|
294
301
|
|
|
302
|
+
def fetch_azure_file_list
|
|
303
|
+
azure_client.fetch_repo_contents.map do |entry|
|
|
304
|
+
type = case entry.fetch("gitObjectType")
|
|
305
|
+
when "blob" then "file"
|
|
306
|
+
when "tree" then "dir"
|
|
307
|
+
else entry.fetch("gitObjectType")
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
OpenStruct.new(
|
|
311
|
+
name: File.basename(entry.fetch("relativePath")),
|
|
312
|
+
type: type,
|
|
313
|
+
size: entry.fetch("size"),
|
|
314
|
+
path: entry.fetch("relativePath"),
|
|
315
|
+
html_url: "#{source.url}?path=/#{entry.fetch('relativePath')}",
|
|
316
|
+
download_url: entry.fetch("url")
|
|
317
|
+
)
|
|
318
|
+
end
|
|
319
|
+
rescue Dependabot::Clients::Azure::NotFound,
|
|
320
|
+
Dependabot::Clients::Azure::Unauthorized,
|
|
321
|
+
Dependabot::Clients::Azure::Forbidden
|
|
322
|
+
[]
|
|
323
|
+
end
|
|
324
|
+
|
|
295
325
|
def new_version
|
|
296
326
|
return @new_version if defined?(@new_version)
|
|
297
327
|
|
|
@@ -346,7 +376,19 @@ module Dependabot
|
|
|
346
376
|
|
|
347
377
|
def github_client
|
|
348
378
|
@github_client ||= Dependabot::Clients::GithubWithRetries.
|
|
349
|
-
|
|
379
|
+
for_source(source: source, credentials: credentials)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def azure_client
|
|
383
|
+
@azure_client ||= Dependabot::Clients::Azure.
|
|
384
|
+
for_source(source: source, credentials: credentials)
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def github_client_for_source(client_source)
|
|
388
|
+
return github_client if client_source == source
|
|
389
|
+
|
|
390
|
+
Dependabot::Clients::GithubWithRetries.
|
|
391
|
+
for_source(source: client_source, credentials: credentials)
|
|
350
392
|
end
|
|
351
393
|
|
|
352
394
|
def bitbucket_client
|