-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
Expand file tree
/
Copy pathjava.rake
More file actions
377 lines (314 loc) · 13.2 KB
/
java.rake
File metadata and controls
377 lines (314 loc) · 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# frozen_string_literal: true
require 'base64'
require 'net/http'
# use #java_release_targets to access this list
JAVA_RELEASE_TARGETS = %w[
//java/src/org/openqa/selenium/chrome:chrome.publish
//java/src/org/openqa/selenium/chromium:chromium.publish
//java/src/org/openqa/selenium/devtools/v146:v146.publish
//java/src/org/openqa/selenium/devtools/v147:v147.publish
//java/src/org/openqa/selenium/devtools/v148:v148.publish
//java/src/org/openqa/selenium/edge:edge.publish
//java/src/org/openqa/selenium/firefox:firefox.publish
//java/src/org/openqa/selenium/grid/node/kubernetes:kubernetes.publish
//java/src/org/openqa/selenium/grid/sessionmap/jdbc:jdbc.publish
//java/src/org/openqa/selenium/grid/sessionmap/redis:redis.publish
//java/src/org/openqa/selenium/grid:bom-dependencies.publish
//java/src/org/openqa/selenium/grid:bom.publish
//java/src/org/openqa/selenium/grid:grid.publish
//java/src/org/openqa/selenium/ie:ie.publish
//java/src/org/openqa/selenium/json:json.publish
//java/src/org/openqa/selenium/manager:manager.publish
//java/src/org/openqa/selenium/os:os.publish
//java/src/org/openqa/selenium/remote/http:http.publish
//java/src/org/openqa/selenium/remote:remote.publish
//java/src/org/openqa/selenium/safari:safari.publish
//java/src/org/openqa/selenium/support:support.publish
//java/src/org/openqa/selenium:client-combined.publish
//java/src/org/openqa/selenium:core.publish
].freeze
def java_version
File.foreach('java/version.bzl') do |line|
return line.split('=').last.strip.tr('"', '') if line.include?('SE_VERSION')
end
end
def java_release_targets
unless @targets_verified
verify_java_release_targets
@targets_verified = true
end
JAVA_RELEASE_TARGETS
end
def verify_java_release_targets
query = 'kind(maven_publish, set(//java/... //third_party/...))'
current_targets = []
Bazel.execute('query', [], query) do |output|
current_targets = output.lines.map(&:strip).reject(&:empty?).select { |line| line.start_with?('//') }
end
obsolete_targets = JAVA_RELEASE_TARGETS - current_targets
unlisted_targets = current_targets - JAVA_RELEASE_TARGETS
return if obsolete_targets.empty? && unlisted_targets.empty?
error_message = 'Java release targets are out of sync with Bazel query results.'
unless obsolete_targets.empty?
error_message += "\nObsolete targets (in list but not in Bazel): #{obsolete_targets.join(', ')}"
end
unless unlisted_targets.empty?
error_message += "\nMissing targets (in Bazel but not in list): #{unlisted_targets.join(', ')}"
end
raise error_message
end
def read_m2_user_pass
settings_path = File.join(Dir.home, '.m2', 'settings.xml')
unless File.exist?(settings_path)
warn "Maven settings file not found at #{settings_path}"
return
end
puts 'Maven environment variables not set, inspecting ~/.m2/settings.xml.'
settings = File.read(settings_path)
found_section = false
settings.each_line do |line|
if !found_section
found_section = line.include? '<id>central</id>'
elsif line.include?('<username>')
ENV['MAVEN_USER'] = line[%r{<username>(.*?)</username>}, 1]
elsif line.include?('<password>')
ENV['MAVEN_PASSWORD'] = line[%r{<password>(.*?)</password>}, 1]
end
break if ENV['MAVEN_PASSWORD'] && ENV['MAVEN_USER']
end
end
def sonatype_auth_token
read_m2_user_pass unless ENV['MAVEN_PASSWORD'] && ENV['MAVEN_USER']
Base64.strict_encode64("#{ENV.fetch('MAVEN_USER')}:#{ENV.fetch('MAVEN_PASSWORD')}")
end
def trigger_sonatype_publish(token)
puts 'Triggering Sonatype upload with automatic publishing...'
uri = URI('https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/org.seleniumhq?publishing_type=automatic')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic #{token}"
req['Accept'] = '*/*'
req['Content-Length'] = '0'
begin
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true,
open_timeout: 10, read_timeout: 180) do |http|
http.request(req)
end
rescue Net::ReadTimeout, Net::OpenTimeout => e
warn <<~MSG
Request timed out.
The deployment may still have been created on the server.
Check https://central.sonatype.com/publishing/deployments for status.
MSG
raise e
end
unless res.is_a?(Net::HTTPSuccess)
warn "Failed to trigger upload (HTTP #{res.code}): #{res.body}"
exit(1)
end
puts 'Upload triggered — Sonatype will automatically validate and publish.'
end
desc 'Build Java Client Jars'
task :build do |_task, arguments|
java_release_targets.each { |target| Bazel.execute('build', arguments.to_a, target) }
end
desc 'Build the selenium client jars'
task :client do |_task, arguments|
Bazel.execute('build', arguments.to_a, '//java/src/org/openqa/selenium:client-combined')
end
desc 'Build Grid Server'
task :grid do |_task, arguments|
Bazel.execute('build', arguments.to_a, '//java/src/org/openqa/selenium/grid:executable-grid')
end
desc 'Package Java bindings and grid into releasable packages and stage for release'
task :package do |_task, arguments|
args = arguments.to_a.empty? ? ['--config=release'] : arguments.to_a
Bazel.execute('build', args, '//java/src/org/openqa/selenium:client-zip')
Bazel.execute('build', args, '//java/src/org/openqa/selenium/grid:server-zip')
Bazel.execute('build', args, '//java/src/org/openqa/selenium/grid:executable-grid')
mkdir_p 'build/dist'
Dir.glob('build/dist/*{java,server}*').each { |file| FileUtils.rm_f(file) }
FileUtils.copy('bazel-bin/java/src/org/openqa/selenium/grid/server-zip.zip',
"build/dist/selenium-server-#{java_version}.zip")
FileUtils.chmod(0o644, "build/dist/selenium-server-#{java_version}.zip")
FileUtils.copy('bazel-bin/java/src/org/openqa/selenium/client-zip.zip',
"build/dist/selenium-java-#{java_version}.zip")
FileUtils.chmod(0o644, "build/dist/selenium-java-#{java_version}.zip")
FileUtils.copy('bazel-bin/java/src/org/openqa/selenium/grid/selenium',
"build/dist/selenium-server-#{java_version}.jar")
FileUtils.chmod(0o755, "build/dist/selenium-server-#{java_version}.jar")
end
desc 'Validate Java release credentials'
task :check_credentials do |_task, arguments|
nightly = arguments.to_a.include?('nightly')
has_env = (ENV['MAVEN_USER'] || ENV.fetch('SEL_M2_USER',
nil)) && (ENV['MAVEN_PASSWORD'] || ENV.fetch('SEL_M2_PASS', nil))
settings = File.join(Dir.home, '.m2', 'settings.xml')
has_file = File.exist?(settings) && File.read(settings).include?('<id>central</id>')
unless has_env || has_file
raise 'Missing Maven credentials: set MAVEN_USER/MAVEN_PASSWORD or configure ~/.m2/settings.xml'
end
next if nightly
has_gpg = system('which gpg >/dev/null 2>&1') || system('where gpg >NUL 2>&1')
raise 'Missing GPG: gpg command not found (required for signing releases)' unless has_gpg
end
desc 'Deploy all jars to Maven'
task :release do |_task, arguments|
args = arguments.to_a
nightly = args.delete('nightly')
Rake::Task['java:check_credentials'].invoke(*(nightly ? ['nightly'] : []))
ENV['MAVEN_USER'] ||= ENV.fetch('SEL_M2_USER', nil)
ENV['MAVEN_PASSWORD'] ||= ENV.fetch('SEL_M2_PASS', nil)
token = sonatype_auth_token
repo_domain = 'central.sonatype.com'
repo = if nightly
"#{repo_domain}/repository/maven-snapshots"
else
"ossrh-staging-api.#{repo_domain}/service/local/staging/deploy/maven2/"
end
ENV['MAVEN_REPO'] = "https://#{repo}"
ENV['GPG_SIGN'] = (!nightly).to_s
if nightly
puts 'Updating Java version to nightly...'
Rake::Task['java:version'].invoke('nightly')
end
puts 'Packaging Java artifacts...'
Rake::Task['java:package'].invoke('--config=release')
Rake::Task['java:build'].invoke('--config=release')
puts "Releasing Java artifacts to Maven repository at '#{ENV.fetch('MAVEN_REPO', nil)}'"
java_release_targets.each { |target| Bazel.execute('run', ['--config=release'], target) }
next if nightly
trigger_sonatype_publish(token)
end
desc 'Verify Java packages are published on Maven Central'
task :verify do
SeleniumRake.verify_package_published("https://repo1.maven.org/maven2/org/seleniumhq/selenium/selenium-java/#{java_version}/selenium-java-#{java_version}.pom")
end
desc 'Install jars to local m2 directory'
task :install do
java_release_targets.each do |p|
Bazel.execute('run',
['--define',
"maven_repo=file://#{Dir.home}/.m2/repository",
'--define',
'gpg_sign=false'],
p)
end
end
desc 'Generate and stage Java documentation'
task :docs do |_task, arguments|
if java_version.include?('SNAPSHOT') && !arguments.to_a.include?('force')
abort('Aborting documentation update: snapshot versions should not update docs.')
end
Rake::Task['java:docs_generate'].invoke
FileUtils.rm_rf('build/docs/api/java')
FileUtils.mkdir_p('build/docs/api/java')
out = 'bazel-bin/java/src/org/openqa/selenium/grid/all-javadocs.jar'
cmd = %(cd build/docs/api/java && jar xf "../../../../#{out}" 2>&1)
cmd = cmd.tr('/', '\\').tr(':', ';') if /mswin|msys|mingw32/.match?(RbConfig::CONFIG['host_os'])
raise 'could not unpack javadocs' unless system(cmd)
File.open('build/docs/api/java/stylesheet.css', 'a') do |file|
file.write(<<~STYLE
/* Custom selenium-specific styling */
.blink {
animation: 2s cubic-bezier(0.5, 0, 0.85, 0.85) infinite blink;
}
@keyframes blink {
50% {
opacity: 0;
}
}
STYLE
)
end
end
desc 'Generate Java documentation without staging'
task :docs_generate do
puts 'Generating Java documentation'
Bazel.execute('build', [], '//java/src/org/openqa/selenium/grid:all-javadocs')
end
desc 'Update Maven dependencies'
task :update do
puts 'Updating Maven dependencies'
# Make sure things are in a good state to start with
Rake::Task['java:pin'].invoke
file_path = 'MODULE.bazel'
content = File.read(file_path)
output = nil
Bazel.execute('run', [], '@maven//:outdated') do |out|
output = out
end
versions = output.scan(/(\S+) \[\S+ -> (\S+)\]/).to_h
versions.each do |artifact, version|
if artifact.match?('graphql') && version.match?(/\A(\d{6}-|0\.0\.0-)/)
# Maven Central indexes non-stable date-based artifacts that sort as "latest" which breaks for graphql
# https://github.com/graphql-java/graphql-java/discussions/3187
# Fall back to calling maven directly for this
version = maven_stable_release(artifact)
next if version.nil?
end
if artifact.start_with?('net.bytebuddy:') && version.match?(/-jdk\d/)
# Byte Buddy publishes -jdkN compat variants alongside regular releases; Maven sorts those
# variants as newer than the regular release. Selenium targets Java 8+ so we want the
# regular release without the JDK suffix.
# https://github.com/SeleniumHQ/selenium/issues/17355
version = maven_stable_release(artifact)
next if version.nil?
end
content.sub!(/#{Regexp.escape(artifact)}:([\d.-]+(?:[-.]?[A-Za-z0-9]+)*)/, "#{artifact}:#{version}")
end
File.write(file_path, content)
Rake::Task['java:pin'].reenable
Rake::Task['java:pin'].invoke
end
def maven_stable_release(artifact)
require 'rexml/document'
group_id, artifact_id = artifact.split(':', 2)
group_path = group_id.tr('.', '/')
uri = URI("https://repo1.maven.org/maven2/#{group_path}/#{artifact_id}/maven-metadata.xml")
xml = Net::HTTP.start(uri.host, uri.port, use_ssl: true, open_timeout: 5, read_timeout: 10) do |http|
http.get(uri.request_uri).body
end
doc = REXML::Document.new(xml)
versions = doc.elements.to_a('metadata/versioning/versions/version').map(&:text)
stable = versions.grep(/\A\d+\.\d+(\.\d+)*\z/)
stable.max_by { |v| Gem::Version.new(v) }
rescue StandardError => e
puts "WARNING — Failed to fetch stable release for #{artifact}: #{e.message}"
nil
end
desc 'Pin Maven dependencies'
task :pin do
args = ['--repo_env=RULES_JVM_EXTERNAL_REPIN=1']
Bazel.execute('run', args, '@maven//:pin')
end
desc 'Update Java changelog'
task :changelogs do
header = "v#{java_version}\n======"
SeleniumRake.update_changelog(java_version, 'java', 'java/src/org/', 'java/CHANGELOG', header)
end
desc 'Update Java version'
task :version, [:version] do |_task, arguments|
old_version = java_version
new_version = SeleniumRake.updated_version(old_version, arguments[:version], '-SNAPSHOT')
puts "Updating Java from #{old_version} to #{new_version}"
file = 'java/version.bzl'
text = File.read(file).gsub(old_version, new_version)
File.open(file, 'w') { |f| f.puts text }
end
desc 'Format Java code with google-java-format'
task :format do
puts ' Running google-java-format...'
java_files = Dir.glob(File.join(Dir.pwd, 'java', '**', '*.java'))
return if java_files.empty?
Tempfile.create('google-java-format-files') do |f|
java_files.each { |file| f.puts(file) }
f.flush
args = ['--', '--replace', "@#{f.path}"]
Bazel.execute('run', args, '//scripts:google-java-format')
end
end
# ErrorProne runs at build time, SpotBugs runs as test targets in RBE
desc 'Run Java linter (docs only, other linting happens during build/test)'
task :lint do
Rake::Task['java:docs_generate'].invoke
end