Make consistent use of Property for Gradle task configuration
Closes gh-32769
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
@@ -30,7 +30,6 @@ import org.gradle.api.tasks.TaskProvider;
|
||||
import org.gradle.jvm.tasks.Jar;
|
||||
|
||||
import org.springframework.boot.gradle.tasks.buildinfo.BuildInfo;
|
||||
import org.springframework.boot.gradle.tasks.buildinfo.BuildInfoProperties;
|
||||
|
||||
/**
|
||||
* Entry point to Spring Boot's Gradle DSL.
|
||||
@@ -92,12 +91,8 @@ public class SpringBootExtension {
|
||||
this::configureBuildInfoTask);
|
||||
this.project.getPlugins().withType(JavaPlugin.class, (plugin) -> {
|
||||
tasks.named(JavaPlugin.CLASSES_TASK_NAME).configure((task) -> task.dependsOn(bootBuildInfo));
|
||||
this.project.afterEvaluate((evaluated) -> bootBuildInfo.configure((buildInfo) -> {
|
||||
BuildInfoProperties properties = buildInfo.getProperties();
|
||||
if (properties.getArtifact() == null) {
|
||||
properties.setArtifact(determineArtifactBaseName());
|
||||
}
|
||||
}));
|
||||
bootBuildInfo.configure((buildInfo) -> buildInfo.getProperties().getArtifact()
|
||||
.convention(this.project.provider(() -> determineArtifactBaseName())));
|
||||
});
|
||||
if (configurer != null) {
|
||||
bootBuildInfo.configure(configurer);
|
||||
@@ -107,8 +102,8 @@ public class SpringBootExtension {
|
||||
private void configureBuildInfoTask(BuildInfo task) {
|
||||
task.setGroup(BasePlugin.BUILD_GROUP);
|
||||
task.setDescription("Generates a META-INF/build-info.properties file.");
|
||||
task.getConventionMapping().map("destinationDir",
|
||||
() -> new File(determineMainSourceSetResourcesOutputDir(), "META-INF"));
|
||||
task.getDestinationDir().convention(this.project.getLayout()
|
||||
.dir(this.project.provider(() -> new File(determineMainSourceSetResourcesOutputDir(), "META-INF"))));
|
||||
}
|
||||
|
||||
private File determineMainSourceSetResourcesOutputDir() {
|
||||
|
||||
@@ -89,8 +89,8 @@ class NativeImagePluginAction implements PluginApplicationAction {
|
||||
private void configureBootBuildImageToProduceANativeImage(Project project) {
|
||||
project.getTasks().named(SpringBootPlugin.BOOT_BUILD_IMAGE_TASK_NAME, BootBuildImage.class)
|
||||
.configure((bootBuildImage) -> {
|
||||
bootBuildImage.setBuilder("paketobuildpacks/builder:tiny");
|
||||
bootBuildImage.environment("BP_NATIVE_IMAGE", "true");
|
||||
bootBuildImage.getBuilder().convention("paketobuildpacks/builder:tiny");
|
||||
bootBuildImage.getEnvironment().put("BP_NATIVE_IMAGE", "true");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -32,25 +32,20 @@ import org.gradle.api.tasks.TaskAction;
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@CacheableTask
|
||||
public class ProcessAot extends AbstractAot {
|
||||
|
||||
private final Property<String> applicationClass;
|
||||
public abstract class ProcessAot extends AbstractAot {
|
||||
|
||||
public ProcessAot() {
|
||||
this.applicationClass = getProject().getObjects().property(String.class);
|
||||
getMainClass().set("org.springframework.boot.SpringApplicationAotProcessor");
|
||||
}
|
||||
|
||||
@Input
|
||||
public Property<String> getApplicationClass() {
|
||||
return this.applicationClass;
|
||||
}
|
||||
public abstract Property<String> getApplicationClass();
|
||||
|
||||
@Override
|
||||
@TaskAction
|
||||
public void exec() {
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add(this.applicationClass.get());
|
||||
args.add(getApplicationClass().get());
|
||||
args.addAll(processorArgs());
|
||||
this.setArgs(args);
|
||||
super.exec();
|
||||
|
||||
@@ -18,14 +18,13 @@ package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.internal.ConventionTask;
|
||||
import org.gradle.api.provider.SetProperty;
|
||||
import org.gradle.api.tasks.Internal;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
@@ -43,28 +42,35 @@ import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetail
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@DisableCachingByDefault(because = "Not worth caching")
|
||||
public class BuildInfo extends ConventionTask {
|
||||
public abstract class BuildInfo extends DefaultTask {
|
||||
|
||||
private final BuildInfoProperties properties = new BuildInfoProperties(getProject());
|
||||
|
||||
private final DirectoryProperty destinationDir;
|
||||
private final BuildInfoProperties properties;
|
||||
|
||||
public BuildInfo() {
|
||||
this.destinationDir = getProject().getObjects().directoryProperty()
|
||||
.convention(getProject().getLayout().getBuildDirectory());
|
||||
this.properties = getProject().getObjects().newInstance(BuildInfoProperties.class, getExcludes());
|
||||
getDestinationDir().convention(getProject().getLayout().getBuildDirectory().dir(getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the properties to exclude from the output.
|
||||
* @return names of the properties to exclude
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Internal
|
||||
public abstract SetProperty<String> getExcludes();
|
||||
|
||||
/**
|
||||
* Generates the {@code build-info.properties} file in the configured
|
||||
* {@link #setDestinationDir(File) destination}.
|
||||
* {@link #getDestinationDir destination}.
|
||||
*/
|
||||
@TaskAction
|
||||
public void generateBuildProperties() {
|
||||
try {
|
||||
ProjectDetails details = new ProjectDetails(this.properties.getGroup(), this.properties.getArtifact(),
|
||||
this.properties.getVersion(), this.properties.getName(), this.properties.getTime(),
|
||||
coerceToStringValues(this.properties.getAdditional()));
|
||||
new BuildPropertiesWriter(new File(getDestinationDir(), "build-info.properties"))
|
||||
ProjectDetails details = new ProjectDetails(this.properties.getGroupIfNotExcluded(),
|
||||
this.properties.getArtifactIfNotExcluded(), this.properties.getVersionIfNotExcluded(),
|
||||
this.properties.getNameIfNotExcluded(), this.properties.getTimeIfNotExcluded(),
|
||||
this.properties.getAdditionalIfNotExcluded());
|
||||
new BuildPropertiesWriter(new File(getDestinationDir().get().getAsFile(), "build-info.properties"))
|
||||
.writeBuildProperties(details);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
@@ -74,21 +80,11 @@ public class BuildInfo extends ConventionTask {
|
||||
|
||||
/**
|
||||
* Returns the directory to which the {@code build-info.properties} file will be
|
||||
* written. Defaults to the {@link Project#getBuildDir() Project's build directory}.
|
||||
* written.
|
||||
* @return the destination directory
|
||||
*/
|
||||
@OutputDirectory
|
||||
public File getDestinationDir() {
|
||||
return this.destinationDir.getAsFile().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the directory to which the {@code build-info.properties} file will be written.
|
||||
* @param destinationDir the destination directory
|
||||
*/
|
||||
public void setDestinationDir(File destinationDir) {
|
||||
this.destinationDir.set(destinationDir);
|
||||
}
|
||||
public abstract DirectoryProperty getDestinationDir();
|
||||
|
||||
/**
|
||||
* Returns the {@link BuildInfoProperties properties} that will be included in the
|
||||
@@ -108,10 +104,4 @@ public class BuildInfo extends ConventionTask {
|
||||
action.execute(this.properties);
|
||||
}
|
||||
|
||||
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
|
||||
Map<String, String> output = new HashMap<>();
|
||||
input.forEach((key, value) -> output.put(key, (value != null) ? value.toString() : null));
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,19 +16,27 @@
|
||||
|
||||
package org.springframework.boot.gradle.tasks.buildinfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.provider.SetProperty;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Internal;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
|
||||
import org.springframework.util.function.SingletonSupplier;
|
||||
|
||||
/**
|
||||
* The properties that are written into the {@code build-info.properties} file.
|
||||
*
|
||||
@@ -36,164 +44,135 @@ import org.gradle.api.tasks.Optional;
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class BuildInfoProperties implements Serializable {
|
||||
public abstract class BuildInfoProperties implements Serializable {
|
||||
|
||||
private transient Instant creationTime = Instant.now();
|
||||
private final SetProperty<String> excludes;
|
||||
|
||||
private final Property<String> group;
|
||||
private final Supplier<String> creationTime = SingletonSupplier.of(new CurrentIsoInstantSupplier());
|
||||
|
||||
private final Property<String> artifact;
|
||||
|
||||
private final Property<String> version;
|
||||
|
||||
private final Property<String> name;
|
||||
|
||||
private final Property<Long> time;
|
||||
|
||||
private boolean timeConfigured = false;
|
||||
|
||||
private Map<String, Object> additionalProperties = new HashMap<>();
|
||||
|
||||
BuildInfoProperties(Project project) {
|
||||
this.time = project.getObjects().property(Long.class);
|
||||
this.group = project.getObjects().property(String.class);
|
||||
this.group.set(project.provider(() -> project.getGroup().toString()));
|
||||
this.artifact = project.getObjects().property(String.class);
|
||||
this.version = project.getObjects().property(String.class);
|
||||
this.version.set(projectVersion(project));
|
||||
this.name = project.getObjects().property(String.class);
|
||||
this.name.set(project.provider(project::getName));
|
||||
}
|
||||
|
||||
private Provider<String> projectVersion(Project project) {
|
||||
return project.provider(() -> project.getVersion().toString());
|
||||
@Inject
|
||||
public BuildInfoProperties(Project project, SetProperty<String> excludes) {
|
||||
this.excludes = excludes;
|
||||
getGroup().convention(project.provider(() -> project.getGroup().toString()));
|
||||
getVersion().convention(project.provider(() -> project.getVersion().toString()));
|
||||
getArtifact()
|
||||
.convention(project.provider(() -> project.findProperty("archivesBaseName")).map(Object::toString));
|
||||
getName().convention(project.provider(project::getName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.group} property. Defaults to the
|
||||
* {@link Project#getGroup() Project's group}.
|
||||
* @return the group
|
||||
* Returns the {@code build.group} property. Defaults to the {@link Project#getGroup()
|
||||
* Project's group}.
|
||||
* @return the group property
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getGroup() {
|
||||
return this.group.getOrNull();
|
||||
}
|
||||
@Internal
|
||||
public abstract Property<String> getGroup();
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.group} property.
|
||||
* @param group the group name
|
||||
* Returns the {@code build.artifact} property.
|
||||
* @return the artifact property
|
||||
*/
|
||||
public void setGroup(String group) {
|
||||
this.group.set(group);
|
||||
}
|
||||
@Internal
|
||||
public abstract Property<String> getArtifact();
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.artifact} property.
|
||||
* @return the artifact
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getArtifact() {
|
||||
return this.artifact.getOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.artifact} property.
|
||||
* @param artifact the artifact
|
||||
*/
|
||||
public void setArtifact(String artifact) {
|
||||
this.artifact.set(artifact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.version} property. Defaults to the
|
||||
* Returns the {@code build.version} property. Defaults to the
|
||||
* {@link Project#getVersion() Project's version}.
|
||||
* @return the version
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getVersion() {
|
||||
return this.version.getOrNull();
|
||||
}
|
||||
@Internal
|
||||
public abstract Property<String> getVersion();
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.version} property.
|
||||
* @param version the version
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
this.version.set(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.name} property. Defaults to the
|
||||
* {@link Project#getDisplayName() Project's display name}.
|
||||
* Returns the {@code build.name} property. Defaults to the {@link Project#getName()
|
||||
* Project's name}.
|
||||
* @return the name
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getName() {
|
||||
return this.name.getOrNull();
|
||||
}
|
||||
@Internal
|
||||
public abstract Property<String> getName();
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.name} property.
|
||||
* @param name the name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name.set(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value used for the {@code build.time} property. Defaults to
|
||||
* {@link Instant#now} when the {@code BuildInfoProperties} instance was created.
|
||||
* Returns the {@code build.time} property.
|
||||
* @return the time
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public Instant getTime() {
|
||||
Long epochMillis = this.time.getOrNull();
|
||||
if (epochMillis != null) {
|
||||
return Instant.ofEpochMilli(epochMillis);
|
||||
}
|
||||
if (this.timeConfigured) {
|
||||
return null;
|
||||
}
|
||||
return this.creationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value used for the {@code build.time} property.
|
||||
* @param time the build time
|
||||
*/
|
||||
public void setTime(Instant time) {
|
||||
this.timeConfigured = true;
|
||||
this.time.set((time != null) ? time.toEpochMilli() : null);
|
||||
}
|
||||
@Internal
|
||||
public abstract Property<String> getTime();
|
||||
|
||||
/**
|
||||
* Returns the additional properties that will be included. When written, the name of
|
||||
* each additional property is prefixed with {@code build.}.
|
||||
* @return the additional properties
|
||||
*/
|
||||
@Internal
|
||||
public abstract MapProperty<String, Object> getAdditional();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public Map<String, Object> getAdditional() {
|
||||
return this.additionalProperties;
|
||||
String getArtifactIfNotExcluded() {
|
||||
return getIfNotExcluded(getArtifact(), "artifact");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the additional properties that will be included. When written, the name of
|
||||
* each additional property is prefixed with {@code build.}.
|
||||
* @param additionalProperties the additional properties
|
||||
*/
|
||||
public void setAdditional(Map<String, Object> additionalProperties) {
|
||||
this.additionalProperties = additionalProperties;
|
||||
@Input
|
||||
@Optional
|
||||
String getGroupIfNotExcluded() {
|
||||
return getIfNotExcluded(getGroup(), "group");
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException {
|
||||
input.defaultReadObject();
|
||||
this.creationTime = Instant.now();
|
||||
@Input
|
||||
@Optional
|
||||
String getNameIfNotExcluded() {
|
||||
return getIfNotExcluded(getName(), "name");
|
||||
}
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
Instant getTimeIfNotExcluded() {
|
||||
String time = getIfNotExcluded(getTime(), "time", this.creationTime);
|
||||
return (time != null) ? Instant.parse(time) : null;
|
||||
}
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
String getVersionIfNotExcluded() {
|
||||
return getIfNotExcluded(getVersion(), "version");
|
||||
}
|
||||
|
||||
@Input
|
||||
Map<String, String> getAdditionalIfNotExcluded() {
|
||||
return coerceToStringValues(applyExclusions(getAdditional().getOrElse(Collections.emptyMap())));
|
||||
}
|
||||
|
||||
private <T> T getIfNotExcluded(Property<T> property, String name) {
|
||||
return getIfNotExcluded(property, name, () -> null);
|
||||
}
|
||||
|
||||
private <T> T getIfNotExcluded(Property<T> property, String name, Supplier<T> defaultValue) {
|
||||
if (this.excludes.getOrElse(Collections.emptySet()).contains(name)) {
|
||||
return null;
|
||||
}
|
||||
return property.getOrElse(defaultValue.get());
|
||||
}
|
||||
|
||||
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
|
||||
Map<String, String> output = new HashMap<>();
|
||||
input.forEach((key, value) -> output.put(key, (value != null) ? value.toString() : null));
|
||||
return output;
|
||||
}
|
||||
|
||||
private Map<String, Object> applyExclusions(Map<String, Object> input) {
|
||||
Map<String, Object> output = new HashMap<>();
|
||||
Set<String> exclusions = this.excludes.getOrElse(Collections.emptySet());
|
||||
input.forEach((key, value) -> output.put(key, (!exclusions.contains(key)) ? value : null));
|
||||
return output;
|
||||
}
|
||||
|
||||
private static final class CurrentIsoInstantSupplier implements Supplier<String> {
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return DateTimeFormatter.ISO_INSTANT.format(Instant.now());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -28,6 +27,7 @@ import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.InputFile;
|
||||
@@ -64,42 +64,12 @@ import org.springframework.util.StringUtils;
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@DisableCachingByDefault
|
||||
public class BootBuildImage extends DefaultTask {
|
||||
public abstract class BootBuildImage extends DefaultTask {
|
||||
|
||||
private static final String BUILDPACK_JVM_VERSION_KEY = "BP_JVM_VERSION";
|
||||
|
||||
private final String projectName;
|
||||
|
||||
private final Property<String> projectVersion;
|
||||
|
||||
private RegularFileProperty archiveFile;
|
||||
|
||||
private Property<JavaVersion> targetJavaVersion;
|
||||
|
||||
private String imageName;
|
||||
|
||||
private String builder;
|
||||
|
||||
private String runImage;
|
||||
|
||||
private Map<String, String> environment = new HashMap<>();
|
||||
|
||||
private boolean cleanCache;
|
||||
|
||||
private boolean verboseLogging;
|
||||
|
||||
private PullPolicy pullPolicy;
|
||||
|
||||
private boolean publish;
|
||||
|
||||
private final ListProperty<String> buildpacks;
|
||||
|
||||
private final ListProperty<String> bindings;
|
||||
|
||||
private String network;
|
||||
|
||||
private final ListProperty<String> tags;
|
||||
|
||||
private final CacheSpec buildCache;
|
||||
|
||||
private final CacheSpec launchCache;
|
||||
@@ -107,15 +77,20 @@ public class BootBuildImage extends DefaultTask {
|
||||
private final DockerSpec docker;
|
||||
|
||||
public BootBuildImage() {
|
||||
this.archiveFile = getProject().getObjects().fileProperty();
|
||||
this.targetJavaVersion = getProject().getObjects().property(JavaVersion.class);
|
||||
this.projectName = getProject().getName();
|
||||
this.projectVersion = getProject().getObjects().property(String.class);
|
||||
Project project = getProject();
|
||||
this.projectVersion.set(getProject().provider(() -> project.getVersion().toString()));
|
||||
this.buildpacks = getProject().getObjects().listProperty(String.class);
|
||||
this.bindings = getProject().getObjects().listProperty(String.class);
|
||||
this.tags = getProject().getObjects().listProperty(String.class);
|
||||
Property<String> projectVersion = project.getObjects().property(String.class)
|
||||
.convention(project.provider(() -> project.getVersion().toString()));
|
||||
getImageName().convention(project.provider(() -> {
|
||||
ImageName imageName = ImageName.of(this.projectName);
|
||||
if ("unspecified".equals(projectVersion.get())) {
|
||||
return ImageReference.of(imageName).toString();
|
||||
}
|
||||
return ImageReference.of(imageName, projectVersion.get()).toString();
|
||||
}));
|
||||
getCleanCache().convention(false);
|
||||
getVerboseLogging().convention(false);
|
||||
getPublish().convention(false);
|
||||
this.buildCache = getProject().getObjects().newInstance(CacheSpec.class);
|
||||
this.launchCache = getProject().getObjects().newInstance(CacheSpec.class);
|
||||
this.docker = getProject().getObjects().newInstance(DockerSpec.class);
|
||||
@@ -127,9 +102,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@InputFile
|
||||
@PathSensitive(PathSensitivity.RELATIVE)
|
||||
public RegularFileProperty getArchiveFile() {
|
||||
return this.archiveFile;
|
||||
}
|
||||
public abstract RegularFileProperty getArchiveFile();
|
||||
|
||||
/**
|
||||
* Returns the target Java version of the project (e.g. as provided by the
|
||||
@@ -138,9 +111,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public Property<JavaVersion> getTargetJavaVersion() {
|
||||
return this.targetJavaVersion;
|
||||
}
|
||||
public abstract Property<JavaVersion> getTargetJavaVersion();
|
||||
|
||||
/**
|
||||
* Returns the name of the image that will be built. When {@code null}, the name will
|
||||
@@ -150,18 +121,8 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getImageName() {
|
||||
return determineImageReference().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the image that will be built.
|
||||
* @param imageName name of the image
|
||||
*/
|
||||
@Option(option = "imageName", description = "The name of the image to generate")
|
||||
public void setImageName(String imageName) {
|
||||
this.imageName = imageName;
|
||||
}
|
||||
public abstract Property<String> getImageName();
|
||||
|
||||
/**
|
||||
* Returns the builder that will be used to build the image. When {@code null}, the
|
||||
@@ -170,18 +131,8 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getBuilder() {
|
||||
return this.builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the builder that will be used to build the image.
|
||||
* @param builder the builder
|
||||
*/
|
||||
@Option(option = "builder", description = "The name of the builder image to use")
|
||||
public void setBuilder(String builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
public abstract Property<String> getBuilder();
|
||||
|
||||
/**
|
||||
* Returns the run image that will be included in the built image. When {@code null},
|
||||
@@ -190,88 +141,32 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getRunImage() {
|
||||
return this.runImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the run image that will be included in the built image.
|
||||
* @param runImage the run image
|
||||
*/
|
||||
@Option(option = "runImage", description = "The name of the run image to use")
|
||||
public void setRunImage(String runImage) {
|
||||
this.runImage = runImage;
|
||||
}
|
||||
public abstract Property<String> getRunImage();
|
||||
|
||||
/**
|
||||
* Returns the environment that will be used when building the image.
|
||||
* @return the environment
|
||||
*/
|
||||
@Input
|
||||
public Map<String, String> getEnvironment() {
|
||||
return this.environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the environment that will be used when building the image.
|
||||
* @param environment the environment
|
||||
*/
|
||||
public void setEnvironment(Map<String, String> environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the environment that will be used when building the image.
|
||||
* @param name the name of the entry
|
||||
* @param value the value of the entry
|
||||
*/
|
||||
public void environment(String name, String value) {
|
||||
this.environment.put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entries to the environment that will be used when building the image.
|
||||
* @param entries the entries to add to the environment
|
||||
*/
|
||||
public void environment(Map<String, String> entries) {
|
||||
this.environment.putAll(entries);
|
||||
}
|
||||
public abstract MapProperty<String, String> getEnvironment();
|
||||
|
||||
/**
|
||||
* Returns whether caches should be cleaned before packaging.
|
||||
* @return whether caches should be cleaned
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Input
|
||||
public boolean isCleanCache() {
|
||||
return this.cleanCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether caches should be cleaned before packaging.
|
||||
* @param cleanCache {@code true} to clean the cache, otherwise {@code false}.
|
||||
*/
|
||||
@Option(option = "cleanCache", description = "Clean caches before packaging")
|
||||
public void setCleanCache(boolean cleanCache) {
|
||||
this.cleanCache = cleanCache;
|
||||
}
|
||||
public abstract Property<Boolean> getCleanCache();
|
||||
|
||||
/**
|
||||
* Whether verbose logging should be enabled while building the image.
|
||||
* @return whether verbose logging should be enabled
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Input
|
||||
public boolean isVerboseLogging() {
|
||||
return this.verboseLogging;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether verbose logging should be enabled while building the image.
|
||||
* @param verboseLogging {@code true} to enable verbose logging, otherwise
|
||||
* {@code false}.
|
||||
*/
|
||||
public void setVerboseLogging(boolean verboseLogging) {
|
||||
this.verboseLogging = verboseLogging;
|
||||
}
|
||||
public abstract Property<Boolean> getVerboseLogging();
|
||||
|
||||
/**
|
||||
* Returns image pull policy that will be used when building the image.
|
||||
@@ -279,36 +174,17 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public PullPolicy getPullPolicy() {
|
||||
return this.pullPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets image pull policy that will be used when building the image.
|
||||
* @param pullPolicy image pull policy {@link PullPolicy}
|
||||
*/
|
||||
@Option(option = "pullPolicy", description = "The image pull policy")
|
||||
public void setPullPolicy(PullPolicy pullPolicy) {
|
||||
this.pullPolicy = pullPolicy;
|
||||
}
|
||||
public abstract Property<PullPolicy> getPullPolicy();
|
||||
|
||||
/**
|
||||
* Whether the built image should be pushed to a registry.
|
||||
* @return whether the built image should be pushed
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Input
|
||||
public boolean isPublish() {
|
||||
return this.publish;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the built image should be pushed to a registry.
|
||||
* @param publish {@code true} the push the built image to a registry. {@code false}.
|
||||
*/
|
||||
@Option(option = "publishImage", description = "Publish the built image to a registry")
|
||||
public void setPublish(boolean publish) {
|
||||
this.publish = publish;
|
||||
}
|
||||
public abstract Property<Boolean> getPublish();
|
||||
|
||||
/**
|
||||
* Returns the buildpacks that will be used when building the image.
|
||||
@@ -316,33 +192,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public List<String> getBuildpacks() {
|
||||
return this.buildpacks.getOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the buildpacks that will be used when building the image.
|
||||
* @param buildpacks the buildpack references
|
||||
*/
|
||||
public void setBuildpacks(List<String> buildpacks) {
|
||||
this.buildpacks.set(buildpacks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the buildpacks that will be used when building the image.
|
||||
* @param buildpack the buildpack reference
|
||||
*/
|
||||
public void buildpack(String buildpack) {
|
||||
this.buildpacks.add(buildpack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entries to the buildpacks that will be used when building the image.
|
||||
* @param buildpacks the buildpack references
|
||||
*/
|
||||
public void buildpacks(List<String> buildpacks) {
|
||||
this.buildpacks.addAll(buildpacks);
|
||||
}
|
||||
public abstract ListProperty<String> getBuildpacks();
|
||||
|
||||
/**
|
||||
* Returns the volume bindings that will be mounted to the container when building the
|
||||
@@ -351,36 +201,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public List<String> getBindings() {
|
||||
return this.bindings.getOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the volume bindings that will be mounted to the container when building the
|
||||
* image.
|
||||
* @param bindings the bindings
|
||||
*/
|
||||
public void setBindings(List<String> bindings) {
|
||||
this.bindings.set(bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the volume bindings that will be mounted to the container when
|
||||
* building the image.
|
||||
* @param binding the binding
|
||||
*/
|
||||
public void binding(String binding) {
|
||||
this.bindings.add(binding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add entries to the volume bindings that will be mounted to the container when
|
||||
* building the image.
|
||||
* @param bindings the bindings
|
||||
*/
|
||||
public void bindings(List<String> bindings) {
|
||||
this.bindings.addAll(bindings);
|
||||
}
|
||||
public abstract ListProperty<String> getBindings();
|
||||
|
||||
/**
|
||||
* Returns the tags that will be created for the built image.
|
||||
@@ -388,33 +209,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public List<String> getTags() {
|
||||
return this.tags.getOrNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tags that will be created for the built image.
|
||||
* @param tags the tags
|
||||
*/
|
||||
public void setTags(List<String> tags) {
|
||||
this.tags.set(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the tags that will be created for the built image.
|
||||
* @param tag the tag
|
||||
*/
|
||||
public void tag(String tag) {
|
||||
this.tags.add(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add entries to the tags that will be created for the built image.
|
||||
* @param tags the tags
|
||||
*/
|
||||
public void tags(List<String> tags) {
|
||||
this.tags.addAll(tags);
|
||||
}
|
||||
public abstract ListProperty<String> getTags();
|
||||
|
||||
/**
|
||||
* Returns the network the build container will connect to.
|
||||
@@ -422,18 +217,8 @@ public class BootBuildImage extends DefaultTask {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getNetwork() {
|
||||
return this.network;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the network the build container will connect to.
|
||||
* @param network the network
|
||||
*/
|
||||
@Option(option = "network", description = "Connect detect and build containers to network")
|
||||
public void setNetwork(String network) {
|
||||
this.network = network;
|
||||
}
|
||||
public abstract Property<String> getNetwork();
|
||||
|
||||
/**
|
||||
* Returns the build cache that will be used when building the image.
|
||||
@@ -500,19 +285,8 @@ public class BootBuildImage extends DefaultTask {
|
||||
}
|
||||
|
||||
BuildRequest createRequest() {
|
||||
return customize(BuildRequest.of(determineImageReference(),
|
||||
(owner) -> new ZipFileTarArchive(this.archiveFile.get().getAsFile(), owner)));
|
||||
}
|
||||
|
||||
private ImageReference determineImageReference() {
|
||||
if (StringUtils.hasText(this.imageName)) {
|
||||
return ImageReference.of(this.imageName);
|
||||
}
|
||||
ImageName imageName = ImageName.of(this.projectName);
|
||||
if ("unspecified".equals(this.projectVersion.get())) {
|
||||
return ImageReference.of(imageName);
|
||||
}
|
||||
return ImageReference.of(imageName, this.projectVersion.get());
|
||||
return customize(BuildRequest.of(getImageName().map(ImageReference::of).get(),
|
||||
(owner) -> new ZipFileTarArchive(getArchiveFile().get().getAsFile(), owner)));
|
||||
}
|
||||
|
||||
private BuildRequest customize(BuildRequest request) {
|
||||
@@ -520,37 +294,40 @@ public class BootBuildImage extends DefaultTask {
|
||||
request = customizeRunImage(request);
|
||||
request = customizeEnvironment(request);
|
||||
request = customizeCreator(request);
|
||||
request = request.withCleanCache(this.cleanCache);
|
||||
request = request.withVerboseLogging(this.verboseLogging);
|
||||
request = request.withCleanCache(getCleanCache().get());
|
||||
request = request.withVerboseLogging(getVerboseLogging().get());
|
||||
request = customizePullPolicy(request);
|
||||
request = customizePublish(request);
|
||||
request = customizeBuildpacks(request);
|
||||
request = customizeBindings(request);
|
||||
request = customizeTags(request);
|
||||
request = customizeCaches(request);
|
||||
request = request.withNetwork(this.network);
|
||||
request = request.withNetwork(getNetwork().getOrNull());
|
||||
return request;
|
||||
}
|
||||
|
||||
private BuildRequest customizeBuilder(BuildRequest request) {
|
||||
if (StringUtils.hasText(this.builder)) {
|
||||
return request.withBuilder(ImageReference.of(this.builder));
|
||||
String builder = this.getBuilder().getOrNull();
|
||||
if (StringUtils.hasText(builder)) {
|
||||
return request.withBuilder(ImageReference.of(builder));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private BuildRequest customizeRunImage(BuildRequest request) {
|
||||
if (StringUtils.hasText(this.runImage)) {
|
||||
return request.withRunImage(ImageReference.of(this.runImage));
|
||||
String runImage = this.getRunImage().getOrNull();
|
||||
if (StringUtils.hasText(runImage)) {
|
||||
return request.withRunImage(ImageReference.of(runImage));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private BuildRequest customizeEnvironment(BuildRequest request) {
|
||||
if (this.environment != null && !this.environment.isEmpty()) {
|
||||
request = request.withEnv(this.environment);
|
||||
Map<String, String> environment = this.getEnvironment().getOrNull();
|
||||
if (environment != null && !environment.isEmpty()) {
|
||||
request = request.withEnv(environment);
|
||||
}
|
||||
if (this.targetJavaVersion.isPresent() && !request.getEnv().containsKey(BUILDPACK_JVM_VERSION_KEY)) {
|
||||
if (this.getTargetJavaVersion().isPresent() && !request.getEnv().containsKey(BUILDPACK_JVM_VERSION_KEY)) {
|
||||
request = request.withEnv(BUILDPACK_JVM_VERSION_KEY, translateTargetJavaVersion());
|
||||
}
|
||||
return request;
|
||||
@@ -565,19 +342,20 @@ public class BootBuildImage extends DefaultTask {
|
||||
}
|
||||
|
||||
private BuildRequest customizePullPolicy(BuildRequest request) {
|
||||
if (this.pullPolicy != null) {
|
||||
request = request.withPullPolicy(this.pullPolicy);
|
||||
PullPolicy pullPolicy = getPullPolicy().getOrNull();
|
||||
if (pullPolicy != null) {
|
||||
request = request.withPullPolicy(pullPolicy);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private BuildRequest customizePublish(BuildRequest request) {
|
||||
request = request.withPublish(this.publish);
|
||||
request = request.withPublish(getPublish().get());
|
||||
return request;
|
||||
}
|
||||
|
||||
private BuildRequest customizeBuildpacks(BuildRequest request) {
|
||||
List<String> buildpacks = this.buildpacks.getOrNull();
|
||||
List<String> buildpacks = getBuildpacks().getOrNull();
|
||||
if (buildpacks != null && !buildpacks.isEmpty()) {
|
||||
return request.withBuildpacks(buildpacks.stream().map(BuildpackReference::of).toList());
|
||||
}
|
||||
@@ -585,7 +363,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
}
|
||||
|
||||
private BuildRequest customizeBindings(BuildRequest request) {
|
||||
List<String> bindings = this.bindings.getOrNull();
|
||||
List<String> bindings = getBindings().getOrNull();
|
||||
if (bindings != null && !bindings.isEmpty()) {
|
||||
return request.withBindings(bindings.stream().map(Binding::of).toList());
|
||||
}
|
||||
@@ -593,7 +371,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
}
|
||||
|
||||
private BuildRequest customizeTags(BuildRequest request) {
|
||||
List<String> tags = this.tags.getOrNull();
|
||||
List<String> tags = getTags().getOrNull();
|
||||
if (tags != null && !tags.isEmpty()) {
|
||||
return request.withTags(tags.stream().map(ImageReference::of).toList());
|
||||
}
|
||||
@@ -611,7 +389,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
}
|
||||
|
||||
private String translateTargetJavaVersion() {
|
||||
return this.targetJavaVersion.get().getMajorVersion() + ".*";
|
||||
return this.getTargetJavaVersion().get().getMajorVersion() + ".*";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
import org.gradle.api.internal.file.copy.CopyAction;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.tasks.Internal;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
@@ -46,7 +45,7 @@ import org.gradle.work.DisableCachingByDefault;
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@DisableCachingByDefault(because = "Not worth caching")
|
||||
public class BootJar extends Jar implements BootArchive {
|
||||
public abstract class BootJar extends Jar implements BootArchive {
|
||||
|
||||
private static final String LAUNCHER = "org.springframework.boot.loader.JarLauncher";
|
||||
|
||||
@@ -64,8 +63,6 @@ public class BootJar extends Jar implements BootArchive {
|
||||
|
||||
private final CopySpec bootInfSpec;
|
||||
|
||||
private final Property<String> mainClass;
|
||||
|
||||
private final LayeredSpec layered;
|
||||
|
||||
private FileCollection classpath;
|
||||
@@ -77,7 +74,6 @@ public class BootJar extends Jar implements BootArchive {
|
||||
this.support = new BootArchiveSupport(LAUNCHER, new LibrarySpec(), new ZipCompressionResolver());
|
||||
Project project = getProject();
|
||||
this.bootInfSpec = project.copySpec().into("BOOT-INF");
|
||||
this.mainClass = project.getObjects().property(String.class);
|
||||
this.layered = project.getObjects().newInstance(LayeredSpec.class);
|
||||
configureBootInfSpec(this.bootInfSpec);
|
||||
getMainSpec().with(this.bootInfSpec);
|
||||
@@ -128,24 +124,19 @@ public class BootJar extends Jar implements BootArchive {
|
||||
}
|
||||
|
||||
private boolean isLayeredDisabled() {
|
||||
return this.layered != null && !this.layered.isEnabled();
|
||||
return !getLayered().getEnabled().get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CopyAction createCopyAction() {
|
||||
if (!isLayeredDisabled()) {
|
||||
LayerResolver layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
|
||||
String layerToolsLocation = this.layered.isIncludeLayerTools() ? LIB_DIRECTORY : null;
|
||||
String layerToolsLocation = this.layered.getIncludeLayerTools().get() ? LIB_DIRECTORY : null;
|
||||
return this.support.createCopyAction(this, this.resolvedDependencies, layerResolver, layerToolsLocation);
|
||||
}
|
||||
return this.support.createCopyAction(this, this.resolvedDependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Property<String> getMainClass() {
|
||||
return this.mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requiresUnpack(String... patterns) {
|
||||
this.support.requiresUnpack(patterns);
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
import org.gradle.api.internal.file.copy.CopyAction;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.Internal;
|
||||
@@ -46,7 +45,7 @@ import org.gradle.work.DisableCachingByDefault;
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@DisableCachingByDefault(because = "Not worth caching")
|
||||
public class BootWar extends War implements BootArchive {
|
||||
public abstract class BootWar extends War implements BootArchive {
|
||||
|
||||
private static final String LAUNCHER = "org.springframework.boot.loader.WarLauncher";
|
||||
|
||||
@@ -62,8 +61,6 @@ public class BootWar extends War implements BootArchive {
|
||||
|
||||
private final BootArchiveSupport support;
|
||||
|
||||
private final Property<String> mainClass;
|
||||
|
||||
private final ResolvedDependencies resolvedDependencies = new ResolvedDependencies();
|
||||
|
||||
private final LayeredSpec layered;
|
||||
@@ -76,7 +73,6 @@ public class BootWar extends War implements BootArchive {
|
||||
public BootWar() {
|
||||
this.support = new BootArchiveSupport(LAUNCHER, new LibrarySpec(), new ZipCompressionResolver());
|
||||
Project project = getProject();
|
||||
this.mainClass = project.getObjects().property(String.class);
|
||||
this.layered = project.getObjects().newInstance(LayeredSpec.class);
|
||||
getWebInf().into("lib-provided", fromCallTo(this::getProvidedLibFiles));
|
||||
this.support.moveModuleInfoToRoot(getRootSpec());
|
||||
@@ -103,24 +99,19 @@ public class BootWar extends War implements BootArchive {
|
||||
}
|
||||
|
||||
private boolean isLayeredDisabled() {
|
||||
return this.layered != null && !this.layered.isEnabled();
|
||||
return !this.layered.getEnabled().get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CopyAction createCopyAction() {
|
||||
if (!isLayeredDisabled()) {
|
||||
LayerResolver layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
|
||||
String layerToolsLocation = this.layered.isIncludeLayerTools() ? LIB_DIRECTORY : null;
|
||||
String layerToolsLocation = this.layered.getIncludeLayerTools().get() ? LIB_DIRECTORY : null;
|
||||
return this.support.createCopyAction(this, this.resolvedDependencies, layerResolver, layerToolsLocation);
|
||||
}
|
||||
return this.support.createCopyAction(this, this.resolvedDependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Property<String> getMainClass() {
|
||||
return this.mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requiresUnpack(String... patterns) {
|
||||
this.support.requiresUnpack(patterns);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2021 the original author or authors.
|
||||
* Copyright 2021-2022 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.
|
||||
@@ -20,6 +20,8 @@ import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.build.Cache;
|
||||
@@ -32,11 +34,13 @@ import org.springframework.boot.buildpack.platform.build.Cache;
|
||||
*/
|
||||
public class CacheSpec {
|
||||
|
||||
private final ObjectFactory objectFactory;
|
||||
|
||||
private Cache cache = null;
|
||||
|
||||
@Inject
|
||||
public CacheSpec() {
|
||||
|
||||
public CacheSpec(ObjectFactory objectFactory) {
|
||||
this.objectFactory = objectFactory;
|
||||
}
|
||||
|
||||
public Cache asCache() {
|
||||
@@ -51,34 +55,22 @@ public class CacheSpec {
|
||||
if (this.cache != null) {
|
||||
throw new GradleException("Each image building cache can be configured only once");
|
||||
}
|
||||
VolumeCacheSpec spec = new VolumeCacheSpec();
|
||||
VolumeCacheSpec spec = this.objectFactory.newInstance(VolumeCacheSpec.class);
|
||||
action.execute(spec);
|
||||
this.cache = Cache.volume(spec.getName());
|
||||
this.cache = Cache.volume(spec.getName().get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for an image building cache stored in a Docker volume.
|
||||
*/
|
||||
public static class VolumeCacheSpec {
|
||||
|
||||
private String name;
|
||||
public abstract static class VolumeCacheSpec {
|
||||
|
||||
/**
|
||||
* Returns the name of the cache.
|
||||
* @return the cache name
|
||||
*/
|
||||
@Input
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the cache.
|
||||
* @param name the cache name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public abstract Property<String> getName();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,12 @@
|
||||
|
||||
package org.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
@@ -31,23 +35,18 @@ import org.springframework.boot.buildpack.platform.docker.configuration.DockerCo
|
||||
* @author Scott Frederick
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public class DockerSpec {
|
||||
|
||||
private String host;
|
||||
|
||||
private boolean tlsVerify;
|
||||
|
||||
private String certPath;
|
||||
|
||||
private boolean bindHostToBuilder;
|
||||
public abstract class DockerSpec {
|
||||
|
||||
private final DockerRegistrySpec builderRegistry;
|
||||
|
||||
private final DockerRegistrySpec publishRegistry;
|
||||
|
||||
public DockerSpec() {
|
||||
this.builderRegistry = new DockerRegistrySpec();
|
||||
this.publishRegistry = new DockerRegistrySpec();
|
||||
@Inject
|
||||
public DockerSpec(ObjectFactory objects) {
|
||||
this.builderRegistry = objects.newInstance(DockerRegistrySpec.class);
|
||||
this.publishRegistry = objects.newInstance(DockerRegistrySpec.class);
|
||||
getBindHostToBuilder().convention(false);
|
||||
getTlsVerify().convention(false);
|
||||
}
|
||||
|
||||
DockerSpec(DockerRegistrySpec builderRegistry, DockerRegistrySpec publishRegistry) {
|
||||
@@ -57,43 +56,19 @@ public class DockerSpec {
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
public abstract Property<String> getHost();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public Boolean isTlsVerify() {
|
||||
return this.tlsVerify;
|
||||
}
|
||||
|
||||
public void setTlsVerify(boolean tlsVerify) {
|
||||
this.tlsVerify = tlsVerify;
|
||||
}
|
||||
public abstract Property<Boolean> getTlsVerify();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public String getCertPath() {
|
||||
return this.certPath;
|
||||
}
|
||||
|
||||
public void setCertPath(String certPath) {
|
||||
this.certPath = certPath;
|
||||
}
|
||||
public abstract Property<String> getCertPath();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public Boolean isBindHostToBuilder() {
|
||||
return this.bindHostToBuilder;
|
||||
}
|
||||
|
||||
public void setBindHostToBuilder(boolean use) {
|
||||
this.bindHostToBuilder = use;
|
||||
}
|
||||
public abstract Property<Boolean> getBindHostToBuilder();
|
||||
|
||||
/**
|
||||
* Returns the {@link DockerRegistrySpec} that configures authentication to the
|
||||
@@ -142,15 +117,16 @@ public class DockerSpec {
|
||||
DockerConfiguration asDockerConfiguration() {
|
||||
DockerConfiguration dockerConfiguration = new DockerConfiguration();
|
||||
dockerConfiguration = customizeHost(dockerConfiguration);
|
||||
dockerConfiguration = dockerConfiguration.withBindHostToBuilder(this.bindHostToBuilder);
|
||||
dockerConfiguration = dockerConfiguration.withBindHostToBuilder(getBindHostToBuilder().get());
|
||||
dockerConfiguration = customizeBuilderAuthentication(dockerConfiguration);
|
||||
dockerConfiguration = customizePublishAuthentication(dockerConfiguration);
|
||||
return dockerConfiguration;
|
||||
}
|
||||
|
||||
private DockerConfiguration customizeHost(DockerConfiguration dockerConfiguration) {
|
||||
if (this.host != null) {
|
||||
return dockerConfiguration.withHost(this.host, this.tlsVerify, this.certPath);
|
||||
String host = getHost().getOrNull();
|
||||
if (host != null) {
|
||||
return dockerConfiguration.withHost(host, getTlsVerify().get(), getCertPath().getOrNull());
|
||||
}
|
||||
return dockerConfiguration;
|
||||
}
|
||||
@@ -160,11 +136,12 @@ public class DockerSpec {
|
||||
return dockerConfiguration;
|
||||
}
|
||||
if (this.builderRegistry.hasTokenAuth() && !this.builderRegistry.hasUserAuth()) {
|
||||
return dockerConfiguration.withBuilderRegistryTokenAuthentication(this.builderRegistry.getToken());
|
||||
return dockerConfiguration.withBuilderRegistryTokenAuthentication(this.builderRegistry.getToken().get());
|
||||
}
|
||||
if (this.builderRegistry.hasUserAuth() && !this.builderRegistry.hasTokenAuth()) {
|
||||
return dockerConfiguration.withBuilderRegistryUserAuthentication(this.builderRegistry.getUsername(),
|
||||
this.builderRegistry.getPassword(), this.builderRegistry.getUrl(), this.builderRegistry.getEmail());
|
||||
return dockerConfiguration.withBuilderRegistryUserAuthentication(this.builderRegistry.getUsername().get(),
|
||||
this.builderRegistry.getPassword().get(), this.builderRegistry.getUrl().getOrNull(),
|
||||
this.builderRegistry.getEmail().getOrNull());
|
||||
}
|
||||
throw new GradleException(
|
||||
"Invalid Docker builder registry configuration, either token or username/password must be provided");
|
||||
@@ -175,11 +152,12 @@ public class DockerSpec {
|
||||
return dockerConfiguration.withEmptyPublishRegistryAuthentication();
|
||||
}
|
||||
if (this.publishRegistry.hasTokenAuth() && !this.publishRegistry.hasUserAuth()) {
|
||||
return dockerConfiguration.withPublishRegistryTokenAuthentication(this.publishRegistry.getToken());
|
||||
return dockerConfiguration.withPublishRegistryTokenAuthentication(this.publishRegistry.getToken().get());
|
||||
}
|
||||
if (this.publishRegistry.hasUserAuth() && !this.publishRegistry.hasTokenAuth()) {
|
||||
return dockerConfiguration.withPublishRegistryUserAuthentication(this.publishRegistry.getUsername(),
|
||||
this.publishRegistry.getPassword(), this.publishRegistry.getUrl(), this.publishRegistry.getEmail());
|
||||
return dockerConfiguration.withPublishRegistryUserAuthentication(this.publishRegistry.getUsername().get(),
|
||||
this.publishRegistry.getPassword().get(), this.publishRegistry.getUrl().getOrNull(),
|
||||
this.publishRegistry.getEmail().getOrNull());
|
||||
}
|
||||
throw new GradleException(
|
||||
"Invalid Docker publish registry configuration, either token or username/password must be provided");
|
||||
@@ -188,31 +166,7 @@ public class DockerSpec {
|
||||
/**
|
||||
* Encapsulates Docker registry authentication configuration options.
|
||||
*/
|
||||
public static class DockerRegistrySpec {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String url;
|
||||
|
||||
private String email;
|
||||
|
||||
private String token;
|
||||
|
||||
public DockerRegistrySpec() {
|
||||
}
|
||||
|
||||
DockerRegistrySpec(String username, String password, String url, String email) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.url = url;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
DockerRegistrySpec(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
public abstract static class DockerRegistrySpec {
|
||||
|
||||
/**
|
||||
* Returns the username to use when authenticating to the Docker registry.
|
||||
@@ -220,17 +174,7 @@ public class DockerSpec {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username to use when authenticating to the Docker registry.
|
||||
* @param username the registry username
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
public abstract Property<String> getUsername();
|
||||
|
||||
/**
|
||||
* Returns the password to use when authenticating to the Docker registry.
|
||||
@@ -238,17 +182,7 @@ public class DockerSpec {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password to use when authenticating to the Docker registry.
|
||||
* @param password the registry username
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
public abstract Property<String> getPassword();
|
||||
|
||||
/**
|
||||
* Returns the Docker registry URL.
|
||||
@@ -256,17 +190,7 @@ public class DockerSpec {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Docker registry URL.
|
||||
* @param url the registry URL
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
public abstract Property<String> getUrl();
|
||||
|
||||
/**
|
||||
* Returns the email address associated with the Docker registry username.
|
||||
@@ -274,17 +198,7 @@ public class DockerSpec {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getEmail() {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the email address associated with the Docker registry username.
|
||||
* @param email the registry email address
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
public abstract Property<String> getEmail();
|
||||
|
||||
/**
|
||||
* Returns the identity token to use when authenticating to the Docker registry.
|
||||
@@ -292,29 +206,36 @@ public class DockerSpec {
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public String getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the identity token to use when authenticating to the Docker registry.
|
||||
* @param token the registry identity token
|
||||
*/
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
public abstract Property<String> getToken();
|
||||
|
||||
boolean hasEmptyAuth() {
|
||||
return this.username == null && this.password == null && this.url == null && this.email == null
|
||||
&& this.token == null;
|
||||
return nonePresent(getUsername(), getPassword(), getUrl(), getEmail(), getToken());
|
||||
}
|
||||
|
||||
private boolean nonePresent(Property<?>... properties) {
|
||||
for (Property<?> property : properties) {
|
||||
if (property.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean hasUserAuth() {
|
||||
return this.getUsername() != null && this.getPassword() != null;
|
||||
return allPresent(getUsername(), getPassword());
|
||||
}
|
||||
|
||||
private boolean allPresent(Property<?>... properties) {
|
||||
for (Property<?> property : properties) {
|
||||
if (!property.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean hasTokenAuth() {
|
||||
return this.getToken() != null;
|
||||
return this.getToken().isPresent();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
|
||||
@@ -49,64 +51,38 @@ import org.springframework.util.Assert;
|
||||
* @author Phillip Webb
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class LayeredSpec {
|
||||
|
||||
private boolean includeLayerTools = true;
|
||||
|
||||
private boolean enabled = true;
|
||||
public abstract class LayeredSpec {
|
||||
|
||||
private ApplicationSpec application;
|
||||
|
||||
private DependenciesSpec dependencies;
|
||||
|
||||
@Optional
|
||||
private List<String> layerOrder;
|
||||
|
||||
private Layers layers;
|
||||
|
||||
@Inject
|
||||
public LayeredSpec(ObjectFactory objects) {
|
||||
this.application = objects.newInstance(ApplicationSpec.class);
|
||||
this.dependencies = objects.newInstance(DependenciesSpec.class);
|
||||
getEnabled().convention(true);
|
||||
getIncludeLayerTools().convention(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the layer tools should be included as a dependency in the layered
|
||||
* archive.
|
||||
* @return whether the layer tools should be included
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Input
|
||||
public boolean isIncludeLayerTools() {
|
||||
return this.includeLayerTools;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the layer tools should be included as a dependency in the layered
|
||||
* archive.
|
||||
* @param includeLayerTools {@code true} if the layer tools should be included,
|
||||
* otherwise {@code false}
|
||||
*/
|
||||
public void setIncludeLayerTools(boolean includeLayerTools) {
|
||||
this.includeLayerTools = includeLayerTools;
|
||||
}
|
||||
public abstract Property<Boolean> getIncludeLayerTools();
|
||||
|
||||
/**
|
||||
* Returns whether the layers.idx should be included in the archive.
|
||||
* @return whether the layers.idx should be included
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Input
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the layers.idx should be included in the archive.
|
||||
* @param enabled {@code true} layers.idx should be included in the archive, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
public abstract Property<Boolean> getEnabled();
|
||||
|
||||
/**
|
||||
* Returns the {@link ApplicationSpec} that controls the layers to which application
|
||||
@@ -168,25 +144,8 @@ public class LayeredSpec {
|
||||
* @return the layer order
|
||||
*/
|
||||
@Input
|
||||
public List<String> getLayerOrder() {
|
||||
return this.layerOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the order of the layers in the archive from least to most frequently changing.
|
||||
* @param layerOrder the layer order
|
||||
*/
|
||||
public void setLayerOrder(String... layerOrder) {
|
||||
this.layerOrder = Arrays.asList(layerOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the order of the layers in the archive from least to most frequently changing.
|
||||
* @param layerOrder the layer order
|
||||
*/
|
||||
public void setLayerOrder(List<String> layerOrder) {
|
||||
this.layerOrder = layerOrder;
|
||||
}
|
||||
@Optional
|
||||
public abstract ListProperty<String> getLayerOrder();
|
||||
|
||||
/**
|
||||
* Return this configuration as a {@link Layers} instance. This method should only be
|
||||
@@ -203,12 +162,13 @@ public class LayeredSpec {
|
||||
}
|
||||
|
||||
private Layers createLayers() {
|
||||
if (this.layerOrder == null || this.layerOrder.isEmpty()) {
|
||||
List<String> layerOrder = getLayerOrder().getOrNull();
|
||||
if (layerOrder == null || layerOrder.isEmpty()) {
|
||||
Assert.state(this.application.isEmpty() && this.dependencies.isEmpty(),
|
||||
"The 'layerOrder' must be defined when using custom layering");
|
||||
return Layers.IMPLICIT;
|
||||
}
|
||||
List<Layer> layers = this.layerOrder.stream().map(Layer::new).toList();
|
||||
List<Layer> layers = layerOrder.stream().map(Layer::new).toList();
|
||||
return new CustomLayers(layers, this.application.asSelectors(), this.dependencies.asSelectors());
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.File;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gradle.api.file.SourceDirectorySet;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
@@ -33,30 +34,20 @@ import org.gradle.work.DisableCachingByDefault;
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@DisableCachingByDefault(because = "Application should always run")
|
||||
public class BootRun extends JavaExec {
|
||||
public abstract class BootRun extends JavaExec {
|
||||
|
||||
private boolean optimizedLaunch = true;
|
||||
public BootRun() {
|
||||
getOptimizedLaunch().convention(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the JVM's launch should be optimized, otherwise
|
||||
* {@code false}. Defaults to {@code true}.
|
||||
* Returns the property for whether the JVM's launch should be optimized. The property
|
||||
* defaults to {@code true}.
|
||||
* @return whether the JVM's launch should be optimized
|
||||
* @since 2.2.0
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Input
|
||||
public boolean isOptimizedLaunch() {
|
||||
return this.optimizedLaunch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the JVM's launch should be optimized. Defaults to {@code true}.
|
||||
* @param optimizedLaunch {@code true} if the JVM's launch should be optimised,
|
||||
* otherwise {@code false}
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public void setOptimizedLaunch(boolean optimizedLaunch) {
|
||||
this.optimizedLaunch = optimizedLaunch;
|
||||
}
|
||||
public abstract Property<Boolean> getOptimizedLaunch();
|
||||
|
||||
/**
|
||||
* Adds the {@link SourceDirectorySet#getSrcDirs() source directories} of the given
|
||||
@@ -73,7 +64,7 @@ public class BootRun extends JavaExec {
|
||||
|
||||
@Override
|
||||
public void exec() {
|
||||
if (this.optimizedLaunch) {
|
||||
if (this.getOptimizedLaunch().get()) {
|
||||
setJvmArgs(getJvmArgs());
|
||||
jvmArgs("-XX:TieredStopAtLevel=1");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user