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 Oct 4, 2020
1 parent e797572 commit d32efeb
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 8 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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,14 @@ Any version conflicts or duplicate artifacts will resolved automatically.

## Publishing to External Repositories

In order to use this feature you must import the java_export maven deps in your workspace:

```python
load("@rules_jvm_external//:defs.bzl", "java_export_deps")

java_export_deps()
```

In order to publish an artifact from your repo to a maven repository, you
must first create a `java_export` target. This is similar to a regular
`java_library`, but allows two additional parameters: the maven coordinates
Expand Down Expand Up @@ -952,6 +960,10 @@ bazel run --stamp \
//user_project:exported_lib.publish`
```

It's also possible to publish to a Google Cloud Storage bucket (make sure to not add a trailing slash):

`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
4 changes: 3 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ http_archive(

# Begin test dependencies

load("//:defs.bzl", "maven_install")
load("//:defs.bzl", "java_export_deps", "maven_install")
load("//:specs.bzl", "maven")

maven_install(
Expand All @@ -67,6 +67,8 @@ maven_install(
],
)

java_export_deps()

load("@maven//:defs.bzl", "pinned_maven_install")

pinned_maven_install()
Expand Down
16 changes: 16 additions & 0 deletions defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ def _parse_artifact_str(artifact_str):
else:
return parse.parse_maven_coordinate(artifact_str)

JAVA_EXPORT_REPO_NAME = "internal_java_exports_maven"

def java_export_deps():
"""
Adds the maven dependencies that are needed to run java_export rule.
"""
maven_install(
name = JAVA_EXPORT_REPO_NAME,
artifacts = [
"com.google.cloud:google-cloud-storage:1.111.2",
],
repositories = [
"https://jcenter.bintray.com/",
],
)

java_export = _java_export
javadoc = _javadoc
pom_file = _pom_file
Expand Down
1 change: 0 additions & 1 deletion examples/java-export/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ java_export(
"//src/main/java/com/github/bazelbuild/rulesjvmexternal/example/export",
],
)

5 changes: 3 additions & 2 deletions examples/java-export/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ local_repository(
path = "../../",
)

load("@rules_jvm_external//:defs.bzl", "maven_install")
load("@rules_jvm_external//:defs.bzl", "java_export_deps", "maven_install")

protobuf_version = "3.11.3"

Expand All @@ -21,6 +21,8 @@ maven_install(
],
)

java_export_deps()

load("@maven//:defs.bzl", "pinned_maven_install")

pinned_maven_install()
Expand Down Expand Up @@ -56,4 +58,3 @@ load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_
rules_proto_dependencies()

rules_proto_toolchains()

12 changes: 11 additions & 1 deletion private/tools/java/rules/jvm/external/maven/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
load("@rules_jvm_external//:defs.bzl", "JAVA_EXPORT_REPO_NAME", "artifact")

java_binary(
name = "MavenPublisher",
srcs = ["MavenPublisher.java"],
Expand All @@ -8,8 +10,16 @@ java_binary(
"8",
],
main_class = "rules.jvm.external.maven.MavenPublisher",
visibility = ["//visibility:public"],
deps = [
"//private/tools/java/rules/jvm/external:byte-streams",
artifact(
"com.google.cloud:google-cloud-storage",
repository_name = JAVA_EXPORT_REPO_NAME,
),
artifact(
"com.google.cloud:google-cloud-core",
repository_name = JAVA_EXPORT_REPO_NAME,
),
],
visibility = ["//visibility:public"],
)
41 changes: 39 additions & 2 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 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

0 comments on commit d32efeb

Please sign in to comment.