Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto build gradle lib-project dependencies #821

Merged
merged 6 commits into from
Aug 10, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions jib-gradle-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ All notable changes to this project will be documented in this file.

### Fixed

- Gradle project dependencies have their `assemble` task run before running a jib task ([#815](https://github.com/GoogleContainerTools/jib/issues/815))

## 0.9.8

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@
package com.google.cloud.tools.jib.gradle;

import com.google.common.annotations.VisibleForTesting;
import java.util.List;
import java.util.stream.Collectors;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.UnknownTaskException;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.plugins.BasePlugin;
import org.gradle.util.GradleVersion;

public class JibPlugin implements Plugin<Project> {
Expand Down Expand Up @@ -66,12 +72,14 @@ public void apply(Project project) {
project.afterEvaluate(
projectAfterEvaluation -> {
try {
List<Task> taskDependencies = getProjectDependencyAssembleTasks(projectAfterEvaluation);
Task classesTask = projectAfterEvaluation.getTasks().getByPath("classes");
taskDependencies.add(classesTask);

buildImageTask.dependsOn(classesTask);
dockerContextTask.dependsOn(classesTask);
buildDockerTask.dependsOn(classesTask);
buildTarTask.dependsOn(classesTask);
buildImageTask.dependsOn(taskDependencies.toArray());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use setDependsOn to avoid toArray.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That overwrites any previously dependencies.

For instance in a build.gradle like

apply plugin: 'jib'

task myCustomTask {
  doLast {
    // blah balh
  }
}

jib.dependOn("myCustomTask")

the build using setDependsOn will not honor the myCustomTask dependency.

dockerContextTask.dependsOn(taskDependencies.toArray());
buildDockerTask.dependsOn(taskDependencies.toArray());
buildTarTask.dependsOn(taskDependencies.toArray());

} catch (UnknownTaskException ex) {
throw new GradleException(
Expand All @@ -83,6 +91,28 @@ public void apply(Project project) {
});
}

/**
* Collects all assemble tasks for project dependencies of the style "compile project(':mylib')"
* for any kind of configuration [compile, runtime, etc]. It potentially will collect common test
* libraries in configs like [test, integrationTest, etc], but it's either that or filter based on
* a configuration containing the word "test" which feels dangerous.
*
* @param project this project we are containerizing
* @return a list of "assemble" tasks associated with projects that this project depends on.
*/
static List<Task> getProjectDependencyAssembleTasks(Project project) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Order above non-static and annotate with @VisibleForTesting.

return project
.getConfigurations()
.stream()
.map(Configuration::getDependencies)
.flatMap(DependencySet::stream)
.filter(ProjectDependency.class::isInstance)
.map(ProjectDependency.class::cast)
.map(ProjectDependency::getDependencyProject)
.map(subProject -> subProject.getTasks().getByPath(BasePlugin.ASSEMBLE_TASK_NAME))
.collect(Collectors.toList());
}

private static void checkGradleVersion() {
if (GRADLE_MIN_VERSION.compareTo(GradleVersion.current()) > 0) {
throw new GradleException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,19 @@

package com.google.cloud.tools.jib.gradle;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Collectors;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.testfixtures.ProjectBuilder;
import org.gradle.testkit.runner.GradleRunner;
import org.gradle.testkit.runner.UnexpectedBuildFailure;
import org.junit.Assert;
Expand Down Expand Up @@ -68,4 +77,68 @@ public void testCheckGradleVersion_fail() throws IOException {
+ "'."));
}
}

@Test
public void testGetProjectDependencyAssembleTasks() {
// root project is our jib packaged service
Project rootProject =
ProjectBuilder.builder().withProjectDir(testProjectRoot.getRoot()).withName("root").build();
rootProject.getPluginManager().apply("java");

// our service DOES depend on this, and jib should trigger an assemble from this project
Project subProject =
ProjectBuilder.builder()
.withParent(rootProject)
.withProjectDir(testProjectRoot.getRoot())
.withName("sub")
.build();
subProject.getPluginManager().apply("java");

// our service doesn't depend on this, and jib should NOT trigger an assemble from this project
Project unrelatedSubProject =
ProjectBuilder.builder()
.withParent(rootProject)
.withProjectDir(testProjectRoot.getRoot())
.withName("unrelated")
.build();
unrelatedSubProject.getPluginManager().apply("java");

// equivalent of "compile project(':sub')" on the root(jib) project
rootProject
.getConfigurations()
.getByName("compile")
.getDependencies()
.add(rootProject.getDependencies().project(ImmutableMap.of("path", subProject.getPath())));

// programmatic check
Assert.assertEquals(
Collections.singletonList(":sub:assemble"),
JibPlugin.getProjectDependencyAssembleTasks(rootProject)
.stream()
.map(Task::getPath)
.collect(Collectors.toList()));

// check by applying the jib plugin and inspect the task dependencies
rootProject.getPluginManager().apply("com.google.cloud.tools.jib");
((ProjectInternal) rootProject).evaluate();

Arrays.asList(
JibPlugin.BUILD_IMAGE_TASK_NAME,
JibPlugin.DOCKER_CONTEXT_TASK_NAME,
JibPlugin.BUILD_DOCKER_TASK_NAME,
JibPlugin.BUILD_TAR_TASK_NAME)
.forEach(
taskName -> {
Assert.assertEquals(
ImmutableSet.of(":sub:assemble", ":classes"),
rootProject
.getTasks()
.getByPath(taskName)
.getDependsOn()
.stream()
.map(Task.class::cast)
.map(Task::getPath)
.collect(Collectors.toSet()));
});
}
}