Skip to content

Commit 61bde1b

Browse files
authored
Merge pull request #62 from confluentinc/vinnybod/upstream-merge-20250828
Merge upstream 2025/08/28
2 parents 1250fea + 2ef68be commit 61bde1b

File tree

16 files changed

+91
-213
lines changed

16 files changed

+91
-213
lines changed

docs/api.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ Generate a javadoc from all the `deps`
4949
load("@rules_jvm_external//:defs.bzl", "java_export")
5050

5151
java_export(<a href="#java_export-name">name</a>, <a href="#java_export-maven_coordinates">maven_coordinates</a>, <a href="#java_export-manifest_entries">manifest_entries</a>, <a href="#java_export-deploy_env">deploy_env</a>, <a href="#java_export-excluded_workspaces">excluded_workspaces</a>, <a href="#java_export-exclusions">exclusions</a>,
52-
<a href="#java_export-pom_template">pom_template</a>, <a href="#java_export-allowed_duplicate_names">allowed_duplicate_names</a>, <a href="#java_export-allowed_duplicate_names">allowed_duplicate_names</a>, <ahref="#java_export-visibility">visibility</a>, <a href="#java_export-tags">tags</a>, <a href="#java_export-testonly">testonly</a>, <a href="#java_export-classifier_artifacts">classifier_artifacts</a>,
53-
<a href="#java_export-publish_maven_metadata">publish_maven_metadata</a>,
54-
<a href="#java_export-kwargs">kwargs</a>)
52+
<a href="#java_export-pom_template">pom_template</a>, <a href="#java_export-allowed_duplicate_names">allowed_duplicate_names</a>, <a href="#java_export-visibility">visibility</a>, <a href="#java_export-tags">tags</a>, <a href="#java_export-testonly">testonly</a>, <a href="#java_export-classifier_artifacts">classifier_artifacts</a>,
53+
<a href="#java_export-publish_maven_metadata">publish_maven_metadata</a>, <a href="#java_export-kwargs">kwargs</a>)
5554
</pre>
5655

5756
Extends `java_library` to allow maven artifacts to be uploaded.
@@ -114,7 +113,7 @@ Generated rules:
114113
| <a id="java_export-tags"></a>tags | <p align="center"> - </p> | `[]` |
115114
| <a id="java_export-testonly"></a>testonly | <p align="center"> - </p> | `None` |
116115
| <a id="java_export-classifier_artifacts"></a>classifier_artifacts | A dict of classifier -> artifact of additional artifacts to publish to Maven. | `{}` |
117-
| <a id="java_export-publish_maven_metadata"></a>publish_maven_metadata | Whether to publish a maven-metadata.xml and so may contain any valid parameter for that rule. | `True` |
116+
| <a id="java_export-publish_maven_metadata"></a>publish_maven_metadata | Whether to publish a maven-metadata.xml to remote repository. Some repositories (like AWS CodeArtifact) require the client to publish this file. It is disabled by default. | `True` |
118117
| <a id="java_export-kwargs"></a>kwargs | <p align="center"> - </p> | none |
119118

120119

private/dependency_tree_parser.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ load(
2929
"strip_packaging_and_classifier_and_version",
3030
"to_repository_name",
3131
)
32-
load("//private/lib:coordinates.bzl", "unpack_coordinates", "to_purl")
32+
load("//private/lib:coordinates.bzl", "to_purl", "unpack_coordinates")
3333
load("//private/lib:urls.bzl", "scheme_and_host")
3434

3535
def _genrule_copy_artifact_from_http_file(artifact, visibilities):

private/rules/coursier.bzl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ def _java_path(repository_ctx):
283283
def _generate_java_jar_command(repository_ctx, jar_path):
284284
coursier_opts = repository_ctx.os.environ.get("COURSIER_OPTS", "")
285285
coursier_opts = coursier_opts.split(" ") if len(coursier_opts) > 0 else []
286+
287+
# if coursier OOMs from a large dependency tree, have it crash instead of hanging
288+
coursier_opts.append("-XX:+ExitOnOutOfMemoryError")
286289
java_path = _java_path(repository_ctx)
287290

288291
if java_path != None:

private/rules/java_export.bzl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,9 @@ def java_export(
9393
end of the package name. For example, `com.example.*` will include all the subpackages of `com.example`, while
9494
`com.example` will include only the files directly in `com.example`
9595
visibility: The visibility of the target
96+
publish_maven_metadata: Whether to publish a maven-metadata.xml to remote repository. Some repositories
97+
(like AWS CodeArtifact) require the client to publish this file. It is disabled by default.
9698
kwargs: These are passed to [`java_library`](https://bazel.build/reference/be/java#java_library),
97-
publish_maven_metadata: Whether to publish a maven-metadata.xml
9899
and so may contain any valid parameter for that rule.
99100
"""
100101

@@ -241,7 +242,8 @@ def maven_export(
241242
end of the package name. For example, `com.example.*` will include all the subpackages of `com.example`, while
242243
`com.example` will include only the files directly in `com.example`
243244
visibility: The visibility of the target
244-
publish_maven_metadata: Whether to publish a maven-metadata.xml
245+
publish_maven_metadata: Whether to publish a maven-metadata.xml to remote repository. Some repositories
246+
(like AWS CodeArtifact) require the client to publish this file. It is disabled by default.
245247
kwargs: These are passed to [`java_library`](https://bazel.build/reference/be/java#java_library),
246248
and so may contain any valid parameter for that rule.
247249
"""

private/tools/java/com/github/bazelbuild/rules_jvm_external/javadoc/CreateJar.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public static void main(String[] args) throws IOException {
5353

5454
public static void createJar(Path out, Path inputDir) throws IOException {
5555
try (OutputStream os = Files.newOutputStream(out);
56-
ZipOutputStream zos = new ZipOutputStream(os);
57-
Stream<Path> walk = Files.walk(inputDir)) {
56+
ZipOutputStream zos = new ZipOutputStream(os);
57+
Stream<Path> walk = Files.walk(inputDir)) {
5858

5959
walk.sorted(Comparator.naturalOrder())
6060
.forEachOrdered(

private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ java_binary(
1111
visibility = ["//visibility:public"],
1212
deps = [
1313
"//private/tools/java/com/github/bazelbuild/rules_jvm_external",
14+
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc",
15+
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote",
16+
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui",
1417
artifact(
1518
"software.amazon.awssdk:sdk-core",
1619
repository_name = "rules_jvm_external_deps",
@@ -47,10 +50,6 @@ java_binary(
4750
"org.bouncycastle:bcpg-jdk15on",
4851
repository_name = "rules_jvm_external_deps",
4952
),
50-
artifact(
51-
"com.google.http-client:google-http-client",
52-
repository_name = "rules_jvm_external_deps",
53-
),
5453
artifact(
5554
"org.apache.maven:maven-repository-metadata",
5655
repository_name = "rules_jvm_external_deps",
@@ -70,20 +69,3 @@ java_binary(
7069
),
7170
],
7271
)
73-
74-
java_test(
75-
name = "MavenPublisherTest",
76-
srcs = [
77-
"MavenPublisherTest.java",
78-
],
79-
deps = [
80-
artifact(
81-
"org.apache.maven:maven-repository-metadata",
82-
repository_name = "rules_jvm_external_deps",
83-
),
84-
artifact(
85-
"junit:junit",
86-
repository_name = "regression_testing_coursier",
87-
),
88-
],
89-
)

private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java

Lines changed: 46 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,8 @@
2424
import static java.util.concurrent.TimeUnit.MINUTES;
2525

2626
import com.github.bazelbuild.rules_jvm_external.ByteStreams;
27-
import com.google.api.client.http.GenericUrl;
28-
import com.google.api.client.http.HttpRequest;
29-
import com.google.api.client.http.HttpResponse;
30-
import com.google.api.client.http.HttpResponseException;
31-
import com.google.api.client.http.HttpTransport;
32-
import com.google.api.client.http.javanet.NetHttpTransport;
27+
import com.github.bazelbuild.rules_jvm_external.resolver.netrc.Netrc;
28+
import com.github.bazelbuild.rules_jvm_external.resolver.remote.HttpDownloader;
3329
import com.google.auth.Credentials;
3430
import com.google.auth.oauth2.GoogleCredentials;
3531
import com.google.cloud.WriteChannel;
@@ -48,7 +44,6 @@
4844
import java.math.BigInteger;
4945
import java.net.HttpURLConnection;
5046
import java.net.URI;
51-
import java.net.URISyntaxException;
5247
import java.net.URL;
5348
import java.nio.channels.Channels;
5449
import java.nio.charset.StandardCharsets;
@@ -92,16 +87,25 @@ public class MavenPublisher {
9287
private static final String[] SUPPORTED_SCHEMES = {
9388
"file:/", "https://", "gs://", "s3://", "artifactregistry://"
9489
};
90+
private static final String[] SUPPORTED_UPLOAD_SCHEMES = {"file:/", "https://", "s3://"};
9591

9692
public static void main(String[] args)
9793
throws IOException, InterruptedException, ExecutionException, TimeoutException {
9894
String repo = System.getenv("MAVEN_REPO");
95+
boolean publishMavenMetadata = Boolean.parseBoolean(args[3]);
96+
9997
if (!isSchemeSupported(repo)) {
10098
throw new IllegalArgumentException(
10199
"Repository must be accessed via the supported schemes: "
102100
+ Arrays.toString(SUPPORTED_SCHEMES));
103101
}
104102

103+
if (!isUploadSchemeSupported(repo)) {
104+
throw new IllegalArgumentException(
105+
"Repository must be uploaded to via the supported schemes: "
106+
+ Arrays.toString(SUPPORTED_UPLOAD_SCHEMES));
107+
}
108+
105109
boolean gpgSign = Boolean.parseBoolean(System.getenv("GPG_SIGN"));
106110
Credentials credentials =
107111
new BasicAuthCredentials(System.getenv("MAVEN_USER"), System.getenv("MAVEN_PASSWORD"));
@@ -133,8 +137,6 @@ public static void main(String[] args)
133137
futures.add(upload(repo, credentials, coords, "." + ext, mainArtifact, signingMetadata));
134138
}
135139

136-
boolean publishMavenMetadata = Boolean.valueOf(args[3]);
137-
138140
if (args.length > 4 && !args[4].isEmpty()) {
139141
List<String> extraArtifactTuples = Splitter.onPattern(",").splitToList(args[4]);
140142
for (String artifactTuple : extraArtifactTuples) {
@@ -158,7 +160,9 @@ public static void main(String[] args)
158160

159161
// uploading the maven-metadata.xml signals to cut over to the new version, so it must be at
160162
// the end.
161-
if (publishMavenMetadata) {
163+
// publishing the file is opt-in for remote repositories, but always done for local file
164+
// repositories.
165+
if (publishMavenMetadata || repo.startsWith("file:/")) {
162166
all = all.thenCompose(Void -> uploadMavenMetadata(repo, credentials, coords));
163167
}
164168

@@ -184,18 +188,27 @@ private static boolean isSchemeSupported(String repo) {
184188
return false;
185189
}
186190

191+
private static boolean isUploadSchemeSupported(String repo) {
192+
for (String scheme : SUPPORTED_UPLOAD_SCHEMES) {
193+
if (repo.startsWith(scheme)) {
194+
return true;
195+
}
196+
}
197+
return false;
198+
}
199+
187200
/**
188201
* Download the pre-existing maven-metadata.xml file if it exists. If no such file exists, create
189202
* a default Metadata with the Coordinates provided.
190203
*/
191204
private static CompletableFuture<Metadata> downloadExistingMavenMetadata(
192-
String repo, Credentials credentials, Coordinates coords) {
205+
String repo, Coordinates coords) {
193206
String mavenMetadataUrl =
194207
String.format(
195208
"%s/%s/%s/maven-metadata.xml",
196209
repo.replaceAll("/$", ""), coords.groupId.replace('.', '/'), coords.artifactId);
197210

198-
return download(mavenMetadataUrl, credentials)
211+
return download(mavenMetadataUrl)
199212
.thenApply(
200213
optionalFileContents -> {
201214
try {
@@ -229,7 +242,7 @@ private static CompletableFuture<Void> uploadMavenMetadata(
229242
String.format(
230243
"%s/%s/%s/maven-metadata.xml",
231244
repo.replaceAll("/$", ""), coords.groupId.replace('.', '/'), coords.artifactId);
232-
return downloadExistingMavenMetadata(repo, credentials, coords)
245+
return downloadExistingMavenMetadata(repo, coords)
233246
.thenCompose(
234247
metadata -> {
235248
try {
@@ -301,44 +314,13 @@ private static CompletableFuture<Void> upload(
301314
MavenSigning.SigningMethod signingMethod = signingMetadata.signingMethod;
302315
if (signingMethod.equals(MavenSigning.SigningMethod.GPG)) {
303316
uploads.add(upload(String.format("%s%s.asc", base, append), credentials, gpg_sign(item)));
304-
uploads.add(upload(String.format("%s%s.md5.asc", base, append), credentials, gpg_sign(md5)));
305-
uploads.add(
306-
upload(String.format("%s%s.sha1.asc", base, append), credentials, gpg_sign(sha1)));
307-
uploads.add(
308-
upload(String.format("%s%s.sha256.asc", base, append), credentials, gpg_sign(sha256)));
309-
uploads.add(
310-
upload(String.format("%s%s.sha512.asc", base, append), credentials, gpg_sign(sha512)));
311317
} else if (signingMethod.equals(MavenSigning.SigningMethod.PGP)) {
312318
uploads.add(
313319
upload(
314320
String.format("%s%s.asc", base, append),
315321
credentials,
316322
in_memory_pgp_sign(
317323
item, signingMetadata.signingKey, signingMetadata.signingPassword)));
318-
uploads.add(
319-
upload(
320-
String.format("%s%s.md5.asc", base, append),
321-
credentials,
322-
in_memory_pgp_sign(
323-
md5, signingMetadata.signingKey, signingMetadata.signingPassword)));
324-
uploads.add(
325-
upload(
326-
String.format("%s%s.sha1.asc", base, append),
327-
credentials,
328-
in_memory_pgp_sign(
329-
sha1, signingMetadata.signingKey, signingMetadata.signingPassword)));
330-
uploads.add(
331-
upload(
332-
String.format("%s%s.sha256.asc", base, append),
333-
credentials,
334-
in_memory_pgp_sign(
335-
sha256, signingMetadata.signingKey, signingMetadata.signingPassword)));
336-
uploads.add(
337-
upload(
338-
String.format("%s%s.sha512.asc", base, append),
339-
credentials,
340-
in_memory_pgp_sign(
341-
sha512, signingMetadata.signingKey, signingMetadata.signingPassword)));
342324
}
343325

344326
return CompletableFuture.allOf(uploads.toArray(new CompletableFuture<?>[0]));
@@ -374,16 +356,15 @@ private static String toHexS(String fmt, String algorithm, byte[] toHash) {
374356
* Attempts to download the file at the given targetUrl. Valid protocols are: http(s), file, and
375357
* s3 at the moment.
376358
*/
377-
private static CompletableFuture<Optional<String>> download(
378-
String targetUrl, Credentials credentials) {
359+
private static CompletableFuture<Optional<String>> download(String targetUrl) {
379360
if (targetUrl.startsWith("http")) {
380-
return httpDownload(targetUrl, credentials);
381-
} else if (targetUrl.startsWith("file://")) {
361+
return httpDownload(targetUrl);
362+
} else if (targetUrl.startsWith("file:/")) {
382363
return fileDownload(targetUrl);
383364
} else if (targetUrl.startsWith("s3://")) {
384365
return s3Download(targetUrl);
385366
} else {
386-
throw new IllegalArgumentException("Unsupported protocol for download.");
367+
throw new IllegalArgumentException("Unsupported protocol for download: " + targetUrl);
387368
}
388369
}
389370

@@ -392,7 +373,7 @@ private static CompletableFuture<Optional<String>> s3Download(String targetUrl)
392373
() -> {
393374
S3Client s3Client = S3Client.create();
394375
try {
395-
URI s3Uri = new URI(targetUrl);
376+
URI s3Uri = URI.create(targetUrl);
396377
String bucketName = s3Uri.getHost();
397378
String key = s3Uri.getPath().substring(1);
398379
GetObjectRequest request =
@@ -402,8 +383,6 @@ private static CompletableFuture<Optional<String>> s3Download(String targetUrl)
402383
CharStreams.toString(new InputStreamReader(s3Object, StandardCharsets.UTF_8)));
403384
} catch (IOException e) {
404385
throw new UncheckedIOException(e);
405-
} catch (URISyntaxException e) {
406-
throw new RuntimeException(e);
407386
} catch (S3Exception e) {
408387
if (e.statusCode() == 404) {
409388
return Optional.empty();
@@ -418,48 +397,28 @@ private static CompletableFuture<Optional<String>> fileDownload(String targetUrl
418397
return CompletableFuture.supplyAsync(
419398
() -> {
420399
try {
421-
Path path = Paths.get(new URL(targetUrl).toURI());
400+
Path path = Paths.get(URI.create(targetUrl));
422401
if (!Files.exists(path)) {
423402
return Optional.empty();
424403
}
425404
return Optional.of(Files.readString(path, StandardCharsets.UTF_8));
426405
} catch (IOException e) {
427406
throw new UncheckedIOException(e);
428-
} catch (URISyntaxException e) {
429-
throw new RuntimeException(e);
430407
}
431408
});
432409
}
433410

434-
private static CompletableFuture<Optional<String>> httpDownload(
435-
String targetUrl, Credentials credentials) {
411+
private static CompletableFuture<Optional<String>> httpDownload(String targetUrl) {
436412
return CompletableFuture.supplyAsync(
437413
() -> {
414+
HttpDownloader downloader = new HttpDownloader(Netrc.fromUserHome());
415+
416+
Path path = downloader.get(URI.create(targetUrl));
417+
if (path == null || !Files.exists(path)) {
418+
return Optional.empty();
419+
}
438420
try {
439-
HttpTransport httpTransport = new NetHttpTransport();
440-
HttpRequest request =
441-
httpTransport
442-
.createRequestFactory(
443-
initRequest -> {
444-
Map<String, List<String>> authHeaders = credentials.getRequestMetadata();
445-
// Add the authorization headers to the HTTP request
446-
if (authHeaders != null) {
447-
for (Map.Entry<String, List<String>> entry : authHeaders.entrySet()) {
448-
initRequest.getHeaders().put(entry.getKey(), entry.getValue());
449-
}
450-
}
451-
})
452-
.buildGetRequest(new GenericUrl(targetUrl));
453-
HttpResponse response = request.execute();
454-
return Optional.of(
455-
CharStreams.toString(
456-
new InputStreamReader(response.getContent(), StandardCharsets.UTF_8)));
457-
} catch (HttpResponseException e) {
458-
if (e.getStatusCode() == 404) {
459-
return Optional.empty();
460-
} else {
461-
throw new UncheckedIOException(e);
462-
}
421+
return Optional.of(Files.readString(path, StandardCharsets.UTF_8));
463422
} catch (IOException e) {
464423
throw new UncheckedIOException(e);
465424
}
@@ -551,7 +510,7 @@ private static Callable<Void> httpUpload(
551510
private static Callable<Void> writeFile(String targetUrl, Path toUpload) {
552511
return () -> {
553512
LOG.info(String.format("Copying %s to %s", toUpload, targetUrl));
554-
Path path = Paths.get(new URL(targetUrl).toURI());
513+
Path path = Paths.get(URI.create(targetUrl));
555514
Files.createDirectories(path.getParent());
556515
Files.deleteIfExists(path);
557516
Files.copy(toUpload, path);
@@ -563,7 +522,7 @@ private static Callable<Void> writeFile(String targetUrl, Path toUpload) {
563522
private static Callable<Void> gcsUpload(String targetUrl, Path toUpload) {
564523
return () -> {
565524
Storage storage = StorageOptions.getDefaultInstance().getService();
566-
URI gsUri = new URI(targetUrl);
525+
URI gsUri = URI.create(targetUrl);
567526
String bucketName = gsUri.getHost();
568527
String path = gsUri.getPath().substring(1);
569528

@@ -581,12 +540,12 @@ private static Callable<Void> gcsUpload(String targetUrl, Path toUpload) {
581540
private static Callable<Void> s3upload(String targetUrl, Path toUpload) {
582541
return () -> {
583542
S3Client s3Client = S3Client.create();
584-
URI s3Uri = new URI(targetUrl);
543+
URI s3Uri = URI.create(targetUrl);
585544
String bucketName = s3Uri.getHost();
586-
String key = s3Uri.getPath().substring(1);
545+
String path = s3Uri.getPath().substring(1);
587546

588-
LOG.info(String.format("Copying %s to s3://%s/%s", toUpload, bucketName, key));
589-
s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(key).build(), toUpload);
547+
LOG.info(String.format("Copying %s to s3://%s/%s", toUpload, bucketName, path));
548+
s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(path).build(), toUpload);
590549

591550
return null;
592551
};

0 commit comments

Comments
 (0)