Skip to content

Commit 7f3e763

Browse files
committed
[bazel] Generate maven artifacts correctly
This also means that the maven_artifacts rule is responsible for publishing to a maven repo.
1 parent f77b937 commit 7f3e763

File tree

11 files changed

+215
-242
lines changed

11 files changed

+215
-242
lines changed

Rakefile

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,27 +100,27 @@ task '//java/client/test/org/openqa/selenium/environment/webserver:webserver:ube
100100
]
101101

102102
# Java targets required for release. These should all be java_export targets.
103-
# Generated from: bazel query 'kind(.*_publish, set(//java/... //third_party/...))'
103+
# Generated from: bazel query 'kind(maven_artifacts, set(//java/... //third_party/...))'
104104
JAVA_RELEASE_TARGETS = %w[
105-
//java/server/src/org/openqa/selenium/grid:grid-publish
106-
//java/server/src/com/thoughtworks/selenium/webdriven:webdriven-publish
107-
//java/client/src/org/openqa/selenium/support:support-publish
108-
//java/client/src/org/openqa/selenium/safari:safari-publish
109-
//java/client/src/org/openqa/selenium/remote/http:http-publish
110-
//java/client/src/org/openqa/selenium/remote:remote-publish
111-
//java/client/src/org/openqa/selenium/opera:opera-publish
112-
//java/client/src/org/openqa/selenium/lift:lift-publish
113-
//java/client/src/org/openqa/selenium/json:json-publish
114-
//java/client/src/org/openqa/selenium/ie:ie-publish
115-
//java/client/src/org/openqa/selenium/firefox/xpi:xpi-publish
116-
//java/client/src/org/openqa/selenium/firefox:firefox-publish
117-
//java/client/src/org/openqa/selenium/edge/edgehtml:edgehtml-publish
118-
//java/client/src/org/openqa/selenium/edge:edgeium-publish
119-
//java/client/src/org/openqa/selenium/devtools:devtools-publish
120-
//java/client/src/org/openqa/selenium/chromium:chromium-publish
121-
//java/client/src/org/openqa/selenium/chrome:chrome-publish
122-
//java/client/src/org/openqa/selenium:core-publish
123-
//java/client/src/org/openqa/selenium:client-combined-publish
105+
//java/client/src/org/openqa/selenium/chrome:chrome-maven-artifacts
106+
//java/client/src/org/openqa/selenium/chromium:chromium-maven-artifacts
107+
//java/client/src/org/openqa/selenium/devtools:devtools-maven-artifacts
108+
//java/client/src/org/openqa/selenium/edge/edgehtml:edgehtml-maven-artifacts
109+
//java/client/src/org/openqa/selenium/edge:edgeium-maven-artifacts
110+
//java/client/src/org/openqa/selenium/firefox/xpi:xpi-maven-artifacts
111+
//java/client/src/org/openqa/selenium/firefox:firefox-maven-artifacts
112+
//java/client/src/org/openqa/selenium/ie:ie-maven-artifacts
113+
//java/client/src/org/openqa/selenium/json:json-maven-artifacts
114+
//java/client/src/org/openqa/selenium/lift:lift-maven-artifacts
115+
//java/client/src/org/openqa/selenium/opera:opera-maven-artifacts
116+
//java/client/src/org/openqa/selenium/remote/http:http-maven-artifacts
117+
//java/client/src/org/openqa/selenium/remote:remote-maven-artifacts
118+
//java/client/src/org/openqa/selenium/safari:safari-maven-artifacts
119+
//java/client/src/org/openqa/selenium/support:support-maven-artifacts
120+
//java/client/src/org/openqa/selenium:client-combined-maven-artifacts
121+
//java/client/src/org/openqa/selenium:core-maven-artifacts
122+
//java/server/src/com/thoughtworks/selenium/webdriven:webdriven-maven-artifacts
123+
//java/server/src/org/openqa/selenium/grid:grid-maven-artifacts
124124
]
125125

126126
# Notice that because we're using rake, anything you can do in a normal rake

java/client/src/org/openqa/selenium/tools/javadoc/JavadocJarMaker.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import javax.tools.DocumentationTool;
66
import javax.tools.JavaFileObject;
77
import javax.tools.StandardJavaFileManager;
8+
import javax.tools.StandardLocation;
89
import javax.tools.ToolProvider;
910
import java.io.File;
1011
import java.io.IOException;
@@ -70,6 +71,7 @@ public static void main(String[] args) throws IOException {
7071
DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
7172
try (StandardJavaFileManager fileManager = tool.getStandardFileManager(null, Locale.getDefault(), StandardCharsets.UTF_8)) {
7273
fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, List.of(dir.toFile()));
74+
fileManager.setLocation(StandardLocation.CLASS_PATH, classpath.stream().map(Path::toFile).collect(Collectors.toSet()));
7375

7476
Set<JavaFileObject> sources = new HashSet<>();
7577
Set<String> topLevelPackages = new HashSet<>();
@@ -78,11 +80,23 @@ public static void main(String[] args) throws IOException {
7880
tempDirs.add(unpackTo);
7981
Set<String> fileNames = new HashSet<>();
8082
readSourceFiles(unpackTo, fileManager, sourceJars, sources, topLevelPackages, fileNames);
81-
List<String> options = new ArrayList<>(List.of("-html5", "-notimestamp", "-use", "-quiet", "-Xdoclint:-missing", "-encoding", "UTF8"));
83+
84+
// True if we're just exporting a set of modules
85+
if (sources.isEmpty()) {
86+
try (OutputStream os = Files.newOutputStream(out);
87+
ZipOutputStream zos = new ZipOutputStream(os)) {
88+
// It's enough to just create the thing
89+
}
90+
return;
91+
}
92+
93+
List<String> options = new ArrayList<>();
8294
if (!classpath.isEmpty()) {
8395
options.add("-cp");
84-
options.add(classpath.stream().map(Path::toAbsolutePath).map(String::valueOf).collect(Collectors.joining(File.pathSeparator)));
96+
options.add(classpath.stream().map(String::valueOf).collect(Collectors.joining(File.pathSeparator)));
8597
}
98+
options.addAll(List.of("-html5", "-notimestamp", "-use", "-quiet", "-Xdoclint:-missing", "-encoding", "UTF8"));
99+
86100

87101
Path outputTo = Files.createTempDirectory("output-dir");
88102
tempDirs.add(outputTo);
@@ -95,6 +109,7 @@ public static void main(String[] args) throws IOException {
95109
DocumentationTool.DocumentationTask task = tool.getTask(writer, fileManager, null, null, options, sources);
96110
Boolean result = task.call();
97111
if (result == null || !result) {
112+
System.err.println("javadoc " + String.join(" ", options));
98113
System.err.println(writer);
99114
return;
100115
}

java/client/src/org/openqa/selenium/tools/BUILD.bazel renamed to java/client/src/org/openqa/selenium/tools/maven/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ load("@rules_jvm_external//:defs.bzl", "artifact")
33
java_binary(
44
name = "MavenPublisher",
55
srcs = ["MavenPublisher.java"],
6-
main_class = "org.openqa.selenium.tools.MavenPublisher",
6+
main_class = "org.openqa.selenium.tools.maven.MavenPublisher",
77
visibility = ["//visibility:public"],
88
deps = [
99
"//java/client/src/org/openqa/selenium/remote",

java/client/src/org/openqa/selenium/tools/MavenPublisher.java renamed to java/client/src/org/openqa/selenium/tools/maven/MavenPublisher.java

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
package org.openqa.selenium.tools;
18+
package org.openqa.selenium.tools.maven;
1919

2020
import com.google.common.base.Splitter;
2121
import com.google.common.collect.ImmutableList;
22-
import com.google.common.hash.HashCode;
2322
import com.google.common.hash.Hashing;
2423
import com.google.common.io.ByteStreams;
2524
import org.openqa.selenium.os.CommandLine;
@@ -52,7 +51,7 @@
5251
public class MavenPublisher {
5352

5453
private static final Logger LOG = Logger.getLogger(MavenPublisher.class.getName());
55-
private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
54+
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(1);
5655

5756
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException, TimeoutException {
5857
String repo = args[0];
@@ -73,12 +72,14 @@ public static void main(String[] args) throws IOException, InterruptedException,
7372
Path pom = Paths.get(args[5]);
7473
Path binJar = Paths.get(args[6]);
7574
Path srcJar = Paths.get(args[7]);
75+
Path docJar = Paths.get(args[8]);
7676

7777
try {
7878
CompletableFuture<Void> all = CompletableFuture.allOf(
7979
upload(repo, credentials, coords, ".pom", pom),
8080
upload(repo, credentials, coords, ".jar", binJar),
81-
upload(repo, credentials, coords, "-sources.jar", srcJar)
81+
upload(repo, credentials, coords, "-sources.jar", srcJar),
82+
upload(repo, credentials, coords, "-javadoc.jar", docJar)
8283
);
8384
all.get(30, MINUTES);
8485
} finally {
@@ -102,38 +103,33 @@ private static CompletableFuture<Void> upload(
102103
coords.artifactId,
103104
coords.version);
104105

105-
// Assume we can hold the thing we're uploading in memory as it makes life a lot easier
106-
byte[] bytes = Files.readAllBytes(item);
107-
HashCode md5 = Hashing.md5().hashBytes(bytes);
108-
HashCode sha1 = Hashing.sha1().hashBytes(bytes);
106+
byte[] toHash = Files.readAllBytes(item);
107+
Path md5 = Files.createTempFile(item.getFileName().toString(), ".md5");
108+
Files.write(md5, Hashing.md5().hashBytes(toHash).toString().getBytes(UTF_8));
109+
110+
Path sha1 = Files.createTempFile(item.getFileName().toString(), ".sha1");
111+
Files.write(sha1, Hashing.sha1().hashBytes(toHash).toString().getBytes(UTF_8));
109112

110113
List<CompletableFuture<?>> uploads = new ArrayList<>();
111-
uploads.add(upload(String.format("%s%s", base, append), credentials, bytes));
112-
uploads.add(upload(String.format("%s%s.md5", base, append), credentials, md5.toString().getBytes(UTF_8)));
113-
uploads.add(upload(String.format("%s%s.sha1", base, append), credentials, sha1.toString().getBytes(UTF_8)));
114+
uploads.add(upload(String.format("%s%s", base, append), credentials, item));
115+
uploads.add(upload(String.format("%s%s.md5", base, append), credentials, md5));
116+
uploads.add(upload(String.format("%s%s.sha1", base, append), credentials, sha1));
114117

115118
if (credentials.getGpgSign()) {
116-
String filename = String.format("%s-%s%s", coords.artifactId, coords.version, append);
117-
118-
byte[] bytesSignature = sign(credentials, filename, Files.readAllBytes(item));
119-
uploads.add(upload(String.format("%s%s.asc", base, append), credentials, bytesSignature));
120-
121-
byte[] md5Signature = sign(credentials, filename + ".md5", md5.toString().getBytes(UTF_8));
122-
uploads.add(upload(String.format("%s%s.md5.asc", base, append), credentials, md5Signature));
123-
124-
byte[] sha1Signature = sign(credentials, filename + ".sha1", sha1.toString().getBytes(UTF_8));
125-
uploads.add(upload(String.format("%s%s.sha1.asc", base, append), credentials, sha1Signature));
119+
uploads.add(upload(String.format("%s%s.asc", base, append), credentials, sign(item)));
120+
uploads.add(upload(String.format("%s%s.md5.asc", base, append), credentials, sign(md5)));
121+
uploads.add(upload(String.format("%s%s.sha1.asc", base, append), credentials, sign(sha1)));
126122
}
127123

128124
return CompletableFuture.allOf(uploads.toArray(new CompletableFuture<?>[0]));
129125
}
130126

131-
private static CompletableFuture<Void> upload(String targetUrl, Credentials credentials, byte[] contents) {
127+
private static CompletableFuture<Void> upload(String targetUrl, Credentials credentials, Path toUpload) {
132128
Callable<Void> callable;
133129
if (targetUrl.startsWith("http://") || targetUrl.startsWith("https://")) {
134-
callable = httpUpload(targetUrl, credentials, contents);
130+
callable = httpUpload(targetUrl, credentials, toUpload);
135131
} else {
136-
callable = writeFile(targetUrl, contents);
132+
callable = writeFile(targetUrl, toUpload);
137133
}
138134

139135
CompletableFuture<Void> toReturn = new CompletableFuture<>();
@@ -148,8 +144,9 @@ private static CompletableFuture<Void> upload(String targetUrl, Credentials cred
148144
return toReturn;
149145
}
150146

151-
private static Callable<Void> httpUpload(String targetUrl, Credentials credentials, byte[] contents) {
147+
private static Callable<Void> httpUpload(String targetUrl, Credentials credentials, Path toUpload) {
152148
return () -> {
149+
LOG.info(String.format("Uploading to %s", targetUrl));
153150
URL url = new URL(targetUrl);
154151

155152
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@@ -160,10 +157,12 @@ private static Callable<Void> httpUpload(String targetUrl, Credentials credentia
160157
String.format("%s:%s", credentials.getUser(), credentials.getPassword()).getBytes(US_ASCII));
161158
connection.setRequestProperty("Authorization", "BASIC " + basicAuth);
162159
}
163-
connection.setRequestProperty("Content-Length", "" + contents.length);
160+
connection.setRequestProperty("Content-Length", "" + Files.size(toUpload));
164161

165162
try (OutputStream out = connection.getOutputStream()) {
166-
out.write(contents);
163+
try (InputStream is = Files.newInputStream(toUpload)) {
164+
is.transferTo(out);
165+
}
167166

168167
int code = connection.getResponseCode();
169168

@@ -178,22 +177,26 @@ private static Callable<Void> httpUpload(String targetUrl, Credentials credentia
178177
}
179178
}
180179
}
180+
LOG.info(String.format("Upload to %s complete.", targetUrl));
181181
return null;
182182
};
183183
}
184184

185-
private static Callable<Void> writeFile(String targetUrl, byte[] contents) {
185+
private static Callable<Void> writeFile(String targetUrl, Path toUpload) {
186186
return () -> {
187+
LOG.info(String.format("Copying %s to %s", toUpload, targetUrl));
187188
Path path = Paths.get(new URL(targetUrl).toURI());
188189
Files.createDirectories(path.getParent());
189190
Files.deleteIfExists(path);
190-
Files.write(path, contents);
191+
Files.copy(toUpload, path);
191192

192193
return null;
193194
};
194195
}
195196

196-
private static byte[] sign(Credentials credentials, String fileName, byte[] data) throws IOException {
197+
private static Path sign(Path toSign) throws IOException {
198+
LOG.info("Signing " + toSign);
199+
197200
// Ideally, we'd use BouncyCastle for this, but for now brute force by assuming
198201
// the gpg binary is on the path
199202

@@ -203,21 +206,28 @@ private static byte[] sign(Credentials credentials, String fileName, byte[] data
203206
}
204207

205208
Path dir = Files.createTempDirectory("maven-sign");
206-
Path file = dir.resolve(fileName + ".asc");
209+
Path file = dir.resolve(toSign.getFileName() + ".asc");
207210

208211
List<String> args = ImmutableList.of(
209-
"gpg", "-ab", "--batch",
210-
"-o", file.toAbsolutePath().toString());
212+
"gpg", "--use-agent", "--armor", "--detach-sign", "--no-tty",
213+
"-o", file.toAbsolutePath().toString(), toSign.toAbsolutePath().toString());
211214

212215
CommandLine gpg = new CommandLine(args.toArray(new String[0]));
213216
gpg.execute();
214217
if (!gpg.isSuccessful()) {
215-
throw new IllegalStateException("Unable to sign: " + fileName + "\n" + gpg.getStdOut());
218+
throw new IllegalStateException("Unable to sign: " + toSign + "\n" + gpg.getStdOut());
219+
}
220+
221+
// Verify the signature
222+
CommandLine verify = new CommandLine(
223+
"gpg", "--verify", "--verbose", "--verbose",
224+
file.toAbsolutePath().toString(), toSign.toAbsolutePath().toString());
225+
verify.execute();
226+
if (!verify.isSuccessful()) {
227+
throw new IllegalStateException("Unable to verify signature of " + toSign + "\n" + gpg.getStdOut());
216228
}
217229

218-
byte[] bytes = Files.readAllBytes(file);
219-
Files.delete(file);
220-
return bytes;
230+
return file;
221231
}
222232

223233
private static class Coordinates {

java/private/common.bzl

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
load("//java/private:module.bzl", "JavaModuleInfo")
2+
13
MavenInfo = provider(
24
fields = {
35
"coordinates": "Maven coordinates of the library we're building (optional)",
@@ -20,8 +22,6 @@ def _has_maven_deps_impl(target, ctx):
2022
exports = getattr(ctx.rule.attr, "exports", [])
2123
rt_deps = getattr(ctx.rule.attr, "runtime_deps", [])
2224
all_deps = deps + exports + rt_deps
23-
if getattr(ctx.rule.attr, "target", None):
24-
all_deps.append(getattr(ctx.rule.attr, "target"))
2525

2626
coordinates = read_coordinates(tags)
2727
if "maven:compile_only" in tags:
@@ -31,6 +31,7 @@ def _has_maven_deps_impl(target, ctx):
3131
artifact_jars = depset(),
3232
source_jars = depset(),
3333
transitive_maven_deps = depset(),
34+
transitive_runtime_jars = depset(),
3435
)
3536

3637
# Find all the deps that have coordinates
@@ -53,13 +54,24 @@ def _has_maven_deps_impl(target, ctx):
5354
infos = []
5455
coordinate = coordinates[0] if len(coordinates) > 0 else None
5556

56-
info = MavenInfo(
57-
coordinates = coordinate,
58-
maven_deps = maven_deps,
59-
artifact_jars = artifact_jars,
60-
source_jars = source_jars,
61-
transitive_maven_deps = transitive_maven_deps,
62-
)
57+
if JavaModuleInfo in target:
58+
info = MavenInfo(
59+
coordinates = coordinate,
60+
maven_deps = maven_deps,
61+
artifact_jars = depset(target[JavaInfo].runtime_output_jars),
62+
source_jars = depset(target[JavaInfo].source_jars),
63+
transitive_maven_deps = transitive_maven_deps,
64+
transitive_runtime_jars = depset(target[JavaInfo].transitive_runtime_jars.to_list(), transitive = [info.transitive_runtime_jars for info in all_infos])
65+
)
66+
else:
67+
info = MavenInfo(
68+
coordinates = coordinate,
69+
maven_deps = maven_deps,
70+
artifact_jars = artifact_jars,
71+
source_jars = source_jars,
72+
transitive_maven_deps = transitive_maven_deps,
73+
transitive_runtime_jars = depset(target[JavaInfo].transitive_runtime_jars.to_list(), transitive = [info.transitive_runtime_jars for info in all_infos])
74+
)
6375
infos.append(info)
6476

6577
return infos
@@ -70,7 +82,6 @@ has_maven_deps = aspect(
7082
"deps",
7183
"exports",
7284
"runtime_deps",
73-
"target",
7485
],
7586
)
7687

0 commit comments

Comments
 (0)