dependabot-bazel 0.345.0 → 0.347.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/bazel/file_fetcher.rb +119 -11
- data/lib/dependabot/bazel/file_parser.rb +2 -1
- data/lib/dependabot/bazel/file_updater/bzlmod_file_updater.rb +24 -2
- data/lib/dependabot/bazel/file_updater/lockfile_updater.rb +239 -0
- data/lib/dependabot/bazel/file_updater.rb +16 -1
- data/lib/dependabot/bazel/metadata_finder.rb +91 -7
- data/lib/dependabot/bazel/update_checker/registry_client.rb +2 -1
- data/lib/dependabot/bazel/update_checker/requirements_updater.rb +3 -1
- data/lib/dependabot/bazel/version.rb +7 -7
- data/lib/dependabot/bazel.rb +3 -2
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9852686dc5127e74b39132b06f0f0842c87072db3c49cdf6967c497f18188c0c
|
|
4
|
+
data.tar.gz: fb12ceb562835906b5b0c49240fc9f8e2e89c58b66b600795cfc25f4546cb12a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a38a1c7af4b2d3f2e9eb85dd108cb7a516c2d623d7e3c4ee28908149a99d18c8f7cf0f814ddd9fdfe897469aa453b12a2e33c53633d4af74db23d2c7799ea05
|
|
7
|
+
data.tar.gz: 9d5dbe0e680f1be8ce7c3debdc133c95c30ea0ba9899f4b2fffe65cdf7da3100489ebe39138823f482e77a3b7e0730c666b95092f93fa108314c6ef60616232b
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "dependabot/file_fetchers"
|
|
@@ -10,8 +10,10 @@ module Dependabot
|
|
|
10
10
|
extend T::Sig
|
|
11
11
|
|
|
12
12
|
WORKSPACE_FILES = T.let(%w(WORKSPACE WORKSPACE.bazel).freeze, T::Array[String])
|
|
13
|
-
|
|
14
|
-
CONFIG_FILES = T.let(
|
|
13
|
+
MODULE_FILE = T.let("MODULE.bazel", String)
|
|
14
|
+
CONFIG_FILES = T.let(
|
|
15
|
+
%w(.bazelrc MODULE.bazel.lock .bazelversion maven_install.json BUILD BUILD.bazel).freeze, T::Array[String]
|
|
16
|
+
)
|
|
15
17
|
SKIP_DIRECTORIES = T.let(%w(.git .bazel-* bazel-* node_modules .github).freeze, T::Array[String])
|
|
16
18
|
|
|
17
19
|
sig { override.returns(String) }
|
|
@@ -21,7 +23,7 @@ module Dependabot
|
|
|
21
23
|
|
|
22
24
|
sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
|
|
23
25
|
def self.required_files_in?(filenames)
|
|
24
|
-
filenames.any? { |name| WORKSPACE_FILES.include?(name) ||
|
|
26
|
+
filenames.any? { |name| WORKSPACE_FILES.include?(name) || name.end_with?(MODULE_FILE) }
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
sig { override.returns(T::Array[DependencyFile]) }
|
|
@@ -40,6 +42,7 @@ module Dependabot
|
|
|
40
42
|
fetched_files += workspace_files
|
|
41
43
|
fetched_files += module_files
|
|
42
44
|
fetched_files += config_files
|
|
45
|
+
fetched_files += referenced_files_from_modules
|
|
43
46
|
|
|
44
47
|
return fetched_files if fetched_files.any?
|
|
45
48
|
|
|
@@ -74,33 +77,138 @@ module Dependabot
|
|
|
74
77
|
def module_files
|
|
75
78
|
files = T.let([], T::Array[DependencyFile])
|
|
76
79
|
|
|
77
|
-
|
|
78
|
-
file = fetch_file_if_present(
|
|
80
|
+
module_file_items.each do |item|
|
|
81
|
+
file = fetch_file_if_present(item.name)
|
|
79
82
|
files << file if file
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
files
|
|
83
86
|
end
|
|
84
87
|
|
|
88
|
+
sig { returns(T::Array[T.untyped]) }
|
|
89
|
+
def module_file_items
|
|
90
|
+
repo_contents(raise_errors: false).select { |f| f.type == "file" && f.name.end_with?(MODULE_FILE) }
|
|
91
|
+
end
|
|
92
|
+
|
|
85
93
|
sig { returns(T::Array[DependencyFile]) }
|
|
86
94
|
def config_files
|
|
87
95
|
files = T.let([], T::Array[DependencyFile])
|
|
88
96
|
|
|
89
|
-
CONFIG_FILES.
|
|
90
|
-
file =
|
|
97
|
+
CONFIG_FILES.map do |filename|
|
|
98
|
+
file = if filename == ".bazelversion"
|
|
99
|
+
fetch_bazelversion_file
|
|
100
|
+
else
|
|
101
|
+
fetch_file_if_present(filename)
|
|
102
|
+
end
|
|
91
103
|
files << file if file
|
|
92
104
|
end
|
|
93
105
|
|
|
94
|
-
bazelversion = fetch_file_if_present(".bazelversion")
|
|
95
|
-
files << bazelversion if bazelversion
|
|
96
|
-
|
|
97
106
|
files
|
|
98
107
|
end
|
|
99
108
|
|
|
109
|
+
sig { returns(T.nilable(DependencyFile)) }
|
|
110
|
+
def fetch_bazelversion_file
|
|
111
|
+
file = fetch_file_if_present(".bazelversion")
|
|
112
|
+
return file if file
|
|
113
|
+
return if [".", "/"].include?(directory)
|
|
114
|
+
|
|
115
|
+
fetch_file_from_parent_directories(".bazelversion")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
sig { params(filename: String).returns(T.nilable(DependencyFile)) }
|
|
119
|
+
def fetch_file_from_parent_directories(filename)
|
|
120
|
+
(1..directory.split("/").count).each do |i|
|
|
121
|
+
candidate_path = ("../" * i) + filename
|
|
122
|
+
file = fetch_file_if_present(candidate_path)
|
|
123
|
+
if file
|
|
124
|
+
file.name = filename
|
|
125
|
+
return file
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
nil
|
|
129
|
+
end
|
|
130
|
+
|
|
100
131
|
sig { params(dirname: String).returns(T::Boolean) }
|
|
101
132
|
def should_skip_directory?(dirname)
|
|
102
133
|
SKIP_DIRECTORIES.any? { |skip_dir| dirname.start_with?(skip_dir) }
|
|
103
134
|
end
|
|
135
|
+
|
|
136
|
+
# Fetches files referenced in MODULE.bazel files via lock_file and requirements_lock attributes.
|
|
137
|
+
# Also fetches BUILD/BUILD.bazel files from directories containing referenced files, as these
|
|
138
|
+
# are required by Bazel to recognize the directories as valid packages.
|
|
139
|
+
#
|
|
140
|
+
# This method handles Bazel label syntax and converts it to filesystem paths:
|
|
141
|
+
# - "@repo//path:file.json" -> "path/file.json"
|
|
142
|
+
# - "//path:file.json" -> "path/file.json"
|
|
143
|
+
# - "@repo//:file.json" -> "file.json"
|
|
144
|
+
#
|
|
145
|
+
# @return [Array<DependencyFile>] referenced files and their associated BUILD files
|
|
146
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
147
|
+
def referenced_files_from_modules
|
|
148
|
+
files = T.let([], T::Array[DependencyFile])
|
|
149
|
+
directories_with_files = T.let(Set.new, T::Set[String])
|
|
150
|
+
|
|
151
|
+
module_files.each do |module_file|
|
|
152
|
+
referenced_paths = extract_referenced_paths(module_file)
|
|
153
|
+
|
|
154
|
+
referenced_paths.each do |path|
|
|
155
|
+
fetched_file = fetch_file_if_present(path)
|
|
156
|
+
next unless fetched_file
|
|
157
|
+
|
|
158
|
+
files << fetched_file
|
|
159
|
+
# Track directories that contain referenced files so we can fetch their BUILD files.
|
|
160
|
+
# Exclude root directory (.) as BUILD files there are already handled by config_files.
|
|
161
|
+
dir = File.dirname(path)
|
|
162
|
+
directories_with_files.add(dir) unless dir == "."
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Fetch BUILD or BUILD.bazel files for directories that contain referenced files.
|
|
167
|
+
# These BUILD files are required for Bazel to recognize directories as valid packages.
|
|
168
|
+
directories_with_files.each do |dir|
|
|
169
|
+
build_file = fetch_file_if_present("#{dir}/BUILD") || fetch_file_if_present("#{dir}/BUILD.bazel")
|
|
170
|
+
files << build_file if build_file
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
files
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Extracts file paths from lock_file and requirements_lock attributes in MODULE.bazel content.
|
|
177
|
+
# Converts Bazel label syntax to filesystem paths.
|
|
178
|
+
#
|
|
179
|
+
# Bazel labels can have several formats:
|
|
180
|
+
# - "@repo//path:file" - external or self-referential repository with path
|
|
181
|
+
# - "//path:file" - main repository reference with path
|
|
182
|
+
# - "@repo//:file" - external or self-referential repository root file
|
|
183
|
+
# - "//:file" - main repository root file
|
|
184
|
+
#
|
|
185
|
+
# The method:
|
|
186
|
+
# 1. Strips optional @repo prefix
|
|
187
|
+
# 2. Converts colon separators to forward slashes (path:file -> path/file)
|
|
188
|
+
# 3. Removes leading slashes to create relative paths
|
|
189
|
+
#
|
|
190
|
+
# @param module_file [DependencyFile] the MODULE.bazel file to parse
|
|
191
|
+
# @return [Array<String>] unique relative file paths referenced in the module
|
|
192
|
+
sig { params(module_file: DependencyFile).returns(T::Array[String]) }
|
|
193
|
+
def extract_referenced_paths(module_file)
|
|
194
|
+
content = T.must(module_file.content)
|
|
195
|
+
paths = []
|
|
196
|
+
|
|
197
|
+
# Match lock_file attributes with optional @repo prefix: "(?:@[^"\/]+)?\/\/([^"]+)"
|
|
198
|
+
# Capture group 1: everything after // (e.g., "tools/jol:file.json" or ":file.json")
|
|
199
|
+
content.scan(%r{lock_file\s*=\s*"(?:@[^"/]+)?//([^"]+)"}) do |match|
|
|
200
|
+
path = match[0].tr(":", "/").sub(%r{^/}, "")
|
|
201
|
+
paths << path
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Match requirements_lock attributes with optional @repo prefix
|
|
205
|
+
content.scan(%r{requirements_lock\s*=\s*"(?:@[^"/]+)?//([^"]+)"}) do |match|
|
|
206
|
+
path = match[0].tr(":", "/").sub(%r{^/}, "")
|
|
207
|
+
paths << path
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
paths.uniq
|
|
211
|
+
end
|
|
104
212
|
end
|
|
105
213
|
end
|
|
106
214
|
end
|
|
@@ -222,6 +222,7 @@ module Dependabot
|
|
|
222
222
|
name = func_call.arguments["name"]
|
|
223
223
|
tag = func_call.arguments["tag"]
|
|
224
224
|
commit = func_call.arguments["commit"]
|
|
225
|
+
remote = func_call.arguments["remote"]
|
|
225
226
|
|
|
226
227
|
return nil unless name.is_a?(String)
|
|
227
228
|
|
|
@@ -236,7 +237,7 @@ module Dependabot
|
|
|
236
237
|
file: file.name,
|
|
237
238
|
requirement: version,
|
|
238
239
|
groups: [],
|
|
239
|
-
source: { type: "git_repository", tag: tag, commit: commit }
|
|
240
|
+
source: { type: "git_repository", tag: tag, commit: commit, remote: remote }
|
|
240
241
|
}
|
|
241
242
|
],
|
|
242
243
|
package_manager: "bazel"
|
|
@@ -10,6 +10,8 @@ module Dependabot
|
|
|
10
10
|
class BzlmodFileUpdater
|
|
11
11
|
extend T::Sig
|
|
12
12
|
|
|
13
|
+
require_relative "lockfile_updater"
|
|
14
|
+
|
|
13
15
|
sig do
|
|
14
16
|
params(
|
|
15
17
|
dependency_files: T::Array[Dependabot::DependencyFile],
|
|
@@ -25,12 +27,27 @@ module Dependabot
|
|
|
25
27
|
|
|
26
28
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
27
29
|
def updated_module_files
|
|
28
|
-
|
|
30
|
+
updated_files = T.let([], T::Array[Dependabot::DependencyFile])
|
|
31
|
+
|
|
32
|
+
module_files.each do |file|
|
|
29
33
|
updated_content = update_file_content(file)
|
|
30
34
|
next if updated_content == T.must(file.content)
|
|
31
35
|
|
|
32
|
-
file.dup.tap { |f| f.content = updated_content }
|
|
36
|
+
updated_files << file.dup.tap { |f| f.content = updated_content }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if generate_lockfile?
|
|
40
|
+
lockfile_updater = LockfileUpdater.new(
|
|
41
|
+
dependency_files: dependency_files,
|
|
42
|
+
dependencies: dependencies,
|
|
43
|
+
credentials: credentials
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
updated_lockfile = lockfile_updater.updated_lockfile
|
|
47
|
+
updated_files << updated_lockfile if updated_lockfile
|
|
33
48
|
end
|
|
49
|
+
|
|
50
|
+
updated_files
|
|
34
51
|
end
|
|
35
52
|
|
|
36
53
|
private
|
|
@@ -52,6 +69,11 @@ module Dependabot
|
|
|
52
69
|
)
|
|
53
70
|
end
|
|
54
71
|
|
|
72
|
+
sig { returns(T::Boolean) }
|
|
73
|
+
def generate_lockfile?
|
|
74
|
+
dependency_files.any? { |f| f.name.end_with?("MODULE.bazel.lock") }
|
|
75
|
+
end
|
|
76
|
+
|
|
55
77
|
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
|
56
78
|
def update_file_content(file)
|
|
57
79
|
content = T.must(file.content).dup
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
require "dependabot/bazel/file_updater"
|
|
6
|
+
require "dependabot/shared_helpers"
|
|
7
|
+
require "pathname"
|
|
8
|
+
require "fileutils"
|
|
9
|
+
|
|
10
|
+
module Dependabot
|
|
11
|
+
module Bazel
|
|
12
|
+
class FileUpdater < Dependabot::FileUpdaters::Base
|
|
13
|
+
class LockfileUpdater
|
|
14
|
+
extend T::Sig
|
|
15
|
+
|
|
16
|
+
DEFAULT_BAZEL_VERSION = "8.4.2"
|
|
17
|
+
|
|
18
|
+
sig do
|
|
19
|
+
params(
|
|
20
|
+
dependency_files: T::Array[Dependabot::DependencyFile],
|
|
21
|
+
dependencies: T::Array[Dependabot::Dependency],
|
|
22
|
+
credentials: T::Array[Dependabot::Credential]
|
|
23
|
+
).void
|
|
24
|
+
end
|
|
25
|
+
def initialize(dependency_files:, dependencies:, credentials:)
|
|
26
|
+
@dependency_files = dependency_files
|
|
27
|
+
@dependencies = dependencies
|
|
28
|
+
@credentials = credentials
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
32
|
+
def updated_lockfile
|
|
33
|
+
return nil unless needs_lockfile_update?
|
|
34
|
+
|
|
35
|
+
existing_lockfile = lockfile
|
|
36
|
+
updated_content = generate_lockfile_content
|
|
37
|
+
|
|
38
|
+
if existing_lockfile
|
|
39
|
+
return nil if existing_lockfile.content == updated_content
|
|
40
|
+
|
|
41
|
+
existing_lockfile.dup.tap { |f| f.content = updated_content }
|
|
42
|
+
else
|
|
43
|
+
Dependabot::DependencyFile.new(
|
|
44
|
+
name: "MODULE.bazel.lock",
|
|
45
|
+
content: updated_content,
|
|
46
|
+
directory: module_file.directory
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
rescue SharedHelpers::HelperSubprocessFailed => e
|
|
50
|
+
handle_bazel_error_for_lockfile(e)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
sig { returns(String) }
|
|
54
|
+
def determine_bazel_version
|
|
55
|
+
bazelversion_file = dependency_files.find { |f| f.name == ".bazelversion" }
|
|
56
|
+
return DEFAULT_BAZEL_VERSION unless bazelversion_file
|
|
57
|
+
|
|
58
|
+
version = T.must(bazelversion_file.content).strip
|
|
59
|
+
version.empty? ? DEFAULT_BAZEL_VERSION : version
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
65
|
+
attr_reader :dependency_files
|
|
66
|
+
|
|
67
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
|
68
|
+
attr_reader :dependencies
|
|
69
|
+
|
|
70
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
|
71
|
+
attr_reader :credentials
|
|
72
|
+
|
|
73
|
+
sig { returns(T::Boolean) }
|
|
74
|
+
def needs_lockfile_update?
|
|
75
|
+
return false unless module_file?
|
|
76
|
+
|
|
77
|
+
dependencies.any? { |dep| bzlmod_dependency?(dep) }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
sig { returns(T::Boolean) }
|
|
81
|
+
def module_file?
|
|
82
|
+
module_files.any?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
86
|
+
def module_files
|
|
87
|
+
@module_files ||= T.let(
|
|
88
|
+
dependency_files.select { |f| f.name.end_with?("MODULE.bazel") },
|
|
89
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
sig { returns(Dependabot::DependencyFile) }
|
|
94
|
+
def module_file
|
|
95
|
+
T.must(module_files.first)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
99
|
+
def lockfile
|
|
100
|
+
@lockfile ||= T.let(
|
|
101
|
+
dependency_files.find { |f| f.name == "MODULE.bazel.lock" },
|
|
102
|
+
T.nilable(Dependabot::DependencyFile)
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
|
|
107
|
+
def bzlmod_dependency?(dependency)
|
|
108
|
+
dependency.requirements.any? { |req| req[:file]&.end_with?("MODULE.bazel") }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
sig { returns(String) }
|
|
112
|
+
def generate_lockfile_content
|
|
113
|
+
base_directory = module_file.directory
|
|
114
|
+
|
|
115
|
+
SharedHelpers.in_a_temporary_repo_directory(base_directory, repo_contents_path) do
|
|
116
|
+
write_temporary_dependency_files
|
|
117
|
+
|
|
118
|
+
File.write(module_file.name, updated_module_content)
|
|
119
|
+
|
|
120
|
+
run_bazel_mod_tidy_command
|
|
121
|
+
|
|
122
|
+
File.read("MODULE.bazel.lock")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
sig { returns(String) }
|
|
127
|
+
def updated_module_content
|
|
128
|
+
bzlmod_updater = BzlmodFileUpdater.new(
|
|
129
|
+
dependency_files: dependency_files,
|
|
130
|
+
dependencies: dependencies,
|
|
131
|
+
credentials: credentials
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
bzlmod_updater.send(:update_file_content, module_file)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
sig { returns(T.nilable(String)) }
|
|
138
|
+
def repo_contents_path
|
|
139
|
+
# For now, return nil. This can be enhanced later if needed.
|
|
140
|
+
nil
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
sig { void }
|
|
144
|
+
def write_temporary_dependency_files
|
|
145
|
+
dependency_files.each do |file|
|
|
146
|
+
path = file.name
|
|
147
|
+
FileUtils.mkdir_p(Pathname.new(path).dirname) if path.include?("/")
|
|
148
|
+
File.write(path, T.must(file.content))
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
write_bazelversion_if_missing
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
sig { void }
|
|
155
|
+
def write_bazelversion_if_missing
|
|
156
|
+
return if dependency_files.any? { |f| f.name == ".bazelversion" }
|
|
157
|
+
|
|
158
|
+
bazel_version = determine_bazel_version
|
|
159
|
+
File.write(".bazelversion", bazel_version)
|
|
160
|
+
Dependabot.logger.info("Using Bazel version: #{bazel_version}")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
sig { void }
|
|
164
|
+
def run_bazel_mod_tidy_command
|
|
165
|
+
bazel_command = bazelisk_available? ? "bazelisk" : "bazel"
|
|
166
|
+
|
|
167
|
+
SharedHelpers.run_shell_command(
|
|
168
|
+
"#{bazel_command} mod tidy --lockfile_mode=update",
|
|
169
|
+
fingerprint: "#{bazel_command} mod tidy --lockfile_mode=update"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
return if File.exist?("MODULE.bazel.lock")
|
|
173
|
+
|
|
174
|
+
raise SharedHelpers::HelperSubprocessFailed.new(
|
|
175
|
+
message: "MODULE.bazel.lock file was not generated",
|
|
176
|
+
error_context: {}
|
|
177
|
+
)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
sig { returns(T::Boolean) }
|
|
181
|
+
def bazelisk_available?
|
|
182
|
+
!!system("which bazelisk > /dev/null 2>&1")
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
sig { params(error: SharedHelpers::HelperSubprocessFailed).returns(T.nilable(Dependabot::DependencyFile)) }
|
|
186
|
+
def handle_bazel_error_for_lockfile(error)
|
|
187
|
+
Dependabot.logger.warn("Bazel lockfile generation failed: #{error.message}")
|
|
188
|
+
|
|
189
|
+
case error.message
|
|
190
|
+
when /command not found/i, /bazel(isk)?\s*:\s*(command\s+)?not found/i
|
|
191
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
192
|
+
"Bazel binary not available. Cannot generate MODULE.bazel.lock file."
|
|
193
|
+
when /module.*not.*found/i, /registry.*not.*found/i
|
|
194
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
195
|
+
"Dependency not found in Bazel Central Registry."
|
|
196
|
+
when /network.*error/i, /timeout/i, /connection.*refused/i
|
|
197
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
198
|
+
"Network error during lockfile generation. Please try again later."
|
|
199
|
+
when /invalid.*syntax/i, /parse.*error/i
|
|
200
|
+
raise Dependabot::DependencyFileNotParseable,
|
|
201
|
+
"Invalid MODULE.bazel syntax prevents lockfile generation."
|
|
202
|
+
when /permission.*denied/i
|
|
203
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
204
|
+
"Permission error during lockfile generation."
|
|
205
|
+
else
|
|
206
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
207
|
+
"Error generating lockfile: #{error.message}"
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
sig { params(error: SharedHelpers::HelperSubprocessFailed).returns(String) }
|
|
212
|
+
def handle_bazel_error(error)
|
|
213
|
+
Dependabot.logger.warn("Bazel lockfile generation failed: #{error.message}")
|
|
214
|
+
|
|
215
|
+
case error.message
|
|
216
|
+
when /command not found/i, /bazel(isk)?\s*:\s*(command\s+)?not found/i
|
|
217
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
218
|
+
"Bazel binary not available. Cannot generate MODULE.bazel.lock file."
|
|
219
|
+
when /module.*not.*found/i, /registry.*not.*found/i
|
|
220
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
221
|
+
"Dependency not found in Bazel Central Registry."
|
|
222
|
+
when /network.*error/i, /timeout/i, /connection.*refused/i
|
|
223
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
224
|
+
"Network error during lockfile generation. Please try again later."
|
|
225
|
+
when /invalid.*syntax/i, /parse.*error/i
|
|
226
|
+
raise Dependabot::DependencyFileNotParseable,
|
|
227
|
+
"Invalid MODULE.bazel syntax prevents lockfile generation."
|
|
228
|
+
when /permission.*denied/i
|
|
229
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
230
|
+
"Permission error during lockfile generation."
|
|
231
|
+
else
|
|
232
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
233
|
+
"Error generating lockfile: #{error.message}"
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
@@ -17,7 +17,9 @@ module Dependabot
|
|
|
17
17
|
def self.updated_files_regex
|
|
18
18
|
[
|
|
19
19
|
/^MODULE\.bazel$/,
|
|
20
|
-
%r{^(?:.*/)?MODULE\.bazel$},
|
|
20
|
+
%r{^(?:.*/)?[^/]+\.MODULE\.bazel$},
|
|
21
|
+
/^MODULE\.bazel\.lock$/,
|
|
22
|
+
%r{^(?:.*/)?MODULE\.bazel\.lock$},
|
|
21
23
|
/^WORKSPACE$/,
|
|
22
24
|
%r{^(?:.*/)?WORKSPACE\.bazel$},
|
|
23
25
|
%r{^(?:.*/)?BUILD$},
|
|
@@ -70,6 +72,19 @@ module Dependabot
|
|
|
70
72
|
)
|
|
71
73
|
end
|
|
72
74
|
|
|
75
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
76
|
+
def lockfile_files
|
|
77
|
+
@lockfile_files ||= T.let(
|
|
78
|
+
dependency_files.select { |f| f.name.end_with?("MODULE.bazel.lock") },
|
|
79
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
sig { returns(T::Boolean) }
|
|
84
|
+
def requires_lockfile_update?
|
|
85
|
+
dependencies.any? { |dep| bzlmod_dependency?(dep) }
|
|
86
|
+
end
|
|
87
|
+
|
|
73
88
|
sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
|
|
74
89
|
def bzlmod_dependency?(dependency)
|
|
75
90
|
dependency.requirements.any? { |req| req[:file]&.end_with?("MODULE.bazel") }
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
# NOTE: This file was scaffolded automatically but is OPTIONAL.
|
|
5
|
-
# If you don't need custom metadata finding logic (changelogs, release notes, etc.),
|
|
6
|
-
# you can safely delete this file and remove the require from lib/dependabot/bazel.rb
|
|
7
|
-
|
|
8
4
|
require "dependabot/metadata_finders"
|
|
9
5
|
require "dependabot/metadata_finders/base"
|
|
10
6
|
|
|
@@ -13,14 +9,102 @@ module Dependabot
|
|
|
13
9
|
class MetadataFinder < Dependabot::MetadataFinders::Base
|
|
14
10
|
extend T::Sig
|
|
15
11
|
|
|
12
|
+
require_relative "update_checker/registry_client"
|
|
13
|
+
|
|
14
|
+
GITHUB_URL_PATTERNS = T.let(
|
|
15
|
+
[
|
|
16
|
+
%r{github\.com/([^/]+)/([^/]+)/archive},
|
|
17
|
+
%r{github\.com/([^/]+)/([^/]+)/releases},
|
|
18
|
+
%r{github\.com/([^/]+)/([^/]+)}
|
|
19
|
+
].freeze,
|
|
20
|
+
T::Array[Regexp]
|
|
21
|
+
)
|
|
22
|
+
|
|
16
23
|
private
|
|
17
24
|
|
|
18
25
|
sig { override.returns(T.nilable(Dependabot::Source)) }
|
|
19
26
|
def look_up_source
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
case source_type
|
|
28
|
+
when :bazel_dep
|
|
29
|
+
find_source_from_bcr
|
|
30
|
+
when :http_archive
|
|
31
|
+
find_source_from_http_archive
|
|
32
|
+
when :git_repository
|
|
33
|
+
find_source_from_git_repository
|
|
34
|
+
when :unknown
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
sig { returns(Symbol) }
|
|
40
|
+
def source_type
|
|
41
|
+
return :bazel_dep if dependency.requirements.empty?
|
|
42
|
+
return :bazel_dep if dependency.requirements.any? { |r| r[:source].nil? }
|
|
43
|
+
|
|
44
|
+
source_details = dependency.requirements.first&.dig(:source)
|
|
45
|
+
return :bazel_dep unless source_details
|
|
46
|
+
|
|
47
|
+
case source_details[:type]
|
|
48
|
+
when "http_archive" then :http_archive
|
|
49
|
+
when "git_repository" then :git_repository
|
|
50
|
+
else :unknown
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
sig { returns(T.nilable(Dependabot::Source)) }
|
|
55
|
+
def find_source_from_bcr
|
|
56
|
+
version = dependency.version
|
|
57
|
+
return nil unless version
|
|
58
|
+
|
|
59
|
+
source_info = registry_client.get_source(dependency.name, version)
|
|
60
|
+
url = source_info&.dig("url")
|
|
61
|
+
return nil unless url
|
|
62
|
+
|
|
63
|
+
source_from_url(url)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
sig { returns(T.nilable(Dependabot::Source)) }
|
|
67
|
+
def find_source_from_http_archive
|
|
68
|
+
url = dependency.requirements.first&.dig(:source, :url)
|
|
69
|
+
return nil unless url
|
|
70
|
+
|
|
71
|
+
source_from_url(url)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
sig { returns(T.nilable(Dependabot::Source)) }
|
|
75
|
+
def find_source_from_git_repository
|
|
76
|
+
remote_url = dependency.requirements.first&.dig(:source, :remote)
|
|
77
|
+
return nil unless remote_url
|
|
78
|
+
|
|
79
|
+
Dependabot::Source.from_url(remote_url)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
sig { params(url: String).returns(T.nilable(Dependabot::Source)) }
|
|
83
|
+
def source_from_url(url)
|
|
84
|
+
extract_github_source_from_url(url) || Dependabot::Source.from_url(url)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
sig { params(url: String).returns(T.nilable(Dependabot::Source)) }
|
|
88
|
+
def extract_github_source_from_url(url)
|
|
89
|
+
GITHUB_URL_PATTERNS.each do |pattern|
|
|
90
|
+
match = url.match(pattern)
|
|
91
|
+
next unless match
|
|
92
|
+
|
|
93
|
+
repo_url = "https://github.com/#{match[1]}/#{match[2]}"
|
|
94
|
+
source = Dependabot::Source.from_url(repo_url)
|
|
95
|
+
return source if source
|
|
96
|
+
end
|
|
97
|
+
|
|
22
98
|
nil
|
|
23
99
|
end
|
|
100
|
+
|
|
101
|
+
sig { returns(Dependabot::Bazel::UpdateChecker::RegistryClient) }
|
|
102
|
+
def registry_client
|
|
103
|
+
@registry_client ||= T.let(
|
|
104
|
+
Dependabot::Bazel::UpdateChecker::RegistryClient.new(credentials: credentials),
|
|
105
|
+
T.nilable(Dependabot::Bazel::UpdateChecker::RegistryClient)
|
|
106
|
+
)
|
|
107
|
+
end
|
|
24
108
|
end
|
|
25
109
|
end
|
|
26
110
|
end
|
|
@@ -8,10 +8,11 @@ require "dependabot/shared_helpers"
|
|
|
8
8
|
require "dependabot/clients/github_with_retries"
|
|
9
9
|
require "dependabot/dependency"
|
|
10
10
|
require "dependabot/errors"
|
|
11
|
+
require "dependabot/bazel/update_checker"
|
|
11
12
|
|
|
12
13
|
module Dependabot
|
|
13
14
|
module Bazel
|
|
14
|
-
class UpdateChecker
|
|
15
|
+
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
|
15
16
|
class RegistryClient
|
|
16
17
|
extend T::Sig
|
|
17
18
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "dependabot/bazel/update_checker"
|
|
5
|
+
|
|
4
6
|
module Dependabot
|
|
5
7
|
module Bazel
|
|
6
|
-
class UpdateChecker
|
|
8
|
+
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
|
7
9
|
class RequirementsUpdater
|
|
8
10
|
extend T::Sig
|
|
9
11
|
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
# NOTE: This file was scaffolded automatically but is OPTIONAL.
|
|
5
|
-
# If your ecosystem uses standard semantic versioning without special logic,
|
|
6
|
-
# you can safely delete this file and remove the require from lib/dependabot/bazel.rb
|
|
7
|
-
|
|
8
4
|
require "dependabot/version"
|
|
9
5
|
require "dependabot/utils"
|
|
10
6
|
|
|
@@ -13,9 +9,13 @@ module Dependabot
|
|
|
13
9
|
class Version < Dependabot::Version
|
|
14
10
|
extend T::Sig
|
|
15
11
|
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
12
|
+
# Bazel uses semantic versioning with hyphens for pre-release versions (e.g., "1.7.0-rc4")
|
|
13
|
+
# Dependabot::Version normalizes these to dot notation with "pre" prefix (e.g., "1.7.0.pre.rc4")
|
|
14
|
+
# We need to preserve the original format for Bazel Central Registry compatibility
|
|
15
|
+
sig { override.returns(String) }
|
|
16
|
+
def to_s
|
|
17
|
+
@original_version
|
|
18
|
+
end
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
data/lib/dependabot/bazel.rb
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
# These all need to be required so the various classes can be registered in a
|
|
5
5
|
# lookup table of package manager names to concrete classes.
|
|
6
|
-
require "dependabot/bazel/language"
|
|
7
|
-
require "dependabot/bazel/package_manager"
|
|
8
6
|
require "dependabot/bazel/file_fetcher"
|
|
9
7
|
require "dependabot/bazel/file_parser"
|
|
10
8
|
require "dependabot/bazel/update_checker"
|
|
11
9
|
require "dependabot/bazel/file_updater"
|
|
10
|
+
|
|
11
|
+
require "dependabot/bazel/language"
|
|
12
|
+
require "dependabot/bazel/package_manager"
|
|
12
13
|
require "dependabot/bazel/metadata_finder"
|
|
13
14
|
require "dependabot/bazel/version"
|
|
14
15
|
require "dependabot/bazel/requirement"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-bazel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.347.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.347.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.347.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -248,6 +248,7 @@ files:
|
|
|
248
248
|
- lib/dependabot/bazel/file_updater.rb
|
|
249
249
|
- lib/dependabot/bazel/file_updater/bzlmod_file_updater.rb
|
|
250
250
|
- lib/dependabot/bazel/file_updater/declaration_parser.rb
|
|
251
|
+
- lib/dependabot/bazel/file_updater/lockfile_updater.rb
|
|
251
252
|
- lib/dependabot/bazel/file_updater/workspace_file_updater.rb
|
|
252
253
|
- lib/dependabot/bazel/language.rb
|
|
253
254
|
- lib/dependabot/bazel/metadata_finder.rb
|
|
@@ -262,7 +263,7 @@ licenses:
|
|
|
262
263
|
- MIT
|
|
263
264
|
metadata:
|
|
264
265
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
265
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
266
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.347.0
|
|
266
267
|
rdoc_options: []
|
|
267
268
|
require_paths:
|
|
268
269
|
- lib
|