Only create effective bom artifact when needed
Closes gh-22143
This commit is contained in:
parent
c000ccdaea
commit
d33a01a13f
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
package org.springframework.boot.build.bom;
|
package org.springframework.boot.build.bom;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -23,21 +27,42 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.xpath.XPath;
|
||||||
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
|
||||||
import groovy.lang.Closure;
|
import groovy.lang.Closure;
|
||||||
import groovy.lang.GroovyObjectSupport;
|
import groovy.lang.GroovyObjectSupport;
|
||||||
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
||||||
import org.apache.maven.artifact.versioning.VersionRange;
|
import org.apache.maven.artifact.versioning.VersionRange;
|
||||||
|
import org.gradle.api.Action;
|
||||||
|
import org.gradle.api.GradleException;
|
||||||
import org.gradle.api.InvalidUserCodeException;
|
import org.gradle.api.InvalidUserCodeException;
|
||||||
import org.gradle.api.InvalidUserDataException;
|
import org.gradle.api.InvalidUserDataException;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.Task;
|
||||||
|
import org.gradle.api.artifacts.Configuration;
|
||||||
import org.gradle.api.artifacts.dsl.DependencyHandler;
|
import org.gradle.api.artifacts.dsl.DependencyHandler;
|
||||||
import org.gradle.api.plugins.JavaPlatformPlugin;
|
import org.gradle.api.plugins.JavaPlatformPlugin;
|
||||||
|
import org.gradle.api.publish.maven.tasks.GenerateMavenPom;
|
||||||
|
import org.gradle.api.tasks.Sync;
|
||||||
|
import org.gradle.api.tasks.TaskExecutionException;
|
||||||
import org.gradle.util.ConfigureUtil;
|
import org.gradle.util.ConfigureUtil;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import org.springframework.boot.build.DeployedPlugin;
|
||||||
import org.springframework.boot.build.bom.Library.Exclusion;
|
import org.springframework.boot.build.bom.Library.Exclusion;
|
||||||
import org.springframework.boot.build.bom.Library.Group;
|
import org.springframework.boot.build.bom.Library.Group;
|
||||||
import org.springframework.boot.build.bom.Library.Module;
|
import org.springframework.boot.build.bom.Library.Module;
|
||||||
import org.springframework.boot.build.bom.Library.ProhibitedVersion;
|
import org.springframework.boot.build.bom.Library.ProhibitedVersion;
|
||||||
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
||||||
|
import org.springframework.boot.build.mavenplugin.MavenExec;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DSL extensions for {@link BomPlugin}.
|
* DSL extensions for {@link BomPlugin}.
|
||||||
|
@ -56,8 +81,11 @@ public class BomExtension {
|
||||||
|
|
||||||
private final DependencyHandler dependencyHandler;
|
private final DependencyHandler dependencyHandler;
|
||||||
|
|
||||||
public BomExtension(DependencyHandler dependencyHandler) {
|
private final Project project;
|
||||||
|
|
||||||
|
public BomExtension(DependencyHandler dependencyHandler, Project project) {
|
||||||
this.dependencyHandler = dependencyHandler;
|
this.dependencyHandler = dependencyHandler;
|
||||||
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Library> getLibraries() {
|
public List<Library> getLibraries() {
|
||||||
|
@ -80,6 +108,43 @@ public class BomExtension {
|
||||||
libraryHandler.prohibitedVersions));
|
libraryHandler.prohibitedVersions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void effectiveBomArtifact() {
|
||||||
|
Configuration effectiveBomConfiguration = this.project.getConfigurations().create("effectiveBom");
|
||||||
|
this.project.getTasks().matching((task) -> task.getName().equals(DeployedPlugin.GENERATE_POM_TASK_NAME))
|
||||||
|
.all((task) -> {
|
||||||
|
Sync syncBom = this.project.getTasks().create("syncBom", Sync.class);
|
||||||
|
syncBom.dependsOn(task);
|
||||||
|
File generatedBomDir = new File(this.project.getBuildDir(), "generated/bom");
|
||||||
|
syncBom.setDestinationDir(generatedBomDir);
|
||||||
|
syncBom.from(((GenerateMavenPom) task).getDestination(), (pom) -> pom.rename((name) -> "pom.xml"));
|
||||||
|
try {
|
||||||
|
String settingsXmlContent = FileCopyUtils
|
||||||
|
.copyToString(new InputStreamReader(
|
||||||
|
getClass().getClassLoader().getResourceAsStream("effective-bom-settings.xml"),
|
||||||
|
StandardCharsets.UTF_8))
|
||||||
|
.replace("localRepositoryPath",
|
||||||
|
new File(this.project.getBuildDir(), "local-m2-repository").getAbsolutePath());
|
||||||
|
syncBom.from(this.project.getResources().getText().fromString(settingsXmlContent),
|
||||||
|
(settingsXml) -> settingsXml.rename((name) -> "settings.xml"));
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new GradleException("Failed to prepare settings.xml", ex);
|
||||||
|
}
|
||||||
|
MavenExec generateEffectiveBom = this.project.getTasks().create("generateEffectiveBom",
|
||||||
|
MavenExec.class);
|
||||||
|
generateEffectiveBom.setProjectDir(generatedBomDir);
|
||||||
|
File effectiveBom = new File(this.project.getBuildDir(),
|
||||||
|
"generated/effective-bom/" + this.project.getName() + "-effective-bom.xml");
|
||||||
|
generateEffectiveBom.args("--settings", "settings.xml", "help:effective-pom",
|
||||||
|
"-Doutput=" + effectiveBom);
|
||||||
|
generateEffectiveBom.dependsOn(syncBom);
|
||||||
|
generateEffectiveBom.getOutputs().file(effectiveBom);
|
||||||
|
generateEffectiveBom.doLast(new StripUnrepeatableOutputAction(effectiveBom));
|
||||||
|
this.project.getArtifacts().add(effectiveBomConfiguration.getName(), effectiveBom,
|
||||||
|
(artifact) -> artifact.builtBy(generateEffectiveBom));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private String createDependencyNotation(String groupId, String artifactId, DependencyVersion version) {
|
private String createDependencyNotation(String groupId, String artifactId, DependencyVersion version) {
|
||||||
return groupId + ":" + artifactId + ":" + version;
|
return groupId + ":" + artifactId + ":" + version;
|
||||||
}
|
}
|
||||||
|
@ -298,4 +363,38 @@ public class BomExtension {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class StripUnrepeatableOutputAction implements Action<Task> {
|
||||||
|
|
||||||
|
private final File effectiveBom;
|
||||||
|
|
||||||
|
private StripUnrepeatableOutputAction(File xmlFile) {
|
||||||
|
this.effectiveBom = xmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Task task) {
|
||||||
|
try {
|
||||||
|
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(this.effectiveBom);
|
||||||
|
XPath xpath = XPathFactory.newInstance().newXPath();
|
||||||
|
NodeList comments = (NodeList) xpath.evaluate("//comment()", document, XPathConstants.NODESET);
|
||||||
|
for (int i = 0; i < comments.getLength(); i++) {
|
||||||
|
org.w3c.dom.Node comment = comments.item(i);
|
||||||
|
comment.getParentNode().removeChild(comment);
|
||||||
|
}
|
||||||
|
org.w3c.dom.Node build = (org.w3c.dom.Node) xpath.evaluate("/project/build", document,
|
||||||
|
XPathConstants.NODE);
|
||||||
|
build.getParentNode().removeChild(build);
|
||||||
|
org.w3c.dom.Node reporting = (org.w3c.dom.Node) xpath.evaluate("/project/reporting", document,
|
||||||
|
XPathConstants.NODE);
|
||||||
|
reporting.getParentNode().removeChild(reporting);
|
||||||
|
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document),
|
||||||
|
new StreamResult(this.effectiveBom));
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new TaskExecutionException(task, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,28 +16,13 @@
|
||||||
|
|
||||||
package org.springframework.boot.build.bom;
|
package org.springframework.boot.build.bom;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.dom.DOMSource;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import javax.xml.xpath.XPath;
|
|
||||||
import javax.xml.xpath.XPathConstants;
|
|
||||||
import javax.xml.xpath.XPathFactory;
|
|
||||||
|
|
||||||
import groovy.util.Node;
|
import groovy.util.Node;
|
||||||
import groovy.xml.QName;
|
import groovy.xml.QName;
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.GradleException;
|
|
||||||
import org.gradle.api.Plugin;
|
import org.gradle.api.Plugin;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.Task;
|
|
||||||
import org.gradle.api.artifacts.Configuration;
|
import org.gradle.api.artifacts.Configuration;
|
||||||
import org.gradle.api.plugins.JavaPlatformExtension;
|
import org.gradle.api.plugins.JavaPlatformExtension;
|
||||||
import org.gradle.api.plugins.JavaPlatformPlugin;
|
import org.gradle.api.plugins.JavaPlatformPlugin;
|
||||||
|
@ -45,18 +30,11 @@ import org.gradle.api.plugins.PluginContainer;
|
||||||
import org.gradle.api.publish.PublishingExtension;
|
import org.gradle.api.publish.PublishingExtension;
|
||||||
import org.gradle.api.publish.maven.MavenPom;
|
import org.gradle.api.publish.maven.MavenPom;
|
||||||
import org.gradle.api.publish.maven.MavenPublication;
|
import org.gradle.api.publish.maven.MavenPublication;
|
||||||
import org.gradle.api.publish.maven.tasks.GenerateMavenPom;
|
|
||||||
import org.gradle.api.tasks.Sync;
|
|
||||||
import org.gradle.api.tasks.TaskExecutionException;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
import org.springframework.boot.build.DeployedPlugin;
|
import org.springframework.boot.build.DeployedPlugin;
|
||||||
import org.springframework.boot.build.MavenRepositoryPlugin;
|
import org.springframework.boot.build.MavenRepositoryPlugin;
|
||||||
import org.springframework.boot.build.bom.Library.Group;
|
import org.springframework.boot.build.bom.Library.Group;
|
||||||
import org.springframework.boot.build.bom.bomr.UpgradeBom;
|
import org.springframework.boot.build.bom.bomr.UpgradeBom;
|
||||||
import org.springframework.boot.build.mavenplugin.MavenExec;
|
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Plugin} for defining a bom. Dependencies are added as constraints in the
|
* {@link Plugin} for defining a bom. Dependencies are added as constraints in the
|
||||||
|
@ -78,43 +56,12 @@ public class BomPlugin implements Plugin<Project> {
|
||||||
JavaPlatformExtension javaPlatform = project.getExtensions().getByType(JavaPlatformExtension.class);
|
JavaPlatformExtension javaPlatform = project.getExtensions().getByType(JavaPlatformExtension.class);
|
||||||
javaPlatform.allowDependencies();
|
javaPlatform.allowDependencies();
|
||||||
createApiEnforcedConfiguration(project);
|
createApiEnforcedConfiguration(project);
|
||||||
BomExtension bom = project.getExtensions().create("bom", BomExtension.class, project.getDependencies());
|
BomExtension bom = project.getExtensions().create("bom", BomExtension.class, project.getDependencies(),
|
||||||
|
project);
|
||||||
project.getTasks().create("bomrCheck", CheckBom.class, bom);
|
project.getTasks().create("bomrCheck", CheckBom.class, bom);
|
||||||
project.getTasks().create("bomrUpgrade", UpgradeBom.class, bom);
|
project.getTasks().create("bomrUpgrade", UpgradeBom.class, bom);
|
||||||
new PublishingCustomizer(project, bom).customize();
|
new PublishingCustomizer(project, bom).customize();
|
||||||
Configuration effectiveBomConfiguration = project.getConfigurations().create("effectiveBom");
|
|
||||||
project.getTasks().matching((task) -> task.getName().equals(DeployedPlugin.GENERATE_POM_TASK_NAME))
|
|
||||||
.all((task) -> {
|
|
||||||
Sync syncBom = project.getTasks().create("syncBom", Sync.class);
|
|
||||||
syncBom.dependsOn(task);
|
|
||||||
File generatedBomDir = new File(project.getBuildDir(), "generated/bom");
|
|
||||||
syncBom.setDestinationDir(generatedBomDir);
|
|
||||||
syncBom.from(((GenerateMavenPom) task).getDestination(), (pom) -> pom.rename((name) -> "pom.xml"));
|
|
||||||
try {
|
|
||||||
String settingsXmlContent = FileCopyUtils
|
|
||||||
.copyToString(new InputStreamReader(
|
|
||||||
getClass().getClassLoader().getResourceAsStream("effective-bom-settings.xml"),
|
|
||||||
StandardCharsets.UTF_8))
|
|
||||||
.replace("localRepositoryPath",
|
|
||||||
new File(project.getBuildDir(), "local-m2-repository").getAbsolutePath());
|
|
||||||
syncBom.from(project.getResources().getText().fromString(settingsXmlContent),
|
|
||||||
(settingsXml) -> settingsXml.rename((name) -> "settings.xml"));
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new GradleException("Failed to prepare settings.xml", ex);
|
|
||||||
}
|
|
||||||
MavenExec generateEffectiveBom = project.getTasks().create("generateEffectiveBom", MavenExec.class);
|
|
||||||
generateEffectiveBom.setProjectDir(generatedBomDir);
|
|
||||||
File effectiveBom = new File(project.getBuildDir(),
|
|
||||||
"generated/effective-bom/" + project.getName() + "-effective-bom.xml");
|
|
||||||
generateEffectiveBom.args("--settings", "settings.xml", "help:effective-pom",
|
|
||||||
"-Doutput=" + effectiveBom);
|
|
||||||
generateEffectiveBom.dependsOn(syncBom);
|
|
||||||
generateEffectiveBom.getOutputs().file(effectiveBom);
|
|
||||||
generateEffectiveBom.doLast(new StripUnrepeatableOutputAction(effectiveBom));
|
|
||||||
project.getArtifacts().add(effectiveBomConfiguration.getName(), effectiveBom,
|
|
||||||
(artifact) -> artifact.builtBy(generateEffectiveBom));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createApiEnforcedConfiguration(Project project) {
|
private void createApiEnforcedConfiguration(Project project) {
|
||||||
|
@ -276,38 +223,4 @@ public class BomPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class StripUnrepeatableOutputAction implements Action<Task> {
|
|
||||||
|
|
||||||
private final File effectiveBom;
|
|
||||||
|
|
||||||
private StripUnrepeatableOutputAction(File xmlFile) {
|
|
||||||
this.effectiveBom = xmlFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Task task) {
|
|
||||||
try {
|
|
||||||
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(this.effectiveBom);
|
|
||||||
XPath xpath = XPathFactory.newInstance().newXPath();
|
|
||||||
NodeList comments = (NodeList) xpath.evaluate("//comment()", document, XPathConstants.NODESET);
|
|
||||||
for (int i = 0; i < comments.getLength(); i++) {
|
|
||||||
org.w3c.dom.Node comment = comments.item(i);
|
|
||||||
comment.getParentNode().removeChild(comment);
|
|
||||||
}
|
|
||||||
org.w3c.dom.Node build = (org.w3c.dom.Node) xpath.evaluate("/project/build", document,
|
|
||||||
XPathConstants.NODE);
|
|
||||||
build.getParentNode().removeChild(build);
|
|
||||||
org.w3c.dom.Node reporting = (org.w3c.dom.Node) xpath.evaluate("/project/reporting", document,
|
|
||||||
XPathConstants.NODE);
|
|
||||||
reporting.getParentNode().removeChild(reporting);
|
|
||||||
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document),
|
|
||||||
new StreamResult(this.effectiveBom));
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
throw new TaskExecutionException(task, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ plugins {
|
||||||
description = "Spring Boot Dependencies"
|
description = "Spring Boot Dependencies"
|
||||||
|
|
||||||
bom {
|
bom {
|
||||||
|
effectiveBomArtifact()
|
||||||
upgrade {
|
upgrade {
|
||||||
policy = "same-major-version"
|
policy = "same-major-version"
|
||||||
gitHub {
|
gitHub {
|
||||||
|
|
Loading…
Reference in New Issue