Skip to content

Commit

Permalink
Add a BuildInfo task for generating build.properties with Gradle
Browse files Browse the repository at this point in the history
The commit adds a new BuildInfo task that can be used to generate
a build.properties file, intended for inclusion in the Actuator's
info endpoint.

A default instance of the task can be configure using the plugin's
DSL:

springBoot {
	buildInfo()
}

Additional properties can also be configured using the DSL:

springBoot {
	buildInfo {
		additionalProperties = [
			'foo': 'bar'
		]
	}
}

When configured via the DSL, the Java plugin's classes task is
configured to depend on the build info task. Alternatively, if more
control is required, the task can be declared and configured manually:

task buildInfo(type: org.springframework.boot.gradle.buildinfo.BuildInfo) {
	additionalProperties = [
		'foo': 'bar'
	]
}

classes {
	dependsOn buildInfo
}

See spring-projectsgh-2559
  • Loading branch information
wilkinsona committed Mar 24, 2016
1 parent 4167469 commit 58ca9a1
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 68 deletions.
8 changes: 7 additions & 1 deletion spring-boot-samples/spring-boot-sample-actuator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ apply plugin: 'spring-boot'

jar {
baseName = 'spring-boot-sample-actuator'
version = '0.0.0'
}

group = 'org.springframework.boot'
version = springBootVersion

repositories {
// NOTE: You should declare only repositories that you need here
mavenLocal()
Expand Down Expand Up @@ -59,3 +61,7 @@ springBoot {
task wrapper(type: Wrapper) {
gradleVersion = '1.6'
}

springBoot {
buildInfo()
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public class SpringBootPlugin implements Plugin<Project> {

@Override
public void apply(Project project) {
project.getExtensions().create("springBoot", SpringBootPluginExtension.class);
project.getExtensions().create("springBoot", SpringBootPluginExtension.class,
project);
project.getPlugins().apply(JavaPlugin.class);
new AgentPluginFeatures().apply(project);
new RepackagePluginFeatures().apply(project);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 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.
Expand All @@ -20,6 +20,11 @@
import java.util.Map;
import java.util.Set;

import groovy.lang.Closure;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;

import org.springframework.boot.gradle.buildinfo.BuildInfo;
import org.springframework.boot.loader.tools.Layout;
import org.springframework.boot.loader.tools.Layouts;

Expand All @@ -39,9 +44,12 @@
* @author Phillip Webb
* @author Dave Syer
* @author Stephane Nicoll
* @author Andy Wilkinson
*/
public class SpringBootPluginExtension {

private final Project project;

/**
* The main class that should be run. Instead of setting this explicitly you can use
* the 'mainClassName' of the project or the 'main' of the 'run' task. If not
Expand Down Expand Up @@ -128,6 +136,10 @@ public class SpringBootPluginExtension {
*/
Map<String, String> embeddedLaunchScriptProperties;

public SpringBootPluginExtension(Project project) {
this.project = project;
}

/**
* Convenience method for use in a custom task.
* @return the Layout to use or null if not explicitly set
Expand Down Expand Up @@ -249,6 +261,21 @@ public void setEmbeddedLaunchScriptProperties(
this.embeddedLaunchScriptProperties = embeddedLaunchScriptProperties;
}

public void buildInfo() {
this.buildInfo(null);
}

public void buildInfo(Closure<?> taskConfigurer) {
BuildInfo buildInfo = this.project.getTasks().create("buildInfo",
BuildInfo.class);
this.project.getTasks().getByName(JavaPlugin.CLASSES_TASK_NAME)
.dependsOn(buildInfo);
if (taskConfigurer != null) {
taskConfigurer.setDelegate(buildInfo);
taskConfigurer.call();
}
}

/**
* Layout Types.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright 2012-2016 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.IOException;
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.tasks.Input;
import org.gradle.api.tasks.OutputFile;
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.properties} file from a
* {@code Project}.
* <p>
* By default, the {@code build.properties} file is generated in
* project.buildDir/resources/main/META-INF/boot.
* </p>
*
* @author Andy Wilkinson
*/
public class BuildInfo extends DefaultTask {

@OutputFile
private File outputFile = getProject().file(new File(getProject().getBuildDir(),
"resources/main/META-INF/boot/build.properties"));

@Input
private String projectGroup = getProject().getGroup().toString();

@Input
private String projectArtifact = ((Jar) getProject().getTasks()
.getByName(JavaPlugin.JAR_TASK_NAME)).getBaseName();

@Input
private String projectVersion = getProject().getVersion().toString();

@Input
private String projectName = getProject().getName();

@Input
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

@TaskAction
public void generateBuildProperties() {
try {
new BuildPropertiesWriter(this.outputFile)
.writeBuildProperties(new ProjectDetails(this.projectGroup,
this.projectArtifact, this.projectVersion, this.projectName,
coerceToStringValues(this.additionalProperties)));
}
catch (IOException ex) {
throw new TaskExecutionException(this, ex);
}
}

public String getProjectGroup() {
return this.projectGroup;
}

public void setProjectGroup(String projectGroup) {
this.projectGroup = projectGroup;
}

public String getProjectArtifact() {
return this.projectArtifact;
}

public void setProjectArtifact(String projectArtifact) {
this.projectArtifact = projectArtifact;
}

public String getProjectVersion() {
return this.projectVersion;
}

public void setProjectVersion(String projectVersion) {
this.projectVersion = projectVersion;
}

public String getProjectName() {
return this.projectName;
}

public void setProjectName(String projectName) {
this.projectName = projectName;
}

public File getOutputFile() {
return this.outputFile;
}

public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
}

public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}

public void setAdditionalProperties(Map<String, Object> additionalProperties) {
this.additionalProperties = additionalProperties;
}

private Map<String, String> coerceToStringValues(Map<String, Object> input) {
Map<String, String> output = new HashMap<String, String>();
for (Entry<String, Object> entry : this.additionalProperties.entrySet()) {
output.put(entry.getKey(), entry.getValue().toString());
}
return output;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright 2012-2016 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.loader.tools;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

/**
* A {@code BuildPropertiesWriter} writes the {@code build.properties} for consumption by
* the Actuator.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
public final class BuildPropertiesWriter {

private final File outputFile;

/**
* Creates a new {@code BuildPropertiesWriter} that will write to the given
* {@code outputFile}.
*
* @param outputFile the output file
*/
public BuildPropertiesWriter(File outputFile) {
this.outputFile = outputFile;
}

public void writeBuildProperties(ProjectDetails projectDetails) throws IOException {
Properties properties = createBuildInfo(projectDetails);
createFileIfNecessary(this.outputFile);
FileOutputStream outputStream = new FileOutputStream(this.outputFile);
try {
properties.store(outputStream, "Properties");
}
finally {
try {
outputStream.close();
}
catch (IOException ex) {
// Continue
}
}
}

private void createFileIfNecessary(File file) throws IOException {
if (file.exists()) {
return;
}
File parent = file.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IllegalStateException("Cannot create parent directory for '"
+ this.outputFile.getAbsolutePath() + "'");
}
if (!file.createNewFile()) {
throw new IllegalStateException("Cannot create target file '"
+ this.outputFile.getAbsolutePath() + "'");
}
}

protected Properties createBuildInfo(ProjectDetails project) {
Properties properties = new Properties();
properties.put("build.group", project.getGroup());
properties.put("build.artifact", project.getArtifact());
properties.put("build.name", project.getName());
properties.put("build.version", project.getVersion());
properties.put("build.time", formatDate(new Date()));
if (project.getAdditionalProperties() != null) {
for (Map.Entry<String, String> entry : project.getAdditionalProperties()
.entrySet()) {
properties.put("build." + entry.getKey(), entry.getValue());
}
}
return properties;
}

private String formatDate(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
return sdf.format(date);
}

/**
* Build-system agnostic details of a project.
*/
public static final class ProjectDetails {

private final String group;

private final String artifact;

private final String name;

private final String version;

private final Map<String, String> additionalProperties;

public ProjectDetails(String group, String artifact, String version, String name,
Map<String, String> additionalProperties) {
this.group = group;
this.artifact = artifact;
this.name = name;
this.version = version;
this.additionalProperties = additionalProperties;
}

public String getGroup() {
return this.group;
}

public String getArtifact() {
return this.artifact;
}

public String getName() {
return this.name;
}

public String getVersion() {
return this.version;
}

public Map<String, String> getAdditionalProperties() {
return this.additionalProperties;
}

}
}
Loading

0 comments on commit 58ca9a1

Please sign in to comment.