diff --git a/rockcraft-gradle/src/main/java/com/canonical/rockcraft/gradle/PushRockcraftTask.java b/rockcraft-gradle/src/main/java/com/canonical/rockcraft/gradle/PushRockcraftTask.java
new file mode 100644
index 0000000..eec92be
--- /dev/null
+++ b/rockcraft-gradle/src/main/java/com/canonical/rockcraft/gradle/PushRockcraftTask.java
@@ -0,0 +1,35 @@
+package com.canonical.rockcraft.gradle;
+
+import com.canonical.rockcraft.builder.RockBuilder;
+import com.canonical.rockcraft.builder.RockcraftOptions;
+import org.gradle.api.tasks.TaskAction;
+
+import javax.inject.Inject;
+import java.io.IOException;
+
+/**
+ * This task pushes rock image to the local docker
+ */
+public class PushRockcraftTask extends AbstractRockcraftTask {
+
+ /**
+ * Constructs PushRockcraftTask
+ *
+ * @param options - rockcraft options
+ */
+ @Inject
+ public PushRockcraftTask(RockcraftOptions options) {
+ super(options);
+ }
+
+ /**
+ * The task action
+ *
+ * @throws IOException - IO error while writing rockcraft.yaml
+ * @throws InterruptedException - rockcraft process was aborted
+ */
+ @TaskAction
+ public void pushRock() throws IOException, InterruptedException {
+ RockBuilder.buildRock(RockSettingsFactory.createRockProjectSettings(getProject()), getOptions());
+ }
+}
diff --git a/rockcraft-gradle/src/main/java/com/canonical/rockcraft/gradle/RockcraftPlugin.java b/rockcraft-gradle/src/main/java/com/canonical/rockcraft/gradle/RockcraftPlugin.java
index b268223..30afa0b 100644
--- a/rockcraft-gradle/src/main/java/com/canonical/rockcraft/gradle/RockcraftPlugin.java
+++ b/rockcraft-gradle/src/main/java/com/canonical/rockcraft/gradle/RockcraftPlugin.java
@@ -42,6 +42,7 @@ public RockcraftPlugin() {
/**
* Applies the plugin
+ *
* @param project The target object
*/
public void apply(Project project) {
@@ -78,9 +79,13 @@ public void apply(Project project) {
if (tasks.isEmpty())
throw new UnsupportedOperationException("Rockcraft plugin requires bootJar or jar task");
- project.getTasks().register("build-rock", BuildRockcraftTask.class, options);
+ TaskProvider push = project.getTasks().register("push-rock", PushRockcraftTask.class, options);
+ TaskProvider build = project.getTasks().register("build-rock", BuildRockcraftTask.class, options);
TaskProvider create = project.getTasks().register("create-rock", CreateRockcraftTask.class, options);
+ project.getTasks().getByName("push-rock")
+ .dependsOn(build);
+
project.getTasks().getByName("build-rock")
.dependsOn(create);
diff --git a/rockcraft-gradle/src/test/java/com/canonical/rockcraft/gradle/RockcraftPluginTest.java b/rockcraft-gradle/src/test/java/com/canonical/rockcraft/gradle/RockcraftPluginTest.java
index 5abf82d..4af8af0 100644
--- a/rockcraft-gradle/src/test/java/com/canonical/rockcraft/gradle/RockcraftPluginTest.java
+++ b/rockcraft-gradle/src/test/java/com/canonical/rockcraft/gradle/RockcraftPluginTest.java
@@ -36,6 +36,17 @@ void buildRockTest() throws IOException {
assertEquals(TaskOutcome.SUCCESS, getLastTaskOutcome(result)); // the build needs to succeed
}
+ /**
+ * Make a separate test for pushing, so that it could be excluded in docker-less
+ * scenarios
+ * @throws IOException
+ */
+ @Test
+ void pushRockTest() throws IOException {
+ BuildResult result = runBuild("push-rock");
+ assertEquals(TaskOutcome.SUCCESS, getLastTaskOutcome(result)); // the build needs to succeed
+ }
+
@Test
void validRockcraftYaml() throws IOException {
runBuild("create-rock");
diff --git a/rockcraft/src/main/java/com/canonical/rockcraft/builder/RockBuilder.java b/rockcraft/src/main/java/com/canonical/rockcraft/builder/RockBuilder.java
index 784274a..25d0ac6 100644
--- a/rockcraft/src/main/java/com/canonical/rockcraft/builder/RockBuilder.java
+++ b/rockcraft/src/main/java/com/canonical/rockcraft/builder/RockBuilder.java
@@ -47,6 +47,25 @@ public static void checkRockcraft() throws InterruptedException, IOException {
throw new UnsupportedOperationException("Please install rockcraft 'snap install rockcraft'.");
}
+ /**
+ * Pushes rock image to the docker
+ *
+ * @param settings - rockcraft project settings
+ * @throws IOException - IO error while writing rockcraft.yaml
+ * @throws InterruptedException - rockcraft process was aborted
+ */
+ @SuppressWarnings("unchecked")
+ public static void pushRock(RockProjectSettings settings, RockcraftOptions options) throws InterruptedException, IOException {
+ Yaml yaml = new Yaml();
+ Map rockcraft = (Map) yaml.load(new FileReader(settings.getRockOutput().resolve(IRockcraftNames.ROCKCRAFT_YAML).toFile()));
+ String imageName = String.valueOf(rockcraft.get(IRockcraftNames.ROCKCRAFT_NAME));
+ String imageVersion = String.valueOf(rockcraft.get(IRockcraftNames.ROCKCRAFT_VERSION));
+ Path rockDestPath = settings.getRockOutput().resolve(IRockcraftNames.ROCK_OUTPUT);
+ for (File file : rockDestPath.toFile().listFiles((dir, file) -> file.endsWith(".rock"))) {
+ copyInDocker(file, imageName, imageVersion);
+ }
+ }
+
/**
* Builds the rock image
*
@@ -76,4 +95,26 @@ public static void buildRock(RockProjectSettings settings, RockcraftOptions opti
Files.move(source, destination);
}
}
+
+ private static void copyInDocker(File ociImage, String imageName, String imageVersion) throws IOException, InterruptedException {
+ ProcessBuilder pb = new ProcessBuilder("rockcraft.skopeo",
+ "copy",
+ String.format("oci-archive:%s", ociImage.getAbsolutePath()),
+ String.format("docker-daemon:%s:latest", imageName))
+ .directory(ociImage.getParentFile())
+ .inheritIO();
+ Process process = pb.start();
+ int result = process.waitFor();
+ if (result != 0)
+ throw new UnsupportedOperationException("Failed to copy " + ociImage.getAbsolutePath() + " to docker image " + String.format("%s:latest", imageName));
+
+ pb = new ProcessBuilder("docker", "tag", imageName,
+ String.format("%s:%s", imageName, imageVersion))
+ .directory(ociImage.getParentFile())
+ .inheritIO();
+ process = pb.start();
+ result = process.waitFor();
+ if (result != 0)
+ throw new UnsupportedOperationException("Failed to tag " + String.format("%s:%s", imageName, imageVersion));
+ }
}