Remove assumptions from BootInfo and move them to the DSL extension

pull/8686/merge
Andy Wilkinson 8 years ago
parent 5708eaf41b
commit 188c9e0f42

@ -16,9 +16,15 @@
package org.springframework.boot.gradle;
import java.io.File;
import java.util.concurrent.Callable;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.bundling.Jar;
import org.springframework.boot.gradle.buildinfo.BuildInfo;
@ -43,7 +49,11 @@ public class SpringBootExtension {
/**
* Creates a new {@link BuildInfo} task named {@code bootBuildInfo} and configures the
* {@code classes} task to depend upon it.
* Java plugin's {@code classes} task to depend upon it.
* <p>
* By default, the task's destination dir will be a directory named {@code META-INF}
* beneath the main source set's resources output directory, and the task's project
* artifact will be the base name of the {@code bootWar} or {@code bootJar} task.
*/
public void buildInfo() {
this.buildInfo(null);
@ -51,16 +61,39 @@ public class SpringBootExtension {
/**
* Creates a new {@link BuildInfo} task named {@code bootBuildInfo} and configures the
* {@code classes} task to depend upon it. The task is passed to the given
* {@code configurer} for further configuration.
* Java plugin's {@code classes} task to depend upon it. The task is passed to the
* given {@code configurer} for further configuration.
* <p>
* By default, the task's destination dir will be a directory named {@code META-INF}
* beneath the main source set's resources output directory, and the task's project
* artifact will be the base name of the {@code bootWar} or {@code bootJar} task.
*
* @param configurer the task configurer
*/
public void buildInfo(Action<BuildInfo> configurer) {
BuildInfo bootBuildInfo = this.project.getTasks().create("bootBuildInfo",
BuildInfo.class);
this.project.getTasks().getByName(JavaPlugin.CLASSES_TASK_NAME)
.dependsOn(bootBuildInfo);
this.project.getPlugins().withType(JavaPlugin.class, (plugin) -> {
this.project.getTasks().getByName(JavaPlugin.CLASSES_TASK_NAME)
.dependsOn(bootBuildInfo);
bootBuildInfo.getConventionMapping().map("projectArtifact",
(Callable<String>) () -> {
Jar artifactTask = (Jar) this.project.getTasks().findByName("bootWar");
if (artifactTask == null) {
artifactTask = (Jar) this.project.getTasks().findByName("bootJar");
}
String result = artifactTask == null ? null : artifactTask.getBaseName();
return result;
});
bootBuildInfo.getConventionMapping().map("destinationDir",
(Callable<File>) () -> {
return new File(
this.project.getConvention().getPlugin(JavaPluginConvention.class)
.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME)
.getOutput().getResourcesDir(),
"META-INF");
});
});
if (configurer != null) {
configurer.execute(bootBuildInfo);
}

@ -22,62 +22,53 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.gradle.api.DefaultTask;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.Task;
import org.gradle.api.internal.ConventionTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskExecutionException;
import org.gradle.api.tasks.bundling.Jar;
import org.springframework.boot.loader.tools.BuildPropertiesWriter;
import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetails;
/**
* {@link DefaultTask} for generating a {@code build-info.properties} file from a
* {@code Project}.
* <p>
* By default, the {@code build-info.properties} file is generated in
* project.buildDir/resources/main/META-INF.
* </p>
* {@link Task} for generating a {@code build-info.properties} file from a
* {@code Project}. The {@link #setDestinationDir destination dir} and
* {@link #setProjectArtifact project artifact} must be configured before execution.
*
* @author Andy Wilkinson
*/
public class BuildInfo extends DefaultTask {
public class BuildInfo extends ConventionTask {
@OutputFile
private File outputFile = getProject().file(new File(getProject().getBuildDir(),
"resources/main/META-INF/build-info.properties"));
private File destinationDir;
@Input
private String projectGroup = getProject().getGroup().toString();
@Input
private String projectArtifact = ((Jar) getProject().getTasks()
.getByName(JavaPlugin.JAR_TASK_NAME)).getBaseName();
private String projectArtifact;
@Input
private String projectVersion = getProject().getVersion().toString();
@Input
private String projectName = getProject().getName();
@Input
private Map<String, Object> additionalProperties = new HashMap<>();
@TaskAction
public void generateBuildProperties() {
try {
new BuildPropertiesWriter(this.outputFile)
.writeBuildProperties(new ProjectDetails(this.projectGroup,
this.projectArtifact, this.projectVersion, this.projectName,
coerceToStringValues(this.additionalProperties)));
new BuildPropertiesWriter(
new File(getDestinationDir(), "build-info.properties"))
.writeBuildProperties(new ProjectDetails(this.projectGroup,
getProjectArtifact(), this.projectVersion,
this.projectName,
coerceToStringValues(this.additionalProperties)));
}
catch (IOException ex) {
throw new TaskExecutionException(this, ex);
}
}
@Input
public String getProjectGroup() {
return this.projectGroup;
}
@ -86,6 +77,7 @@ public class BuildInfo extends DefaultTask {
this.projectGroup = projectGroup;
}
@Input
public String getProjectArtifact() {
return this.projectArtifact;
}
@ -94,6 +86,7 @@ public class BuildInfo extends DefaultTask {
this.projectArtifact = projectArtifact;
}
@Input
public String getProjectVersion() {
return this.projectVersion;
}
@ -102,6 +95,7 @@ public class BuildInfo extends DefaultTask {
this.projectVersion = projectVersion;
}
@Input
public String getProjectName() {
return this.projectName;
}
@ -110,14 +104,16 @@ public class BuildInfo extends DefaultTask {
this.projectName = projectName;
}
public File getOutputFile() {
return this.outputFile;
@OutputDirectory
public File getDestinationDir() {
return this.destinationDir;
}
public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
public void setDestinationDir(File destinationDir) {
this.destinationDir = destinationDir;
}
@Input
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}

@ -0,0 +1,128 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.gradle.buildinfo;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link BuildInfo} created using the
* {@link org.springframework.boot.gradle.SpringBootExtension DSL}.
*
* @author Andy Wilkinson
*/
public class BuildInfoDslIntegrationTests {
@Rule
public final GradleBuild gradleBuild = new GradleBuild();
@Test
public void basicJar() throws IOException {
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties properties = buildInfoProperties();
assertThat(properties).containsEntry("build.name",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.artifact",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.group", "com.example");
assertThat(properties).containsEntry("build.version", "1.0");
}
@Test
public void jarWithCustomName() throws IOException {
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties properties = buildInfoProperties();
assertThat(properties).containsEntry("build.name",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.artifact", "foo");
assertThat(properties).containsEntry("build.group", "com.example");
assertThat(properties).containsEntry("build.version", "1.0");
}
@Test
public void basicWar() throws IOException {
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties properties = buildInfoProperties();
assertThat(properties).containsEntry("build.name",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.artifact",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.group", "com.example");
assertThat(properties).containsEntry("build.version", "1.0");
}
@Test
public void warWithCustomName() throws IOException {
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties properties = buildInfoProperties();
assertThat(properties).containsEntry("build.name",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.artifact", "foo");
assertThat(properties).containsEntry("build.group", "com.example");
assertThat(properties).containsEntry("build.version", "1.0");
}
@Test
public void additionalProperties() throws IOException {
assertThat(this.gradleBuild.build("bootBuildInfo", "--stacktrace")
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Properties properties = buildInfoProperties();
assertThat(properties).containsEntry("build.name",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.artifact",
this.gradleBuild.getProjectDir().getName());
assertThat(properties).containsEntry("build.group", "com.example");
assertThat(properties).containsEntry("build.version", "1.0");
assertThat(properties).containsEntry("build.a", "alpha");
assertThat(properties).containsEntry("build.b", "bravo");
}
@Test
public void classesDependency() throws IOException {
assertThat(this.gradleBuild.build("classes", "--stacktrace")
.task(":bootBuildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
}
private Properties buildInfoProperties() {
File file = new File(this.gradleBuild.getProjectDir(),
"build/resources/main/META-INF/build-info.properties");
assertThat(file).isFile();
Properties properties = new Properties();
try (FileReader reader = new FileReader(file)) {
properties.load(reader);
return properties;
}
catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}

@ -0,0 +1,88 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.gradle.buildinfo;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link BuildInfo}.
*
* @author Andy Wilkinson
*/
public class BuildInfoIntegrationTests {
@Rule
public final GradleBuild gradleBuild = new GradleBuild();
@Test
public void basicExecution() {
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
.isEqualTo(TaskOutcome.SUCCESS);
}
@Test
public void upToDateWhenExecutedTwice() {
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
.isEqualTo(TaskOutcome.SUCCESS);
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
.isEqualTo(TaskOutcome.UP_TO_DATE);
}
@Test
public void notUpToDateWhenDestinationDirChanges() {
notUpToDateWithChangeToProperty("buildInfoDestinationDir");
}
@Test
public void notUpToDateWhenProjectArtifactChanges() {
notUpToDateWithChangeToProperty("buildInfoProjectArtifact");
}
@Test
public void notUpToDateWhenProjectGroupChanges() {
notUpToDateWithChangeToProperty("buildInfoProjectGroup");
}
@Test
public void notUpToDateWhenProjectVersionChanges() {
notUpToDateWithChangeToProperty("buildInfoProjectVersion");
}
@Test
public void notUpToDateWhenProjectNameChanges() {
notUpToDateWithChangeToProperty("buildInfoProjectName");
}
@Test
public void notUpToDateWhenAdditionalPropertyChanges() {
notUpToDateWithChangeToProperty("buildInfoAdditionalProperty");
}
private void notUpToDateWithChangeToProperty(String name) {
assertThat(this.gradleBuild.build("buildInfo").task(":buildInfo").getOutcome())
.isEqualTo(TaskOutcome.SUCCESS);
assertThat(this.gradleBuild.build("buildInfo", "-P" + name + "=changed")
.task(":buildInfo").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
}
}

@ -0,0 +1,17 @@
buildscript {
dependencies {
classpath files(pluginClasspath.split(','))
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'java'
group = 'com.example'
version = '1.0'
springBoot {
buildInfo {
additionalProperties 'a': 'alpha', 'b': 'bravo'
}
}

@ -0,0 +1,15 @@
buildscript {
dependencies {
classpath files(pluginClasspath.split(','))
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'java'
group = 'com.example'
version = '1.0'
springBoot {
buildInfo()
}

@ -0,0 +1,15 @@
buildscript {
dependencies {
classpath files(pluginClasspath.split(','))
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
group = 'com.example'
version = '1.0'
springBoot {
buildInfo()
}

@ -0,0 +1,12 @@
buildscript {
dependencies {
classpath files(pluginClasspath.split(','))
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'java'
springBoot {
buildInfo()
}

@ -0,0 +1,19 @@
buildscript {
dependencies {
classpath files(pluginClasspath.split(','))
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'java'
group = 'com.example'
version = '1.0'
bootJar {
baseName = 'foo'
}
springBoot {
buildInfo()
}

@ -0,0 +1,19 @@
buildscript {
dependencies {
classpath files(pluginClasspath.split(','))
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
group = 'com.example'
version = '1.0'
bootWar {
baseName = 'foo'
}
springBoot {
buildInfo()
}

@ -0,0 +1,18 @@
buildscript {
dependencies {
classpath files(pluginClasspath.split(','))
}
}
def property(String name, Object defaultValue) {
project.hasProperty(name) ? project.getProperty(name) : defaultValue
}
task buildInfo(type: org.springframework.boot.gradle.buildinfo.BuildInfo) {
destinationDir file(property('buildInfoDestinationDir', project.buildDir))
projectArtifact property('buildInfoProjectArtifact', 'foo')
projectVersion property('buildInfoProjectVersion', '1.0')
projectGroup property('buildInfoProjectGroup', 'foo')
projectName property('buildInfoProjectName', 'foo')
additionalProperties 'additional': property('buildInfoAdditionalProperty', 'foo')
}
Loading…
Cancel
Save