dependabot-gradle 0.344.1 → 0.346.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/gradle/distributions.rb +20 -0
- data/lib/dependabot/gradle/file_fetcher.rb +27 -0
- data/lib/dependabot/gradle/file_parser/distributions_finder.rb +90 -0
- data/lib/dependabot/gradle/file_parser.rb +22 -0
- data/lib/dependabot/gradle/file_updater/wrapper_updater.rb +161 -0
- data/lib/dependabot/gradle/file_updater.rb +35 -11
- data/lib/dependabot/gradle/metadata_finder.rb +3 -0
- data/lib/dependabot/gradle/package/distributions_fetcher.rb +67 -0
- data/lib/dependabot/gradle/package/package_details_fetcher.rb +40 -2
- data/lib/dependabot/gradle/update_checker/requirements_updater.rb +36 -0
- metadata +10 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c0e7bd82eab187986339ffedc9f8373d0b14bd54d89fdb1753814532baf8f0e5
|
|
4
|
+
data.tar.gz: 22e4355175c077fb3a95461d5f8e4970ec3c095a43db830caf368fe1f64ace6d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 015aead61df769d95c51d9f23b2383f6bca808335de15c2a2531af3d3b9e4eb53fe7887244ec576e64ece0fc304d095659f418c4b2227df39cbca96c713bd2cc
|
|
7
|
+
data.tar.gz: de0365699f56cc9be2fcbf043b447922bbd64c8d7df95095dc4f6d7fd8bcff5c11c10db0aa0fc8273881d75d4d6231e89acb30728c709fc3e97a75be1f557d11
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Dependabot
|
|
5
|
+
module Gradle
|
|
6
|
+
module Distributions
|
|
7
|
+
extend T::Sig
|
|
8
|
+
|
|
9
|
+
DISTRIBUTION_REPOSITORY_URL = "https://services.gradle.org"
|
|
10
|
+
DISTRIBUTION_DEPENDENCY_TYPE = "gradle-distribution"
|
|
11
|
+
|
|
12
|
+
sig { params(requirements: T::Array[T::Hash[Symbol, T.untyped]]).returns(T::Boolean) }
|
|
13
|
+
def self.distribution_requirements?(requirements)
|
|
14
|
+
requirements.any? do |req|
|
|
15
|
+
req.dig(:source, :type) == DISTRIBUTION_DEPENDENCY_TYPE
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -24,6 +24,13 @@ module Dependabot
|
|
|
24
24
|
SUPPORTED_SETTINGS_FILE_NAMES =
|
|
25
25
|
T.let(%w(settings.gradle settings.gradle.kts).freeze, T::Array[String])
|
|
26
26
|
|
|
27
|
+
SUPPORTED_WRAPPER_FILES_PATH = %w(
|
|
28
|
+
gradlew
|
|
29
|
+
gradlew.bat
|
|
30
|
+
gradle/wrapper/gradle-wrapper.jar
|
|
31
|
+
gradle/wrapper/gradle-wrapper.properties
|
|
32
|
+
).freeze
|
|
33
|
+
|
|
27
34
|
# For now Gradle only supports library .toml files in the main gradle folder
|
|
28
35
|
SUPPORTED_VERSION_CATALOG_FILE_PATH =
|
|
29
36
|
T.let(%w(/gradle/libs.versions.toml).freeze, T::Array[String])
|
|
@@ -76,6 +83,7 @@ module Dependabot
|
|
|
76
83
|
def all_buildfiles_in_build(root_dir)
|
|
77
84
|
files = [buildfile(root_dir), settings_file(root_dir), version_catalog_file(root_dir), lockfile(root_dir)]
|
|
78
85
|
.compact
|
|
86
|
+
files += wrapper_files(root_dir)
|
|
79
87
|
files += subproject_buildfiles(root_dir)
|
|
80
88
|
files += subproject_lockfiles(root_dir)
|
|
81
89
|
files += dependency_script_plugins(root_dir)
|
|
@@ -172,6 +180,25 @@ module Dependabot
|
|
|
172
180
|
end
|
|
173
181
|
end
|
|
174
182
|
|
|
183
|
+
sig { params(dir: String).returns(T::Array[DependencyFile]) }
|
|
184
|
+
def wrapper_files(dir)
|
|
185
|
+
return [] unless Experiments.enabled?(:gradle_wrapper_updater)
|
|
186
|
+
|
|
187
|
+
SUPPORTED_WRAPPER_FILES_PATH.filter_map do |filename|
|
|
188
|
+
file = fetch_file_if_present(File.join(dir, filename))
|
|
189
|
+
next unless file
|
|
190
|
+
|
|
191
|
+
if file.name.end_with?(".jar")
|
|
192
|
+
file.content = Base64.encode64(T.must(file.content)) if file.content
|
|
193
|
+
file.content_encoding = DependencyFile::ContentEncoding::BASE64
|
|
194
|
+
end
|
|
195
|
+
file
|
|
196
|
+
rescue Dependabot::DependencyFileNotFound
|
|
197
|
+
# Gradle itself doesn't worry about missing subprojects, so we don't
|
|
198
|
+
nil
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
175
202
|
sig { params(root_dir: String).returns(T.nilable(DependencyFile)) }
|
|
176
203
|
def version_catalog_file(root_dir)
|
|
177
204
|
return nil unless root_dir == "."
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "dependabot/gradle/file_parser"
|
|
5
|
+
require "dependabot/gradle/distributions"
|
|
6
|
+
require "sorbet-runtime"
|
|
7
|
+
|
|
8
|
+
module Dependabot
|
|
9
|
+
module Gradle
|
|
10
|
+
class FileParser
|
|
11
|
+
class DistributionsFinder
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
DISTRIBUTION_URL_REGEX =
|
|
15
|
+
/.*?(?<version>(\d+(?:\.\d+){1,3}(?:-(?!bin|all)\w++)*(?:\+\w++)*))(?:-bin|-all)?.*?/
|
|
16
|
+
|
|
17
|
+
sig { params(properties_file: DependencyFile).returns(T.nilable(Dependency)) }
|
|
18
|
+
def self.resolve_dependency(properties_file) # rubocop:disable Metrics/MethodLength
|
|
19
|
+
content = properties_file.content
|
|
20
|
+
return nil unless content
|
|
21
|
+
|
|
22
|
+
distribution_url, checksum = load_properties(content)
|
|
23
|
+
match = distribution_url&.match(DISTRIBUTION_URL_REGEX)&.named_captures
|
|
24
|
+
return nil unless match
|
|
25
|
+
|
|
26
|
+
version = match.fetch("version")
|
|
27
|
+
|
|
28
|
+
requirements = T.let(
|
|
29
|
+
[{
|
|
30
|
+
requirement: version,
|
|
31
|
+
file: properties_file.name,
|
|
32
|
+
source: {
|
|
33
|
+
type: Distributions::DISTRIBUTION_DEPENDENCY_TYPE,
|
|
34
|
+
url: distribution_url,
|
|
35
|
+
property: "distributionUrl"
|
|
36
|
+
},
|
|
37
|
+
groups: []
|
|
38
|
+
}],
|
|
39
|
+
T::Array[T::Hash[Symbol, T.untyped]]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if checksum
|
|
43
|
+
requirements << {
|
|
44
|
+
requirement: checksum,
|
|
45
|
+
file: properties_file.name,
|
|
46
|
+
source: {
|
|
47
|
+
type: Distributions::DISTRIBUTION_DEPENDENCY_TYPE,
|
|
48
|
+
url: "#{distribution_url}.sha256",
|
|
49
|
+
property: "distributionSha256Sum"
|
|
50
|
+
},
|
|
51
|
+
groups: []
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Dependency.new(
|
|
56
|
+
name: "gradle-wrapper",
|
|
57
|
+
version: version,
|
|
58
|
+
requirements: requirements,
|
|
59
|
+
package_manager: "gradle"
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
sig { params(properties_content: String).returns(T::Array[T.nilable(String)]) }
|
|
64
|
+
def self.load_properties(properties_content)
|
|
65
|
+
distribution_url = T.let(nil, T.nilable(String))
|
|
66
|
+
checksum = T.let(nil, T.nilable(String))
|
|
67
|
+
|
|
68
|
+
properties_content.lines.each do |line|
|
|
69
|
+
(key, value) = line.split("=", 2).map(&:strip)
|
|
70
|
+
next unless key && value
|
|
71
|
+
|
|
72
|
+
case key
|
|
73
|
+
when "distributionUrl"
|
|
74
|
+
distribution_url = value.gsub("\\:", ":")
|
|
75
|
+
when "distributionSha256Sum"
|
|
76
|
+
checksum = value
|
|
77
|
+
else
|
|
78
|
+
next
|
|
79
|
+
end
|
|
80
|
+
break if distribution_url && checksum
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
[distribution_url, checksum]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private_class_method :load_properties
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -25,6 +25,7 @@ module Dependabot
|
|
|
25
25
|
extend T::Sig
|
|
26
26
|
|
|
27
27
|
require "dependabot/file_parsers/base/dependency_set"
|
|
28
|
+
require_relative "file_parser/distributions_finder"
|
|
28
29
|
require_relative "file_parser/property_value_finder"
|
|
29
30
|
|
|
30
31
|
SUPPORTED_BUILD_FILE_NAMES = T.let(
|
|
@@ -59,6 +60,11 @@ module Dependabot
|
|
|
59
60
|
script_plugin_files.each do |plugin_file|
|
|
60
61
|
dependency_set += buildfile_dependencies(plugin_file)
|
|
61
62
|
end
|
|
63
|
+
if Experiments.enabled?(:gradle_wrapper_updater)
|
|
64
|
+
wrapper_properties_file.each do |properties_file|
|
|
65
|
+
dependency_set += wrapper_properties_dependencies(properties_file)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
62
68
|
version_catalog_file.each do |toml_file|
|
|
63
69
|
dependency_set += version_catalog_dependencies(toml_file)
|
|
64
70
|
end
|
|
@@ -119,6 +125,14 @@ module Dependabot
|
|
|
119
125
|
)
|
|
120
126
|
end
|
|
121
127
|
|
|
128
|
+
sig { params(properties_file: Dependabot::DependencyFile).returns(DependencySet) }
|
|
129
|
+
def wrapper_properties_dependencies(properties_file)
|
|
130
|
+
dependency_set = DependencySet.new
|
|
131
|
+
dependency = DistributionsFinder.resolve_dependency(properties_file)
|
|
132
|
+
dependency_set << dependency if dependency
|
|
133
|
+
dependency_set
|
|
134
|
+
end
|
|
135
|
+
|
|
122
136
|
sig { params(toml_file: Dependabot::DependencyFile).returns(DependencySet) }
|
|
123
137
|
def version_catalog_dependencies(toml_file)
|
|
124
138
|
dependency_set = DependencySet.new
|
|
@@ -544,6 +558,14 @@ module Dependabot
|
|
|
544
558
|
)
|
|
545
559
|
end
|
|
546
560
|
|
|
561
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
562
|
+
def wrapper_properties_file
|
|
563
|
+
@wrapper_properties_file ||= T.let(
|
|
564
|
+
dependency_files.select { |f| f.name.end_with?("gradle-wrapper.properties") },
|
|
565
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
|
566
|
+
)
|
|
567
|
+
end
|
|
568
|
+
|
|
547
569
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
548
570
|
def version_catalog_file
|
|
549
571
|
@version_catalog_file ||= T.let(
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
require "shellwords"
|
|
6
|
+
|
|
7
|
+
require "dependabot/gradle/distributions"
|
|
8
|
+
|
|
9
|
+
module Dependabot
|
|
10
|
+
module Gradle
|
|
11
|
+
class FileUpdater
|
|
12
|
+
class WrapperUpdater
|
|
13
|
+
extend T::Sig
|
|
14
|
+
include Dependabot::Gradle::Distributions
|
|
15
|
+
|
|
16
|
+
sig { params(dependency_files: T::Array[Dependabot::DependencyFile], dependency: Dependabot::Dependency).void }
|
|
17
|
+
def initialize(dependency_files:, dependency:)
|
|
18
|
+
@dependency_files = dependency_files
|
|
19
|
+
@dependency = dependency
|
|
20
|
+
@target_files = T.let(
|
|
21
|
+
%w(
|
|
22
|
+
/gradlew
|
|
23
|
+
/gradlew.bat
|
|
24
|
+
/gradle/wrapper/gradle-wrapper.properties
|
|
25
|
+
/gradle/wrapper/gradle-wrapper.jar
|
|
26
|
+
),
|
|
27
|
+
T::Array[String]
|
|
28
|
+
)
|
|
29
|
+
@build_files = T.let(
|
|
30
|
+
%w(
|
|
31
|
+
build.gradle
|
|
32
|
+
build.gradle.kts
|
|
33
|
+
settings.gradle
|
|
34
|
+
settings.gradle.kts
|
|
35
|
+
),
|
|
36
|
+
T::Array[String]
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
sig { params(build_file: Dependabot::DependencyFile).returns(T::Array[Dependabot::DependencyFile]) }
|
|
41
|
+
def update_files(build_file)
|
|
42
|
+
local_files = dependency_files.select do |file|
|
|
43
|
+
file.directory == build_file.directory && target_file?(file)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# If we don't have any files in the build files don't generate one
|
|
47
|
+
return dependency_files unless local_files.any?
|
|
48
|
+
|
|
49
|
+
updated_files = dependency_files.dup
|
|
50
|
+
SharedHelpers.in_a_temporary_directory do |temp_dir|
|
|
51
|
+
populate_temp_directory(temp_dir)
|
|
52
|
+
cwd = File.join(temp_dir, base_path(build_file))
|
|
53
|
+
|
|
54
|
+
# Create gradle.properties file with proxy settings
|
|
55
|
+
# Would prefer to use command line arguments, but they don't work.
|
|
56
|
+
properties_filename = File.join(temp_dir, build_file.directory, "gradle.properties")
|
|
57
|
+
write_properties_file(properties_filename)
|
|
58
|
+
|
|
59
|
+
command_parts = %w(gradle --no-daemon --stacktrace) + command_args
|
|
60
|
+
command = Shellwords.join(command_parts)
|
|
61
|
+
|
|
62
|
+
Dir.chdir(cwd) do
|
|
63
|
+
SharedHelpers.run_shell_command(command, cwd: cwd)
|
|
64
|
+
update_files_content(temp_dir, local_files, updated_files)
|
|
65
|
+
rescue SharedHelpers::HelperSubprocessFailed => e
|
|
66
|
+
puts "Failed to update files: #{e.message}"
|
|
67
|
+
return updated_files
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
updated_files
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Boolean) }
|
|
76
|
+
def target_file?(file)
|
|
77
|
+
@target_files.any? { |r| "/#{file.name}".end_with?(r) }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
sig { returns(T::Array[String]) }
|
|
81
|
+
def command_args
|
|
82
|
+
version = T.let(dependency.requirements[0]&.[](:requirement), String)
|
|
83
|
+
checksum = T.let(dependency.requirements[1]&.[](:requirement), String) if dependency.requirements.size > 1
|
|
84
|
+
|
|
85
|
+
args = %W(wrapper --no-validate-url --gradle-version #{version})
|
|
86
|
+
args += %W(--gradle-distribution-sha256-sum #{checksum}) if checksum
|
|
87
|
+
args
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Gradle builds can be complex, to maximize the chances of a successful we just keep related wrapper files
|
|
91
|
+
# and produce a minimal build for it to run (losing any customisations of the `wrapper` task in the process)
|
|
92
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
93
|
+
def files_to_populate
|
|
94
|
+
@dependency_files.filter_map do |f|
|
|
95
|
+
next f if target_file?(f)
|
|
96
|
+
next Dependabot::DependencyFile.new(directory: f.directory, name: f.name, content: "") if build_file?(f)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Boolean) }
|
|
101
|
+
def build_file?(file)
|
|
102
|
+
@build_files.include?(File.basename(file.name))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
sig { params(build_file: Dependabot::DependencyFile).returns(String) }
|
|
106
|
+
def base_path(build_file)
|
|
107
|
+
File.dirname(File.join(build_file.directory, build_file.name)).delete_suffix("/gradle/wrapper")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
sig do
|
|
111
|
+
params(
|
|
112
|
+
temp_dir: T.any(Pathname, String),
|
|
113
|
+
local_files: T::Array[Dependabot::DependencyFile],
|
|
114
|
+
updated_files: T::Array[Dependabot::DependencyFile]
|
|
115
|
+
).void
|
|
116
|
+
end
|
|
117
|
+
def update_files_content(temp_dir, local_files, updated_files)
|
|
118
|
+
local_files.each do |file|
|
|
119
|
+
f_content = File.read(File.join(temp_dir, file.directory, file.name))
|
|
120
|
+
tmp_file = file.dup
|
|
121
|
+
tmp_file.content = tmp_file.binary? ? Base64.encode64(f_content) : f_content
|
|
122
|
+
updated_files[T.must(updated_files.index(file))] = tmp_file
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
sig { params(temp_dir: T.any(Pathname, String)).void }
|
|
127
|
+
def populate_temp_directory(temp_dir)
|
|
128
|
+
files_to_populate.each do |file|
|
|
129
|
+
in_path_name = File.join(temp_dir, file.directory, file.name)
|
|
130
|
+
FileUtils.mkdir_p(File.dirname(in_path_name))
|
|
131
|
+
File.write(in_path_name, file.content)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
sig { params(file_name: String).void }
|
|
136
|
+
def write_properties_file(file_name) # rubocop:disable Metrics/PerceivedComplexity
|
|
137
|
+
http_proxy = ENV.fetch("HTTP_PROXY", nil)
|
|
138
|
+
https_proxy = ENV.fetch("HTTPS_PROXY", nil)
|
|
139
|
+
http_split = http_proxy&.split(":")
|
|
140
|
+
https_split = https_proxy&.split(":")
|
|
141
|
+
http_proxy_host = http_split&.fetch(1, nil)&.gsub("//", "") || "host.docker.internal"
|
|
142
|
+
https_proxy_host = https_split&.fetch(1, nil)&.gsub("//", "") || "host.docker.internal"
|
|
143
|
+
http_proxy_port = http_split&.fetch(2) || "1080"
|
|
144
|
+
https_proxy_port = https_split&.fetch(2) || "1080"
|
|
145
|
+
properties_content = "
|
|
146
|
+
systemProp.http.proxyHost=#{http_proxy_host}
|
|
147
|
+
systemProp.http.proxyPort=#{http_proxy_port}
|
|
148
|
+
systemProp.https.proxyHost=#{https_proxy_host}
|
|
149
|
+
systemProp.https.proxyPort=#{https_proxy_port}"
|
|
150
|
+
File.write(file_name, properties_content)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
154
|
+
attr_reader :dependency_files
|
|
155
|
+
|
|
156
|
+
sig { returns(Dependabot::Dependency) }
|
|
157
|
+
attr_reader :dependency
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -15,6 +15,7 @@ module Dependabot
|
|
|
15
15
|
require_relative "file_updater/dependency_set_updater"
|
|
16
16
|
require_relative "file_updater/property_value_updater"
|
|
17
17
|
require_relative "file_updater/lockfile_updater"
|
|
18
|
+
require_relative "file_updater/wrapper_updater"
|
|
18
19
|
|
|
19
20
|
SUPPORTED_BUILD_FILE_NAMES = %w(build.gradle build.gradle.kts gradle.lockfile).freeze
|
|
20
21
|
|
|
@@ -57,6 +58,7 @@ module Dependabot
|
|
|
57
58
|
# rubocop:disable Metrics/AbcSize
|
|
58
59
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|
59
60
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
61
|
+
# rubocop:disable Metrics/MethodLength
|
|
60
62
|
sig do
|
|
61
63
|
params(buildfiles: T::Array[Dependabot::DependencyFile], dependency: Dependabot::Dependency)
|
|
62
64
|
.returns(T::Array[Dependabot::DependencyFile])
|
|
@@ -64,6 +66,10 @@ module Dependabot
|
|
|
64
66
|
def update_buildfiles_for_dependency(buildfiles:, dependency:)
|
|
65
67
|
files = buildfiles.dup
|
|
66
68
|
|
|
69
|
+
# dependencies may have multiple requirements targeting the same file or build dir
|
|
70
|
+
# we keep the last one by path to later run its native helpers
|
|
71
|
+
buildfiles_processed = T.let({}, T::Hash[String, Dependabot::DependencyFile])
|
|
72
|
+
|
|
67
73
|
# The UpdateChecker ensures the order of requirements is preserved
|
|
68
74
|
# when updating, so we can zip them together in new/old pairs.
|
|
69
75
|
reqs = dependency.requirements.zip(T.must(dependency.previous_requirements))
|
|
@@ -93,17 +99,28 @@ module Dependabot
|
|
|
93
99
|
files[T.must(files.index(buildfile))] = update_version_in_buildfile(dependency, buildfile, old_req, new_req)
|
|
94
100
|
end
|
|
95
101
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
buildfiles_processed[buildfile.name] = buildfile
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# runs native updaters (e.g. wrapper, lockfile) on relevant build files updated
|
|
106
|
+
updated_files = T.let([], T::Array[Dependabot::DependencyFile])
|
|
107
|
+
buildfiles_processed.each do |_, buildfile|
|
|
108
|
+
if Dependabot::Experiments.enabled?(:gradle_lockfile_updater)
|
|
109
|
+
lockfile_updater = LockfileUpdater.new(dependency_files: files)
|
|
110
|
+
updated_files += lockfile_updater.update_lockfiles(buildfile)
|
|
111
|
+
end
|
|
112
|
+
if Dependabot::Experiments.enabled?(:gradle_wrapper_updater)
|
|
113
|
+
wrapper_updater = WrapperUpdater.new(dependency_files: files, dependency: dependency)
|
|
114
|
+
updated_files += wrapper_updater.update_files(buildfile)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
updated_files.each do |file|
|
|
119
|
+
existing_file = files.find { |f| f.name == file.name && f.directory == file.directory }
|
|
120
|
+
if existing_file.nil?
|
|
121
|
+
files << file
|
|
122
|
+
else
|
|
123
|
+
files[T.must(files.index(existing_file))] = file
|
|
107
124
|
end
|
|
108
125
|
end
|
|
109
126
|
|
|
@@ -112,6 +129,7 @@ module Dependabot
|
|
|
112
129
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
113
130
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
114
131
|
# rubocop:enable Metrics/AbcSize
|
|
132
|
+
# rubocop:enable Metrics/MethodLength
|
|
115
133
|
|
|
116
134
|
sig do
|
|
117
135
|
params(
|
|
@@ -191,6 +209,7 @@ module Dependabot
|
|
|
191
209
|
end
|
|
192
210
|
|
|
193
211
|
# rubocop:disable Metrics/AbcSize
|
|
212
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
194
213
|
sig do
|
|
195
214
|
params(
|
|
196
215
|
dependency: Dependabot::Dependency,
|
|
@@ -209,6 +228,10 @@ module Dependabot
|
|
|
209
228
|
if dependency.name.include?(":")
|
|
210
229
|
dep_parts = dependency.name.split(":")
|
|
211
230
|
next false unless line.include?(T.must(dep_parts.first)) || line.include?(T.must(dep_parts.last))
|
|
231
|
+
elsif T.let(requirement.fetch(:file), String).end_with?(".properties")
|
|
232
|
+
property = T.let(requirement, T::Hash[Symbol, T.nilable(T::Hash[Symbol, T.nilable(String)])])
|
|
233
|
+
.dig(:source, :property)
|
|
234
|
+
next false unless !property.nil? && line.start_with?(property)
|
|
212
235
|
elsif T.let(requirement.fetch(:file), String).end_with?(".toml")
|
|
213
236
|
next false unless line.include?(dependency.name)
|
|
214
237
|
else
|
|
@@ -221,6 +244,7 @@ module Dependabot
|
|
|
221
244
|
end
|
|
222
245
|
end
|
|
223
246
|
# rubocop:enable Metrics/AbcSize
|
|
247
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
224
248
|
|
|
225
249
|
sig { params(string: String, buildfile: Dependabot::DependencyFile).returns(String) }
|
|
226
250
|
def evaluate_properties(string, buildfile)
|
|
@@ -5,6 +5,7 @@ require "nokogiri"
|
|
|
5
5
|
require "sorbet-runtime"
|
|
6
6
|
|
|
7
7
|
require "dependabot/file_fetchers/base"
|
|
8
|
+
require "dependabot/gradle/distributions"
|
|
8
9
|
require "dependabot/gradle/file_fetcher"
|
|
9
10
|
require "dependabot/gradle/file_parser/repositories_finder"
|
|
10
11
|
require "dependabot/maven/utils/auth_headers_finder"
|
|
@@ -25,6 +26,8 @@ module Dependabot
|
|
|
25
26
|
|
|
26
27
|
sig { override.returns(T.nilable(Dependabot::Source)) }
|
|
27
28
|
def look_up_source
|
|
29
|
+
return nil if Distributions.distribution_requirements?(dependency.requirements)
|
|
30
|
+
|
|
28
31
|
tmp_source = look_up_source_in_pom(dependency_pom_file)
|
|
29
32
|
return tmp_source if tmp_source
|
|
30
33
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "dependabot/gradle/version"
|
|
5
|
+
require "dependabot/gradle/distributions"
|
|
6
|
+
require "sorbet-runtime"
|
|
7
|
+
|
|
8
|
+
module Dependabot
|
|
9
|
+
module Gradle
|
|
10
|
+
module Package
|
|
11
|
+
class DistributionsFetcher
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
@available_versions = T.let([], T::Array[T::Hash[String, T.untyped]])
|
|
15
|
+
@distributions_checksums = T.let({}, T::Hash[String, T::Array[String]])
|
|
16
|
+
|
|
17
|
+
sig { returns(T.any(T::Array[T::Hash[String, T.untyped]], T::Array[T::Hash[Symbol, T.untyped]])) }
|
|
18
|
+
def self.available_versions
|
|
19
|
+
return @available_versions if @available_versions.any?
|
|
20
|
+
|
|
21
|
+
response = Dependabot::RegistryClient.get(url: "https://services.gradle.org/versions/all")
|
|
22
|
+
versions = T.let(
|
|
23
|
+
JSON.parse(
|
|
24
|
+
T.let(response.body, String),
|
|
25
|
+
object_class: OpenStruct
|
|
26
|
+
),
|
|
27
|
+
T::Array[OpenStruct]
|
|
28
|
+
)
|
|
29
|
+
@available_versions +=
|
|
30
|
+
versions
|
|
31
|
+
.select { |v| release_version?(version: v) }
|
|
32
|
+
.uniq { |v| v[:version] }
|
|
33
|
+
.map do |v|
|
|
34
|
+
{
|
|
35
|
+
version: v[:version],
|
|
36
|
+
build_time: v[:buildTime]
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
sig { params(version: OpenStruct).returns(T::Boolean) }
|
|
42
|
+
def self.release_version?(version:)
|
|
43
|
+
Gradle::Version.correct?(T.let(version[:version], String)) &&
|
|
44
|
+
T.let(version[:broken], T::Boolean) == false &&
|
|
45
|
+
T.let(version[:snapshot], T::Boolean) == false &&
|
|
46
|
+
T.let(version[:rcFor], String) == "" &&
|
|
47
|
+
T.let(version[:milestoneFor], String) == "" &&
|
|
48
|
+
/.*-(rc|milestone)-.*/.match?(T.let(version[:version], String)) == false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
sig { params(distribution_url: String).returns(T.nilable(T::Array[String])) }
|
|
52
|
+
def self.resolve_checksum(distribution_url)
|
|
53
|
+
cached = @distributions_checksums[distribution_url]
|
|
54
|
+
return cached if cached
|
|
55
|
+
|
|
56
|
+
checksum_url = "#{distribution_url}.sha256"
|
|
57
|
+
checksum = T.let(Dependabot::RegistryClient.get(url: checksum_url).body, String).strip
|
|
58
|
+
return nil unless checksum.match?(/\A[a-f0-9]{64}\z/)
|
|
59
|
+
|
|
60
|
+
@distributions_checksums[distribution_url] = [checksum_url, checksum]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private_class_method :release_version?
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -8,6 +8,7 @@ require "dependabot/gradle/file_parser/repositories_finder"
|
|
|
8
8
|
require "dependabot/gradle/update_checker"
|
|
9
9
|
require "dependabot/gradle/version"
|
|
10
10
|
require "dependabot/gradle/requirement"
|
|
11
|
+
require "dependabot/gradle/distributions"
|
|
11
12
|
require "dependabot/maven/utils/auth_headers_finder"
|
|
12
13
|
require "sorbet-runtime"
|
|
13
14
|
require "dependabot/gradle/metadata_finder"
|
|
@@ -65,6 +66,7 @@ module Dependabot
|
|
|
65
66
|
repositories.map do |repository_details|
|
|
66
67
|
url = repository_details.fetch("url")
|
|
67
68
|
|
|
69
|
+
next distribution_version_details if url == Gradle::Distributions::DISTRIBUTION_REPOSITORY_URL
|
|
68
70
|
next google_version_details if url == Gradle::FileParser::RepositoriesFinder::GOOGLE_MAVEN_REPO
|
|
69
71
|
|
|
70
72
|
dependency_metadata(repository_details).css("versions > version")
|
|
@@ -83,7 +85,7 @@ module Dependabot
|
|
|
83
85
|
|
|
84
86
|
package_releases << {
|
|
85
87
|
version: Gradle::Version.new(version),
|
|
86
|
-
released_at:
|
|
88
|
+
released_at: info[:released_at] || release_date_info[version]&.fetch(:release_date),
|
|
87
89
|
source_url: info[:source_url]
|
|
88
90
|
}
|
|
89
91
|
end
|
|
@@ -136,7 +138,9 @@ module Dependabot
|
|
|
136
138
|
def repositories
|
|
137
139
|
return @repositories if @repositories
|
|
138
140
|
|
|
139
|
-
details = if
|
|
141
|
+
details = if distribution?
|
|
142
|
+
distribution_repository_details
|
|
143
|
+
elsif plugin?
|
|
140
144
|
plugin_repository_details + credentials_repository_details
|
|
141
145
|
else
|
|
142
146
|
dependency_repository_details + credentials_repository_details
|
|
@@ -151,6 +155,27 @@ module Dependabot
|
|
|
151
155
|
end
|
|
152
156
|
end
|
|
153
157
|
|
|
158
|
+
sig { returns(T.nilable(T::Array[T::Hash[String, T.untyped]])) }
|
|
159
|
+
def distribution_version_details
|
|
160
|
+
return nil unless Experiments.enabled?(:gradle_wrapper_updater)
|
|
161
|
+
|
|
162
|
+
DistributionsFetcher.available_versions.map do |info|
|
|
163
|
+
release_date = begin
|
|
164
|
+
Time.parse(info[:build_time])
|
|
165
|
+
rescue StandardError
|
|
166
|
+
nil
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
{
|
|
170
|
+
version: info[:version],
|
|
171
|
+
released_at: release_date,
|
|
172
|
+
source_url: Distributions::DISTRIBUTION_REPOSITORY_URL
|
|
173
|
+
}
|
|
174
|
+
end
|
|
175
|
+
rescue StandardError
|
|
176
|
+
nil
|
|
177
|
+
end
|
|
178
|
+
|
|
154
179
|
sig { returns(T.nilable(T::Array[T::Hash[String, T.untyped]])) }
|
|
155
180
|
def google_version_details
|
|
156
181
|
url = Gradle::FileParser::RepositoriesFinder::GOOGLE_MAVEN_REPO
|
|
@@ -276,6 +301,14 @@ module Dependabot
|
|
|
276
301
|
}] + dependency_repository_details
|
|
277
302
|
end
|
|
278
303
|
|
|
304
|
+
sig { returns(T::Array[T::Hash[String, T.untyped]]) }
|
|
305
|
+
def distribution_repository_details
|
|
306
|
+
[{
|
|
307
|
+
"url" => Gradle::Distributions::DISTRIBUTION_REPOSITORY_URL,
|
|
308
|
+
"auth_headers" => {}
|
|
309
|
+
}]
|
|
310
|
+
end
|
|
311
|
+
|
|
279
312
|
sig { params(comparison_version: T.untyped).returns(T::Boolean) }
|
|
280
313
|
def matches_dependency_version_type?(comparison_version)
|
|
281
314
|
return true unless dependency.version
|
|
@@ -336,6 +369,11 @@ module Dependabot
|
|
|
336
369
|
plugin? && dependency.requirements.any? { |r| r.fetch(:groups).include? "kotlin" }
|
|
337
370
|
end
|
|
338
371
|
|
|
372
|
+
sig { returns(T::Boolean) }
|
|
373
|
+
def distribution?
|
|
374
|
+
Distributions.distribution_requirements?(dependency.requirements)
|
|
375
|
+
end
|
|
376
|
+
|
|
339
377
|
sig { returns(T::Array[String]) }
|
|
340
378
|
def central_repo_urls
|
|
341
379
|
central_url_without_protocol =
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
require "sorbet-runtime"
|
|
10
10
|
|
|
11
11
|
require "dependabot/requirements_updater/base"
|
|
12
|
+
require "dependabot/gradle/distributions"
|
|
13
|
+
require "dependabot/gradle/package/distributions_fetcher"
|
|
12
14
|
require "dependabot/gradle/update_checker"
|
|
13
15
|
require "dependabot/gradle/version"
|
|
14
16
|
require "dependabot/gradle/requirement"
|
|
@@ -46,11 +48,13 @@ module Dependabot
|
|
|
46
48
|
return unless latest_version
|
|
47
49
|
|
|
48
50
|
@latest_version = T.let(version_class.new(latest_version), Version)
|
|
51
|
+
@is_distribution = T.let(Distributions.distribution_requirements?(requirements), T::Boolean)
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
52
55
|
def updated_requirements
|
|
53
56
|
return requirements unless latest_version
|
|
57
|
+
return updated_distribution_requirements if @is_distribution
|
|
54
58
|
|
|
55
59
|
# NOTE: Order is important here. The FileUpdater needs the updated
|
|
56
60
|
# requirement at index `i` to correspond to the previous requirement
|
|
@@ -114,6 +118,38 @@ module Dependabot
|
|
|
114
118
|
end
|
|
115
119
|
end
|
|
116
120
|
|
|
121
|
+
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
|
122
|
+
def updated_distribution_requirements
|
|
123
|
+
return requirements unless Experiments.enabled?(:gradle_wrapper_updater)
|
|
124
|
+
|
|
125
|
+
distribution_url = T.let(nil, T.nilable(String))
|
|
126
|
+
|
|
127
|
+
requirements.map do |req|
|
|
128
|
+
source = req[:source]
|
|
129
|
+
next req unless source
|
|
130
|
+
|
|
131
|
+
case source[:property]
|
|
132
|
+
when "distributionUrl"
|
|
133
|
+
requirement = req[:requirement]
|
|
134
|
+
version = update_exact_requirement(requirement)
|
|
135
|
+
distribution_url = source[:url].gsub(requirement, version)
|
|
136
|
+
|
|
137
|
+
req.merge(
|
|
138
|
+
requirement: version,
|
|
139
|
+
source: source.merge(url: distribution_url)
|
|
140
|
+
)
|
|
141
|
+
when "distributionSha256Sum"
|
|
142
|
+
checksum_url, checksum = Gradle::Package::DistributionsFetcher.resolve_checksum(T.must(distribution_url))
|
|
143
|
+
req.merge(
|
|
144
|
+
requirement: checksum,
|
|
145
|
+
source: source.merge(url: checksum_url)
|
|
146
|
+
)
|
|
147
|
+
else
|
|
148
|
+
next req
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
117
153
|
sig { override.returns(T::Class[Version]) }
|
|
118
154
|
def version_class
|
|
119
155
|
Gradle::Version
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-gradle
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.346.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,28 +15,28 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.346.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.346.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: dependabot-maven
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.
|
|
32
|
+
version: 0.346.0
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.
|
|
39
|
+
version: 0.346.0
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: debug
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -256,17 +256,21 @@ extensions: []
|
|
|
256
256
|
extra_rdoc_files: []
|
|
257
257
|
files:
|
|
258
258
|
- lib/dependabot/gradle.rb
|
|
259
|
+
- lib/dependabot/gradle/distributions.rb
|
|
259
260
|
- lib/dependabot/gradle/file_fetcher.rb
|
|
260
261
|
- lib/dependabot/gradle/file_fetcher/settings_file_parser.rb
|
|
261
262
|
- lib/dependabot/gradle/file_parser.rb
|
|
263
|
+
- lib/dependabot/gradle/file_parser/distributions_finder.rb
|
|
262
264
|
- lib/dependabot/gradle/file_parser/property_value_finder.rb
|
|
263
265
|
- lib/dependabot/gradle/file_parser/repositories_finder.rb
|
|
264
266
|
- lib/dependabot/gradle/file_updater.rb
|
|
265
267
|
- lib/dependabot/gradle/file_updater/dependency_set_updater.rb
|
|
266
268
|
- lib/dependabot/gradle/file_updater/lockfile_updater.rb
|
|
267
269
|
- lib/dependabot/gradle/file_updater/property_value_updater.rb
|
|
270
|
+
- lib/dependabot/gradle/file_updater/wrapper_updater.rb
|
|
268
271
|
- lib/dependabot/gradle/language.rb
|
|
269
272
|
- lib/dependabot/gradle/metadata_finder.rb
|
|
273
|
+
- lib/dependabot/gradle/package/distributions_fetcher.rb
|
|
270
274
|
- lib/dependabot/gradle/package/package_details_fetcher.rb
|
|
271
275
|
- lib/dependabot/gradle/package_manager.rb
|
|
272
276
|
- lib/dependabot/gradle/requirement.rb
|
|
@@ -280,7 +284,7 @@ licenses:
|
|
|
280
284
|
- MIT
|
|
281
285
|
metadata:
|
|
282
286
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
283
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
287
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.346.0
|
|
284
288
|
rdoc_options: []
|
|
285
289
|
require_paths:
|
|
286
290
|
- lib
|