Require libraries to opt in to moving to snapshots

Closes gh-37190
This commit is contained in:
Andy Wilkinson 2023-09-05 10:40:31 +01:00
parent b858801a07
commit ced32f0751
6 changed files with 60 additions and 17 deletions

View File

@ -114,7 +114,8 @@ public class BomExtension {
LibraryHandler libraryHandler = objects.newInstance(LibraryHandler.class, (version != null) ? version : ""); LibraryHandler libraryHandler = objects.newInstance(LibraryHandler.class, (version != null) ? version : "");
action.execute(libraryHandler); action.execute(libraryHandler);
LibraryVersion libraryVersion = new LibraryVersion(DependencyVersion.parse(libraryHandler.version)); LibraryVersion libraryVersion = new LibraryVersion(DependencyVersion.parse(libraryHandler.version));
addLibrary(new Library(name, libraryVersion, libraryHandler.groups, libraryHandler.prohibitedVersions)); addLibrary(new Library(name, libraryVersion, libraryHandler.groups, libraryHandler.prohibitedVersions,
libraryHandler.considerSnapshots));
} }
public void effectiveBomArtifact() { public void effectiveBomArtifact() {
@ -214,6 +215,8 @@ public class BomExtension {
private final List<ProhibitedVersion> prohibitedVersions = new ArrayList<>(); private final List<ProhibitedVersion> prohibitedVersions = new ArrayList<>();
private boolean considerSnapshots = false;
private String version; private String version;
@Inject @Inject
@ -225,6 +228,10 @@ public class BomExtension {
this.version = version; this.version = version;
} }
public void considerSnapshots() {
this.considerSnapshots = true;
}
public void group(String id, Action<GroupHandler> action) { public void group(String id, Action<GroupHandler> action) {
GroupHandler groupHandler = new GroupHandler(id); GroupHandler groupHandler = new GroupHandler(id);
action.execute(groupHandler); action.execute(groupHandler);

View File

@ -42,6 +42,8 @@ public class Library {
private final List<ProhibitedVersion> prohibitedVersions; private final List<ProhibitedVersion> prohibitedVersions;
private final boolean considerSnapshots;
/** /**
* Create a new {@code Library} with the given {@code name}, {@code version}, and * Create a new {@code Library} with the given {@code name}, {@code version}, and
* {@code groups}. * {@code groups}.
@ -49,15 +51,17 @@ public class Library {
* @param version version of the library * @param version version of the library
* @param groups groups in the library * @param groups groups in the library
* @param prohibitedVersions version of the library that are prohibited * @param prohibitedVersions version of the library that are prohibited
* @param considerSnapshots whether to consider snapshots
*/ */
public Library(String name, LibraryVersion version, List<Group> groups, public Library(String name, LibraryVersion version, List<Group> groups, List<ProhibitedVersion> prohibitedVersions,
List<ProhibitedVersion> prohibitedVersions) { boolean considerSnapshots) {
this.name = name; this.name = name;
this.version = version; this.version = version;
this.groups = groups; this.groups = groups;
this.versionProperty = "Spring Boot".equals(name) ? null this.versionProperty = "Spring Boot".equals(name) ? null
: name.toLowerCase(Locale.ENGLISH).replace(' ', '-') + ".version"; : name.toLowerCase(Locale.ENGLISH).replace(' ', '-') + ".version";
this.prohibitedVersions = prohibitedVersions; this.prohibitedVersions = prohibitedVersions;
this.considerSnapshots = considerSnapshots;
} }
public String getName() { public String getName() {
@ -80,6 +84,10 @@ public class Library {
return this.prohibitedVersions; return this.prohibitedVersions;
} }
public boolean isConsiderSnapshots() {
return this.considerSnapshots;
}
/** /**
* A version or range of versions that are prohibited from being used in a bom. * A version or range of versions that are prohibited from being used in a bom.
*/ */

View File

@ -23,6 +23,7 @@ import javax.inject.Inject;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.springframework.boot.build.bom.BomExtension; import org.springframework.boot.build.bom.BomExtension;
import org.springframework.boot.build.bom.Library;
/** /**
* A {@link Task} to move to snapshot dependencies. * A {@link Task} to move to snapshot dependencies.
@ -57,4 +58,9 @@ public abstract class MoveToSnapshots extends UpgradeDependencies {
return snapshotVersion.substring(0, snapshotVersion.length() - "-SNAPSHOT".length()); return snapshotVersion.substring(0, snapshotVersion.length() - "-SNAPSHOT".length());
} }
@Override
protected boolean eligible(Library library) {
return library.isConsiderSnapshots() && super.eligible(library);
}
} }

View File

@ -212,25 +212,30 @@ public abstract class UpgradeDependencies extends DefaultTask {
new MultithreadedLibraryUpdateResolver(getThreads().get(), new MultithreadedLibraryUpdateResolver(getThreads().get(),
new StandardLibraryUpdateResolver(new MavenMetadataVersionResolver(getRepositoryUris().get()), new StandardLibraryUpdateResolver(new MavenMetadataVersionResolver(getRepositoryUris().get()),
this.bom.getUpgrade().getPolicy()))) this.bom.getUpgrade().getPolicy())))
.resolveUpgrades(matchingLibraries(getLibraries().getOrNull()), this.bom.getLibraries()); .resolveUpgrades(matchingLibraries(), this.bom.getLibraries());
return upgrades; return upgrades;
} }
private List<Library> matchingLibraries(String pattern) { private List<Library> matchingLibraries() {
if (pattern == null) {
return this.bom.getLibraries();
}
Predicate<String> libraryPredicate = Pattern.compile(pattern).asPredicate();
List<Library> matchingLibraries = this.bom.getLibraries() List<Library> matchingLibraries = this.bom.getLibraries()
.stream() .stream()
.filter((library) -> libraryPredicate.test(library.getName())) .filter(this::eligible)
.collect(Collectors.toList()); .collect(Collectors.toList());
if (matchingLibraries.isEmpty()) { if (matchingLibraries.isEmpty()) {
throw new InvalidUserDataException("No libraries matched '" + pattern + "'"); throw new InvalidUserDataException("No libraries to upgrade");
} }
return matchingLibraries; return matchingLibraries;
} }
protected boolean eligible(Library library) {
String pattern = getLibraries().getOrNull();
if (pattern == null) {
return true;
}
Predicate<String> libraryPredicate = Pattern.compile(pattern).asPredicate();
return libraryPredicate.test(library.getName());
}
protected abstract String issueTitle(Upgrade upgrade); protected abstract String issueTitle(Upgrade upgrade);
protected abstract String commitMessage(Upgrade upgrade, int issueNumber); protected abstract String commitMessage(Upgrade upgrade, int issueNumber);

View File

@ -52,9 +52,9 @@ class UpgradeApplicatorTests {
String originalContents = new String(Files.readAllBytes(bom.toPath()), StandardCharsets.UTF_8); String originalContents = new String(Files.readAllBytes(bom.toPath()), StandardCharsets.UTF_8);
File gradleProperties = new File(this.temp, "gradle.properties"); File gradleProperties = new File(this.temp, "gradle.properties");
FileCopyUtils.copy(new File("src/test/resources/gradle.properties"), gradleProperties); FileCopyUtils.copy(new File("src/test/resources/gradle.properties"), gradleProperties);
new UpgradeApplicator(bom.toPath(), gradleProperties.toPath()).apply( new UpgradeApplicator(bom.toPath(), gradleProperties.toPath()).apply(new Upgrade(
new Upgrade(new Library("ActiveMQ", new LibraryVersion(DependencyVersion.parse("5.15.11")), null, null), new Library("ActiveMQ", new LibraryVersion(DependencyVersion.parse("5.15.11")), null, null, false),
DependencyVersion.parse("5.16"))); DependencyVersion.parse("5.16")));
String bomContents = new String(Files.readAllBytes(bom.toPath()), StandardCharsets.UTF_8); String bomContents = new String(Files.readAllBytes(bom.toPath()), StandardCharsets.UTF_8);
assertThat(bomContents.length()).isEqualTo(originalContents.length() - 3); assertThat(bomContents.length()).isEqualTo(originalContents.length() - 3);
} }
@ -65,9 +65,9 @@ class UpgradeApplicatorTests {
FileCopyUtils.copy(new File("src/test/resources/bom.gradle"), bom); FileCopyUtils.copy(new File("src/test/resources/bom.gradle"), bom);
File gradleProperties = new File(this.temp, "gradle.properties"); File gradleProperties = new File(this.temp, "gradle.properties");
FileCopyUtils.copy(new File("src/test/resources/gradle.properties"), gradleProperties); FileCopyUtils.copy(new File("src/test/resources/gradle.properties"), gradleProperties);
new UpgradeApplicator(bom.toPath(), gradleProperties.toPath()) new UpgradeApplicator(bom.toPath(), gradleProperties.toPath()).apply(new Upgrade(
.apply(new Upgrade(new Library("Kotlin", new LibraryVersion(DependencyVersion.parse("1.3.70")), null, null), new Library("Kotlin", new LibraryVersion(DependencyVersion.parse("1.3.70")), null, null, false),
DependencyVersion.parse("1.4"))); DependencyVersion.parse("1.4")));
Properties properties = new Properties(); Properties properties = new Properties();
try (InputStream in = new FileInputStream(gradleProperties)) { try (InputStream in = new FileInputStream(gradleProperties)) {
properties.load(in); properties.load(in);

View File

@ -1328,6 +1328,7 @@ bom {
} }
} }
library("Micrometer", "1.9.14") { library("Micrometer", "1.9.14") {
considerSnapshots()
group("io.micrometer") { group("io.micrometer") {
modules = [ modules = [
"micrometer-registry-stackdriver" { "micrometer-registry-stackdriver" {
@ -1459,6 +1460,7 @@ bom {
} }
} }
library("R2DBC Bom", "Borca-SR2") { library("R2DBC Bom", "Borca-SR2") {
considerSnapshots()
group("io.r2dbc") { group("io.r2dbc") {
imports = [ imports = [
"r2dbc-bom" "r2dbc-bom"
@ -1487,6 +1489,7 @@ bom {
} }
} }
library("Reactor Bom", "2020.0.35") { library("Reactor Bom", "2020.0.35") {
considerSnapshots()
group("io.projectreactor") { group("io.projectreactor") {
imports = [ imports = [
"reactor-bom" "reactor-bom"
@ -1715,6 +1718,7 @@ bom {
} }
} }
library("Spring AMQP", "2.4.15") { library("Spring AMQP", "2.4.15") {
considerSnapshots()
prohibit { prohibit {
versionRange "[3.0.0-M1,)" versionRange "[3.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1730,6 +1734,7 @@ bom {
} }
} }
library("Spring Batch", "4.3.9") { library("Spring Batch", "4.3.9") {
considerSnapshots()
prohibit { prohibit {
versionRange "[5.0.0-M1,)" versionRange "[5.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1744,6 +1749,7 @@ bom {
} }
} }
library("Spring Data Bom", "2021.2.15") { library("Spring Data Bom", "2021.2.15") {
considerSnapshots()
prohibit { prohibit {
versionRange "[2022.0.0-M1,)" versionRange "[2022.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1755,6 +1761,7 @@ bom {
} }
} }
library("Spring Framework", "${springFrameworkVersion}") { library("Spring Framework", "${springFrameworkVersion}") {
considerSnapshots()
prohibit { prohibit {
versionRange "[6.0.0-M1,)" versionRange "[6.0.0-M1,)"
because "we upgrade in Spring Boot 3.x" because "we upgrade in Spring Boot 3.x"
@ -1766,6 +1773,7 @@ bom {
} }
} }
library("Spring GraphQL", "1.0.4") { library("Spring GraphQL", "1.0.4") {
considerSnapshots()
group("org.springframework.graphql") { group("org.springframework.graphql") {
modules = [ modules = [
"spring-graphql", "spring-graphql",
@ -1774,6 +1782,7 @@ bom {
} }
} }
library("Spring HATEOAS", "1.5.5") { library("Spring HATEOAS", "1.5.5") {
considerSnapshots()
prohibit { prohibit {
versionRange "[2.0.0-M1,)" versionRange "[2.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1785,6 +1794,7 @@ bom {
} }
} }
library("Spring Integration", "5.5.18") { library("Spring Integration", "5.5.18") {
considerSnapshots()
prohibit { prohibit {
versionRange "[6.0.0-M1,)" versionRange "[6.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1796,6 +1806,7 @@ bom {
} }
} }
library("Spring Kafka", "2.8.11") { library("Spring Kafka", "2.8.11") {
considerSnapshots()
group("org.springframework.kafka") { group("org.springframework.kafka") {
modules = [ modules = [
"spring-kafka", "spring-kafka",
@ -1804,6 +1815,7 @@ bom {
} }
} }
library("Spring LDAP", "2.4.1") { library("Spring LDAP", "2.4.1") {
considerSnapshots()
prohibit { prohibit {
versionRange "[3.0.0-M1,)" versionRange "[3.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1819,6 +1831,7 @@ bom {
} }
} }
library("Spring RESTDocs", "2.0.7.RELEASE") { library("Spring RESTDocs", "2.0.7.RELEASE") {
considerSnapshots()
group("org.springframework.restdocs") { group("org.springframework.restdocs") {
modules = [ modules = [
"spring-restdocs-asciidoctor", "spring-restdocs-asciidoctor",
@ -1830,6 +1843,7 @@ bom {
} }
} }
library("Spring Retry", "1.3.4") { library("Spring Retry", "1.3.4") {
considerSnapshots()
group("org.springframework.retry") { group("org.springframework.retry") {
modules = [ modules = [
"spring-retry" "spring-retry"
@ -1837,6 +1851,7 @@ bom {
} }
} }
library("Spring Security", "5.7.10") { library("Spring Security", "5.7.10") {
considerSnapshots()
prohibit { prohibit {
versionRange "[6.0.0-M1,)" versionRange "[6.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1848,6 +1863,7 @@ bom {
} }
} }
library("Spring Session Bom", "2021.2.2") { library("Spring Session Bom", "2021.2.2") {
considerSnapshots()
prohibit { prohibit {
versionRange "[2022.0.0-M1,)" versionRange "[2022.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"
@ -1859,6 +1875,7 @@ bom {
} }
} }
library("Spring WS", "3.1.6") { library("Spring WS", "3.1.6") {
considerSnapshots()
prohibit { prohibit {
versionRange "[4.0.0-M1,)" versionRange "[4.0.0-M1,)"
because "it uses Spring Framework 6" because "it uses Spring Framework 6"