Skip to content

Commit

Permalink
Add google cloud storage support to java_export
Browse files Browse the repository at this point in the history
  • Loading branch information
zacharya19 committed Nov 21, 2020
1 parent 2e5a9c8 commit 26a6681
Show file tree
Hide file tree
Showing 6 changed files with 679 additions and 5 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*.class
bazel-*
.ijwb
.DS_Store
.DS_Store
.idea
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,10 @@ bazel run --stamp \
//user_project:exported_lib.publish`
```

It's also possible to publish to a Google Cloud Storage bucket:

`bazel run --define "maven_repo=gs://example-bucket/repository" //user_project:exported_lib.publish`

When using the `gpg_sign` option, the current default key will be used for
signing, and the `gpg` binary needs to be installed on the machine.

Expand Down
10 changes: 10 additions & 0 deletions private/tools/java/rules/jvm/external/maven/BUILD
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
load("@rules_jvm_external//:defs.bzl", "artifact")

java_binary(
name = "MavenPublisher",
srcs = ["MavenPublisher.java"],
Expand All @@ -11,6 +13,14 @@ java_binary(
visibility = ["//visibility:public"],
deps = [
"//private/tools/java/rules/jvm/external:byte-streams",
artifact(
"com.google.cloud:google-cloud-storage",
repository_name = "rules_jvm_external_deps",
),
artifact(
"com.google.cloud:google-cloud-core",
repository_name = "rules_jvm_external_deps",
),
],
)

Expand Down
43 changes: 40 additions & 3 deletions private/tools/java/rules/jvm/external/maven/MavenPublisher.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@

package rules.jvm.external.maven;

import com.google.cloud.WriteChannel;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import rules.jvm.external.ByteStreams;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Expand All @@ -50,11 +56,13 @@ public class MavenPublisher {

private static final Logger LOG = Logger.getLogger(MavenPublisher.class.getName());
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(1);
private static final String[] SUPPORTED_SCHEMES = {"file:/", "https://", "gs://"};

public static void main(String[] args) throws IOException, InterruptedException, ExecutionException, TimeoutException {
String repo = args[0];
if (!(repo.startsWith("file:/") || repo.startsWith("https://"))) {
throw new IllegalArgumentException("Repository must be accessed via file or https: " + repo);
if (!isSchemeSupported(repo)) {
throw new IllegalArgumentException("Repository must be accessed via the supported schemes: "
+ Arrays.toString(SUPPORTED_SCHEMES));
}

Credentials credentials = new Credentials(args[2], args[3], Boolean.parseBoolean(args[1]));
Expand Down Expand Up @@ -85,6 +93,15 @@ public static void main(String[] args) throws IOException, InterruptedException,
}
}

private static boolean isSchemeSupported(String repo) {
for (String scheme : SUPPORTED_SCHEMES) {
if (repo.startsWith(scheme)) {
return true;
}
}
return false;
}

private static CompletableFuture<Void> upload(
String repo,
Credentials credentials,
Expand All @@ -94,7 +111,7 @@ private static CompletableFuture<Void> upload(

String base = String.format(
"%s/%s/%s/%s/%s-%s",
repo,
repo.replaceAll("/$", ""),
coords.groupId.replace('.', '/'),
coords.artifactId,
coords.version,
Expand Down Expand Up @@ -144,6 +161,8 @@ private static CompletableFuture<Void> upload(String targetUrl, Credentials cred
Callable<Void> callable;
if (targetUrl.startsWith("http://") || targetUrl.startsWith("https://")) {
callable = httpUpload(targetUrl, credentials, toUpload);
} else if (targetUrl.startsWith("gs://")) {
callable = gcsUpload(targetUrl, toUpload);
} else {
callable = writeFile(targetUrl, toUpload);
}
Expand Down Expand Up @@ -210,6 +229,24 @@ private static Callable<Void> writeFile(String targetUrl, Path toUpload) {
};
}

private static Callable<Void> gcsUpload(String targetUrl, Path toUpload) {
return () -> {
Storage storage = StorageOptions.getDefaultInstance().getService();
URI gsUri = new URI(targetUrl);
String bucketName = gsUri.getHost();
String path = gsUri.getPath().substring(1);

LOG.info(String.format("Copying %s to gs://%s/%s", toUpload, bucketName, path));
BlobInfo blobInfo = BlobInfo.newBuilder(bucketName, path).build();
try (WriteChannel writer = storage.writer(blobInfo);
InputStream is = Files.newInputStream(toUpload)) {
ByteStreams.copy(is, Channels.newOutputStream(writer));
}

return null;
};
}

private static Path sign(Path toSign) throws IOException, InterruptedException {
LOG.info("Signing " + toSign);

Expand Down
1 change: 1 addition & 0 deletions repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def rules_jvm_external_deps(repositories = _DEFAULT_REPOSITORIES):
maven_install(
name = "rules_jvm_external_deps",
artifacts = [
"com.google.cloud:google-cloud-storage:1.113.4",
],
maven_install_json = "@rules_jvm_external//:rules_jvm_external_deps_install.json",
repositories = repositories,
Expand Down
Loading

0 comments on commit 26a6681

Please sign in to comment.