mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Merge branch '3.1.x'
Closes gh-37225
This commit is contained in:
commit
96368a4e61
@ -39,9 +39,11 @@ dependencies {
|
|||||||
implementation("org.springframework:spring-core")
|
implementation("org.springframework:spring-core")
|
||||||
implementation("org.springframework:spring-web")
|
implementation("org.springframework:spring-web")
|
||||||
|
|
||||||
testImplementation("org.assertj:assertj-core:3.11.1")
|
|
||||||
testImplementation("org.apache.logging.log4j:log4j-core:2.17.1")
|
testImplementation("org.apache.logging.log4j:log4j-core:2.17.1")
|
||||||
|
testImplementation("org.assertj:assertj-core:3.11.1")
|
||||||
|
testImplementation("org.hamcrest:hamcrest:2.2")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.6.0")
|
testImplementation("org.junit.jupiter:junit-jupiter:5.6.0")
|
||||||
|
testImplementation("org.springframework:spring-test")
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
}
|
}
|
||||||
|
@ -113,8 +113,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, libraryHandler.calendarName, libraryVersion, libraryHandler.groups,
|
||||||
libraryHandler.considerSnapshots));
|
libraryHandler.prohibitedVersions, libraryHandler.considerSnapshots));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void effectiveBomArtifact() {
|
public void effectiveBomArtifact() {
|
||||||
@ -218,6 +218,8 @@ public class BomExtension {
|
|||||||
|
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
|
private String calendarName;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public LibraryHandler(String version) {
|
public LibraryHandler(String version) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@ -231,6 +233,10 @@ public class BomExtension {
|
|||||||
this.considerSnapshots = true;
|
this.considerSnapshots = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCalendarName(String calendarName) {
|
||||||
|
this.calendarName = calendarName;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -34,6 +34,8 @@ public class Library {
|
|||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
private final String calendarName;
|
||||||
|
|
||||||
private final LibraryVersion version;
|
private final LibraryVersion version;
|
||||||
|
|
||||||
private final List<Group> groups;
|
private final List<Group> groups;
|
||||||
@ -48,14 +50,17 @@ public class Library {
|
|||||||
* 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}.
|
||||||
* @param name name of the library
|
* @param name name of the library
|
||||||
|
* @param calendarName name of the library as it appears in the Spring Calendar. May
|
||||||
|
* be {@code null} in which case the {@code name} is used.
|
||||||
* @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
|
* @param considerSnapshots whether to consider snapshots
|
||||||
*/
|
*/
|
||||||
public Library(String name, LibraryVersion version, List<Group> groups, List<ProhibitedVersion> prohibitedVersions,
|
public Library(String name, String calendarName, LibraryVersion version, List<Group> groups,
|
||||||
boolean considerSnapshots) {
|
List<ProhibitedVersion> prohibitedVersions, boolean considerSnapshots) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.calendarName = (calendarName != null) ? calendarName : 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
|
||||||
@ -68,6 +73,10 @@ public class Library {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCalendarName() {
|
||||||
|
return this.calendarName;
|
||||||
|
}
|
||||||
|
|
||||||
public LibraryVersion getVersion() {
|
public LibraryVersion getVersion() {
|
||||||
return this.version;
|
return this.version;
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,23 @@
|
|||||||
package org.springframework.boot.build.bom.bomr;
|
package org.springframework.boot.build.bom.bomr;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.gradle.api.Task;
|
import org.gradle.api.Task;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.springframework.boot.build.bom.BomExtension;
|
import org.springframework.boot.build.bom.BomExtension;
|
||||||
import org.springframework.boot.build.bom.Library;
|
import org.springframework.boot.build.bom.Library;
|
||||||
|
import org.springframework.boot.build.bom.bomr.ReleaseSchedule.Release;
|
||||||
|
import org.springframework.boot.build.bom.bomr.github.Milestone;
|
||||||
|
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Task} to move to snapshot dependencies.
|
* A {@link Task} to move to snapshot dependencies.
|
||||||
@ -32,6 +42,8 @@ import org.springframework.boot.build.bom.Library;
|
|||||||
*/
|
*/
|
||||||
public abstract class MoveToSnapshots extends UpgradeDependencies {
|
public abstract class MoveToSnapshots extends UpgradeDependencies {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(MoveToSnapshots.class);
|
||||||
|
|
||||||
private final URI REPOSITORY_URI = URI.create("https://repo.spring.io/snapshot/");
|
private final URI REPOSITORY_URI = URI.create("https://repo.spring.io/snapshot/");
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -40,6 +52,12 @@ public abstract class MoveToSnapshots extends UpgradeDependencies {
|
|||||||
getRepositoryUris().add(this.REPOSITORY_URI);
|
getRepositoryUris().add(this.REPOSITORY_URI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@TaskAction
|
||||||
|
void upgradeDependencies() {
|
||||||
|
super.upgradeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String issueTitle(Upgrade upgrade) {
|
protected String issueTitle(Upgrade upgrade) {
|
||||||
String snapshotVersion = upgrade.getVersion().toString();
|
String snapshotVersion = upgrade.getVersion().toString();
|
||||||
@ -63,4 +81,28 @@ public abstract class MoveToSnapshots extends UpgradeDependencies {
|
|||||||
return library.isConsiderSnapshots() && super.eligible(library);
|
return library.isConsiderSnapshots() && super.eligible(library);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<BiPredicate<Library, DependencyVersion>> determineUpdatePredicates(Milestone milestone) {
|
||||||
|
ReleaseSchedule releaseSchedule = new ReleaseSchedule();
|
||||||
|
Map<String, List<Release>> releases = releaseSchedule.releasesBetween(OffsetDateTime.now(),
|
||||||
|
milestone.getDueOn());
|
||||||
|
List<BiPredicate<Library, DependencyVersion>> predicates = super.determineUpdatePredicates(milestone);
|
||||||
|
predicates.add((library, candidate) -> {
|
||||||
|
List<Release> releasesForLibrary = releases.get(library.getCalendarName());
|
||||||
|
if (releasesForLibrary != null) {
|
||||||
|
for (Release release : releasesForLibrary) {
|
||||||
|
if (candidate.isSnapshotFor(release.getVersion())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log.isInfoEnabled()) {
|
||||||
|
log.info("Ignoring " + candidate + ". No release of " + library.getName() + " scheduled before "
|
||||||
|
+ milestone.getDueOn());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return predicates;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.bom.bomr;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
|
import org.springframework.web.client.RestOperations;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release schedule for Spring projects, retrieved from
|
||||||
|
* <a href="https://calendar.spring.io">https://calendar.spring.io</a>.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
class ReleaseSchedule {
|
||||||
|
|
||||||
|
private static final Pattern LIBRARY_AND_VERSION = Pattern.compile("([A-Za-z0-9 ]+) ([0-9A-Za-z.-]+)");
|
||||||
|
|
||||||
|
private final RestOperations rest;
|
||||||
|
|
||||||
|
ReleaseSchedule() {
|
||||||
|
this(new RestTemplate());
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseSchedule(RestOperations rest) {
|
||||||
|
this.rest = rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
Map<String, List<Release>> releasesBetween(OffsetDateTime start, OffsetDateTime end) {
|
||||||
|
ResponseEntity<List> response = this.rest
|
||||||
|
.getForEntity("https://calendar.spring.io/releases?start=" + start + "&end=" + end, List.class);
|
||||||
|
List<Map<String, String>> body = response.getBody();
|
||||||
|
Map<String, List<Release>> releasesByLibrary = new LinkedCaseInsensitiveMap<>();
|
||||||
|
body.stream()
|
||||||
|
.map(this::asRelease)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.forEach((release) -> releasesByLibrary.computeIfAbsent(release.getLibraryName(), (l) -> new ArrayList<>())
|
||||||
|
.add(release));
|
||||||
|
return releasesByLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Release asRelease(Map<String, String> entry) {
|
||||||
|
LocalDate due = LocalDate.parse(entry.get("start"));
|
||||||
|
String title = entry.get("title");
|
||||||
|
Matcher matcher = LIBRARY_AND_VERSION.matcher(title);
|
||||||
|
if (!matcher.matches()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String library = matcher.group(1);
|
||||||
|
String version = matcher.group(2);
|
||||||
|
return new Release(library, DependencyVersion.parse(version), due);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Release {
|
||||||
|
|
||||||
|
private final String libraryName;
|
||||||
|
|
||||||
|
private final DependencyVersion version;
|
||||||
|
|
||||||
|
private final LocalDate dueOn;
|
||||||
|
|
||||||
|
Release(String libraryName, DependencyVersion version, LocalDate dueOn) {
|
||||||
|
this.libraryName = libraryName;
|
||||||
|
this.version = version;
|
||||||
|
this.dueOn = dueOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getLibraryName() {
|
||||||
|
return this.libraryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
DependencyVersion getVersion() {
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate getDueOn() {
|
||||||
|
return this.dueOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,16 +23,14 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
|
||||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.springframework.boot.build.bom.Library;
|
import org.springframework.boot.build.bom.Library;
|
||||||
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.UpgradePolicy;
|
|
||||||
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,15 +44,21 @@ class StandardLibraryUpdateResolver implements LibraryUpdateResolver {
|
|||||||
|
|
||||||
private final VersionResolver versionResolver;
|
private final VersionResolver versionResolver;
|
||||||
|
|
||||||
private final UpgradePolicy upgradePolicy;
|
private final BiPredicate<Library, DependencyVersion> predicate;
|
||||||
|
|
||||||
private final boolean movingToSnapshots;
|
StandardLibraryUpdateResolver(VersionResolver versionResolver,
|
||||||
|
List<BiPredicate<Library, DependencyVersion>> predicates) {
|
||||||
StandardLibraryUpdateResolver(VersionResolver versionResolver, UpgradePolicy upgradePolicy,
|
|
||||||
boolean movingToSnapshots) {
|
|
||||||
this.versionResolver = versionResolver;
|
this.versionResolver = versionResolver;
|
||||||
this.upgradePolicy = upgradePolicy;
|
BiPredicate<Library, DependencyVersion> predicate = null;
|
||||||
this.movingToSnapshots = movingToSnapshots;
|
for (BiPredicate<Library, DependencyVersion> p : predicates) {
|
||||||
|
if (predicate == null) {
|
||||||
|
predicate = p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
predicate = predicate.and(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.predicate = predicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -85,57 +89,29 @@ class StandardLibraryUpdateResolver implements LibraryUpdateResolver {
|
|||||||
|
|
||||||
private List<VersionOption> determineResolvedVersionOptions(Library library) {
|
private List<VersionOption> determineResolvedVersionOptions(Library library) {
|
||||||
Map<String, SortedSet<DependencyVersion>> moduleVersions = new LinkedHashMap<>();
|
Map<String, SortedSet<DependencyVersion>> moduleVersions = new LinkedHashMap<>();
|
||||||
DependencyVersion libraryVersion = library.getVersion().getVersion();
|
|
||||||
for (Group group : library.getGroups()) {
|
for (Group group : library.getGroups()) {
|
||||||
for (Module module : group.getModules()) {
|
for (Module module : group.getModules()) {
|
||||||
moduleVersions.put(group.getId() + ":" + module.getName(),
|
moduleVersions.put(group.getId() + ":" + module.getName(),
|
||||||
getLaterVersionsForModule(group.getId(), module.getName(), libraryVersion));
|
getLaterVersionsForModule(group.getId(), module.getName(), library));
|
||||||
}
|
}
|
||||||
for (String bom : group.getBoms()) {
|
for (String bom : group.getBoms()) {
|
||||||
moduleVersions.put(group.getId() + ":" + bom,
|
moduleVersions.put(group.getId() + ":" + bom, getLaterVersionsForModule(group.getId(), bom, library));
|
||||||
getLaterVersionsForModule(group.getId(), bom, libraryVersion));
|
|
||||||
}
|
}
|
||||||
for (String plugin : group.getPlugins()) {
|
for (String plugin : group.getPlugins()) {
|
||||||
moduleVersions.put(group.getId() + ":" + plugin,
|
moduleVersions.put(group.getId() + ":" + plugin,
|
||||||
getLaterVersionsForModule(group.getId(), plugin, libraryVersion));
|
getLaterVersionsForModule(group.getId(), plugin, library));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return moduleVersions.values()
|
return moduleVersions.values()
|
||||||
.stream()
|
.stream()
|
||||||
.flatMap(SortedSet::stream)
|
.flatMap(SortedSet::stream)
|
||||||
.distinct()
|
.distinct()
|
||||||
.filter((dependencyVersion) -> isPermitted(dependencyVersion, library.getProhibitedVersions()))
|
.filter((dependencyVersion) -> this.predicate.test(library, dependencyVersion))
|
||||||
.map((version) -> (VersionOption) new VersionOption.ResolvedVersionOption(version,
|
.map((version) -> (VersionOption) new VersionOption.ResolvedVersionOption(version,
|
||||||
getMissingModules(moduleVersions, version)))
|
getMissingModules(moduleVersions, version)))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPermitted(DependencyVersion dependencyVersion, List<ProhibitedVersion> prohibitedVersions) {
|
|
||||||
for (ProhibitedVersion prohibitedVersion : prohibitedVersions) {
|
|
||||||
String dependencyVersionToString = dependencyVersion.toString();
|
|
||||||
if (prohibitedVersion.getRange() != null && prohibitedVersion.getRange()
|
|
||||||
.containsVersion(new DefaultArtifactVersion(dependencyVersionToString))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (String startsWith : prohibitedVersion.getStartsWith()) {
|
|
||||||
if (dependencyVersionToString.startsWith(startsWith)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String endsWith : prohibitedVersion.getEndsWith()) {
|
|
||||||
if (dependencyVersionToString.endsWith(endsWith)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String contains : prohibitedVersion.getContains()) {
|
|
||||||
if (dependencyVersionToString.contains(contains)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getMissingModules(Map<String, SortedSet<DependencyVersion>> moduleVersions,
|
private List<String> getMissingModules(Map<String, SortedSet<DependencyVersion>> moduleVersions,
|
||||||
DependencyVersion version) {
|
DependencyVersion version) {
|
||||||
List<String> missingModules = new ArrayList<>();
|
List<String> missingModules = new ArrayList<>();
|
||||||
@ -147,12 +123,8 @@ class StandardLibraryUpdateResolver implements LibraryUpdateResolver {
|
|||||||
return missingModules;
|
return missingModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SortedSet<DependencyVersion> getLaterVersionsForModule(String groupId, String artifactId,
|
private SortedSet<DependencyVersion> getLaterVersionsForModule(String groupId, String artifactId, Library library) {
|
||||||
DependencyVersion currentVersion) {
|
return this.versionResolver.resolveVersions(groupId, artifactId);
|
||||||
SortedSet<DependencyVersion> versions = this.versionResolver.resolveVersions(groupId, artifactId);
|
|
||||||
versions.removeIf((candidate) -> !this.upgradePolicy.test(candidate, currentVersion));
|
|
||||||
versions.removeIf((candidate) -> !currentVersion.isUpgrade(candidate, this.movingToSnapshots));
|
|
||||||
return versions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,13 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
import org.gradle.api.DefaultTask;
|
import org.gradle.api.DefaultTask;
|
||||||
import org.gradle.api.InvalidUserDataException;
|
import org.gradle.api.InvalidUserDataException;
|
||||||
import org.gradle.api.internal.tasks.userinput.UserInputHandler;
|
import org.gradle.api.internal.tasks.userinput.UserInputHandler;
|
||||||
@ -45,10 +47,12 @@ import org.gradle.api.tasks.options.Option;
|
|||||||
|
|
||||||
import org.springframework.boot.build.bom.BomExtension;
|
import org.springframework.boot.build.bom.BomExtension;
|
||||||
import org.springframework.boot.build.bom.Library;
|
import org.springframework.boot.build.bom.Library;
|
||||||
|
import org.springframework.boot.build.bom.Library.ProhibitedVersion;
|
||||||
import org.springframework.boot.build.bom.bomr.github.GitHub;
|
import org.springframework.boot.build.bom.bomr.github.GitHub;
|
||||||
import org.springframework.boot.build.bom.bomr.github.GitHubRepository;
|
import org.springframework.boot.build.bom.bomr.github.GitHubRepository;
|
||||||
import org.springframework.boot.build.bom.bomr.github.Issue;
|
import org.springframework.boot.build.bom.bomr.github.Issue;
|
||||||
import org.springframework.boot.build.bom.bomr.github.Milestone;
|
import org.springframework.boot.build.bom.bomr.github.Milestone;
|
||||||
|
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,8 +74,8 @@ public abstract class UpgradeDependencies extends DefaultTask {
|
|||||||
|
|
||||||
protected UpgradeDependencies(BomExtension bom, boolean movingToSnapshots) {
|
protected UpgradeDependencies(BomExtension bom, boolean movingToSnapshots) {
|
||||||
this.bom = bom;
|
this.bom = bom;
|
||||||
this.movingToSnapshots = movingToSnapshots;
|
|
||||||
getThreads().convention(2);
|
getThreads().convention(2);
|
||||||
|
this.movingToSnapshots = movingToSnapshots;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
@ -97,7 +101,7 @@ public abstract class UpgradeDependencies extends DefaultTask {
|
|||||||
this.bom.getUpgrade().getGitHub().getRepository());
|
this.bom.getUpgrade().getGitHub().getRepository());
|
||||||
List<String> issueLabels = verifyLabels(repository);
|
List<String> issueLabels = verifyLabels(repository);
|
||||||
Milestone milestone = determineMilestone(repository);
|
Milestone milestone = determineMilestone(repository);
|
||||||
List<Upgrade> upgrades = resolveUpgrades();
|
List<Upgrade> upgrades = resolveUpgrades(milestone);
|
||||||
applyUpgrades(repository, issueLabels, milestone, upgrades);
|
applyUpgrades(repository, issueLabels, milestone, upgrades);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,15 +217,52 @@ public abstract class UpgradeDependencies extends DefaultTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private List<Upgrade> resolveUpgrades() {
|
private List<Upgrade> resolveUpgrades(Milestone milestone) {
|
||||||
List<Upgrade> upgrades = new InteractiveUpgradeResolver(getServices().get(UserInputHandler.class),
|
List<Upgrade> upgrades = new InteractiveUpgradeResolver(getServices().get(UserInputHandler.class),
|
||||||
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.movingToSnapshots)))
|
determineUpdatePredicates(milestone))))
|
||||||
.resolveUpgrades(matchingLibraries(), this.bom.getLibraries());
|
.resolveUpgrades(matchingLibraries(), this.bom.getLibraries());
|
||||||
return upgrades;
|
return upgrades;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<BiPredicate<Library, DependencyVersion>> determineUpdatePredicates(Milestone milestone) {
|
||||||
|
BiPredicate<Library, DependencyVersion> compilesWithUpgradePolicy = (library,
|
||||||
|
candidate) -> this.bom.getUpgrade().getPolicy().test(candidate, library.getVersion().getVersion());
|
||||||
|
BiPredicate<Library, DependencyVersion> isAnUpgrade = (library,
|
||||||
|
candidate) -> library.getVersion().getVersion().isUpgrade(candidate, this.movingToSnapshots);
|
||||||
|
BiPredicate<Library, DependencyVersion> isPermitted = (library, candidate) -> {
|
||||||
|
for (ProhibitedVersion prohibitedVersion : library.getProhibitedVersions()) {
|
||||||
|
String candidateString = candidate.toString();
|
||||||
|
if (prohibitedVersion.getRange() != null
|
||||||
|
&& prohibitedVersion.getRange().containsVersion(new DefaultArtifactVersion(candidateString))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (String startsWith : prohibitedVersion.getStartsWith()) {
|
||||||
|
if (candidateString.startsWith(startsWith)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String endsWith : prohibitedVersion.getEndsWith()) {
|
||||||
|
if (candidateString.endsWith(endsWith)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String contains : prohibitedVersion.getContains()) {
|
||||||
|
if (candidateString.contains(contains)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
List<BiPredicate<Library, DependencyVersion>> updatePredicates = new ArrayList<>();
|
||||||
|
updatePredicates.add(compilesWithUpgradePolicy);
|
||||||
|
updatePredicates.add(isAnUpgrade);
|
||||||
|
updatePredicates.add(isPermitted);
|
||||||
|
return updatePredicates;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Library> matchingLibraries() {
|
private List<Library> matchingLibraries() {
|
||||||
List<Library> matchingLibraries = this.bom.getLibraries().stream().filter(this::eligible).toList();
|
List<Library> matchingLibraries = this.bom.getLibraries().stream().filter(this::eligible).toList();
|
||||||
if (matchingLibraries.isEmpty()) {
|
if (matchingLibraries.isEmpty()) {
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.springframework.boot.build.bom.bomr.github;
|
package org.springframework.boot.build.bom.bomr.github;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A milestone in a {@link GitHubRepository GitHub repository}.
|
* A milestone in a {@link GitHubRepository GitHub repository}.
|
||||||
*
|
*
|
||||||
@ -27,9 +29,12 @@ public class Milestone {
|
|||||||
|
|
||||||
private final int number;
|
private final int number;
|
||||||
|
|
||||||
Milestone(String name, int number) {
|
private final OffsetDateTime dueOn;
|
||||||
|
|
||||||
|
Milestone(String name, int number, OffsetDateTime dueOn) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.number = number;
|
this.number = number;
|
||||||
|
this.dueOn = dueOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,6 +53,10 @@ public class Milestone {
|
|||||||
return this.number;
|
return this.number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getDueOn() {
|
||||||
|
return this.dueOn;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.name + " (" + this.number + ")";
|
return this.name + " (" + this.number + ")";
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.springframework.boot.build.bom.bomr.github;
|
package org.springframework.boot.build.bom.bomr.github;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -75,8 +76,9 @@ final class StandardGitHubRepository implements GitHubRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Milestone> getMilestones() {
|
public List<Milestone> getMilestones() {
|
||||||
return get("milestones?per_page=100",
|
return get("milestones?per_page=100", (milestone) -> new Milestone((String) milestone.get("title"),
|
||||||
(milestone) -> new Milestone((String) milestone.get("title"), (Integer) milestone.get("number")));
|
(Integer) milestone.get("number"),
|
||||||
|
(milestone.get("due_on") != null) ? OffsetDateTime.parse((String) milestone.get("due_on")) : null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,24 +88,40 @@ class ArtifactVersionDependencyVersion extends AbstractDependencyVersion {
|
|||||||
if (this.artifactVersion.equals(other)) {
|
if (this.artifactVersion.equals(other)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.artifactVersion.getMajorVersion() == other.getMajorVersion()
|
if (sameMajorMinorIncremental(other)) {
|
||||||
&& this.artifactVersion.getMinorVersion() == other.getMinorVersion()
|
|
||||||
&& this.artifactVersion.getIncrementalVersion() == other.getIncrementalVersion()) {
|
|
||||||
if (!StringUtils.hasLength(this.artifactVersion.getQualifier())
|
if (!StringUtils.hasLength(this.artifactVersion.getQualifier())
|
||||||
|| "RELEASE".equals(this.artifactVersion.getQualifier())) {
|
|| "RELEASE".equals(this.artifactVersion.getQualifier())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ("SNAPSHOT".equals(this.artifactVersion.getQualifier())
|
if (isSnapshot()) {
|
||||||
|| "BUILD".equals(this.artifactVersion.getQualifier())) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if ("SNAPSHOT".equals(other.getQualifier()) || "BUILD".equals(other.getQualifier())) {
|
else if (((ArtifactVersionDependencyVersion) candidate).isSnapshot()) {
|
||||||
return movingToSnapshots;
|
return movingToSnapshots;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.isUpgrade(candidate, movingToSnapshots);
|
return super.isUpgrade(candidate, movingToSnapshots);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean sameMajorMinorIncremental(ArtifactVersion other) {
|
||||||
|
return this.artifactVersion.getMajorVersion() == other.getMajorVersion()
|
||||||
|
&& this.artifactVersion.getMinorVersion() == other.getMinorVersion()
|
||||||
|
&& this.artifactVersion.getIncrementalVersion() == other.getIncrementalVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSnapshot() {
|
||||||
|
return "SNAPSHOT".equals(this.artifactVersion.getQualifier())
|
||||||
|
|| "BUILD".equals(this.artifactVersion.getQualifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSnapshotFor(DependencyVersion candidate) {
|
||||||
|
if (!isSnapshot() || !(candidate instanceof ArtifactVersionDependencyVersion)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return sameMajorMinorIncremental(((ArtifactVersionDependencyVersion) candidate).artifactVersion);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(DependencyVersion other) {
|
public int compareTo(DependencyVersion other) {
|
||||||
if (other instanceof ArtifactVersionDependencyVersion otherArtifactDependencyVersion) {
|
if (other instanceof ArtifactVersionDependencyVersion otherArtifactDependencyVersion) {
|
||||||
|
@ -46,13 +46,21 @@ public interface DependencyVersion extends Comparable<DependencyVersion> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given {@code candidate} is an upgrade of this version.
|
* Returns whether the given {@code candidate} is an upgrade of this version.
|
||||||
* @param candidate the version the consider
|
* @param candidate the version to consider
|
||||||
* @param movingToSnapshots whether the upgrade is to be considered as part of moving
|
* @param movingToSnapshots whether the upgrade is to be considered as part of moving
|
||||||
* to snaphots
|
* to snaphots
|
||||||
* @return {@code true} if the candidate is an upgrade, otherwise false
|
* @return {@code true} if the candidate is an upgrade, otherwise false
|
||||||
*/
|
*/
|
||||||
boolean isUpgrade(DependencyVersion candidate, boolean movingToSnapshots);
|
boolean isUpgrade(DependencyVersion candidate, boolean movingToSnapshots);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this version is a snapshot for the given {@code candidate}.
|
||||||
|
* @param candidate the version to consider
|
||||||
|
* @return {@code true} if this version is a snapshot for the candidate, otherwise
|
||||||
|
* false
|
||||||
|
*/
|
||||||
|
boolean isSnapshotFor(DependencyVersion candidate);
|
||||||
|
|
||||||
static DependencyVersion parse(String version) {
|
static DependencyVersion parse(String version) {
|
||||||
List<Function<String, DependencyVersion>> parsers = Arrays.asList(CalendarVersionDependencyVersion::parse,
|
List<Function<String, DependencyVersion>> parsers = Arrays.asList(CalendarVersionDependencyVersion::parse,
|
||||||
ArtifactVersionDependencyVersion::parse, ReleaseTrainDependencyVersion::parse,
|
ArtifactVersionDependencyVersion::parse, ReleaseTrainDependencyVersion::parse,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -72,8 +72,7 @@ final class ReleaseTrainDependencyVersion implements DependencyVersion {
|
|||||||
if (comparison != 0) {
|
if (comparison != 0) {
|
||||||
return comparison < 0;
|
return comparison < 0;
|
||||||
}
|
}
|
||||||
if (movingToSnapshots && !"BUILD-SNAPSHOT".equals(this.type)
|
if (movingToSnapshots && !isSnapshot() && candidateReleaseTrain.isSnapshot()) {
|
||||||
&& "BUILD-SNAPSHOT".equals(candidateReleaseTrain.type)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
comparison = this.type.compareTo(candidateReleaseTrain.type);
|
comparison = this.type.compareTo(candidateReleaseTrain.type);
|
||||||
@ -83,6 +82,19 @@ final class ReleaseTrainDependencyVersion implements DependencyVersion {
|
|||||||
return Integer.compare(this.version, candidateReleaseTrain.version) < 0;
|
return Integer.compare(this.version, candidateReleaseTrain.version) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSnapshot() {
|
||||||
|
return "BUILD-SNAPSHOT".equals(this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSnapshotFor(DependencyVersion candidate) {
|
||||||
|
if (!isSnapshot() || !(candidate instanceof ReleaseTrainDependencyVersion)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ReleaseTrainDependencyVersion candidateReleaseTrain = (ReleaseTrainDependencyVersion) candidate;
|
||||||
|
return this.releaseTrain.equals(candidateReleaseTrain.releaseTrain);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSameMajor(DependencyVersion other) {
|
public boolean isSameMajor(DependencyVersion other) {
|
||||||
return isSameReleaseTrain(other);
|
return isSameReleaseTrain(other);
|
||||||
|
@ -48,6 +48,11 @@ final class UnstructuredDependencyVersion extends AbstractDependencyVersion impl
|
|||||||
return this.version;
|
return this.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSnapshotFor(DependencyVersion candidate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static UnstructuredDependencyVersion parse(String version) {
|
static UnstructuredDependencyVersion parse(String version) {
|
||||||
return new UnstructuredDependencyVersion(version);
|
return new UnstructuredDependencyVersion(version);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.bom.bomr;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.build.bom.bomr.ReleaseSchedule.Release;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.web.client.MockRestServiceServer;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||||
|
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ReleaseSchedule}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class ReleaseScheduleTests {
|
||||||
|
|
||||||
|
private final RestTemplate rest = new RestTemplate();
|
||||||
|
|
||||||
|
private final ReleaseSchedule releaseSchedule = new ReleaseSchedule(this.rest);
|
||||||
|
|
||||||
|
private final MockRestServiceServer server = MockRestServiceServer.bindTo(this.rest).build();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void releasesBetween() {
|
||||||
|
this.server
|
||||||
|
.expect(requestTo("https://calendar.spring.io/releases?start=2023-09-01T00:00Z&end=2023-09-21T23:59Z"))
|
||||||
|
.andRespond(withSuccess(new ClassPathResource("releases.json"), MediaType.APPLICATION_JSON));
|
||||||
|
Map<String, List<Release>> releases = this.releaseSchedule
|
||||||
|
.releasesBetween(OffsetDateTime.parse("2023-09-01T00:00Z"), OffsetDateTime.parse("2023-09-21T23:59Z"));
|
||||||
|
assertThat(releases).hasSize(23);
|
||||||
|
assertThat(releases.get("Spring Framework")).hasSize(3);
|
||||||
|
assertThat(releases.get("Spring Boot")).hasSize(4);
|
||||||
|
assertThat(releases.get("Spring Modulith")).hasSize(1);
|
||||||
|
assertThat(releases.get("spring graphql")).hasSize(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -51,9 +51,9 @@ class UpgradeApplicatorTests {
|
|||||||
String originalContents = Files.readString(bom.toPath());
|
String originalContents = Files.readString(bom.toPath());
|
||||||
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 Upgrade(
|
new UpgradeApplicator(bom.toPath(), gradleProperties.toPath())
|
||||||
new Library("ActiveMQ", new LibraryVersion(DependencyVersion.parse("5.15.11")), null, null, false),
|
.apply(new Upgrade(new Library("ActiveMQ", null, new LibraryVersion(DependencyVersion.parse("5.15.11")),
|
||||||
DependencyVersion.parse("5.16")));
|
null, null, false), DependencyVersion.parse("5.16")));
|
||||||
String bomContents = Files.readString(bom.toPath());
|
String bomContents = Files.readString(bom.toPath());
|
||||||
assertThat(bomContents).hasSize(originalContents.length() - 3);
|
assertThat(bomContents).hasSize(originalContents.length() - 3);
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ class UpgradeApplicatorTests {
|
|||||||
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 Upgrade(
|
new UpgradeApplicator(bom.toPath(), gradleProperties.toPath()).apply(new Upgrade(
|
||||||
new Library("Kotlin", new LibraryVersion(DependencyVersion.parse("1.3.70")), null, null, false),
|
new Library("Kotlin", null, 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)) {
|
||||||
|
@ -62,6 +62,71 @@ class ArtifactVersionDependencyVersionTests {
|
|||||||
assertThat(version("1.10.2").isSameMinor(version("1.9.1"))).isFalse();
|
assertThat(version("1.10.2").isSameMinor(version("1.9.1"))).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForReleaseShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.2-SNAPSHOT").isSnapshotFor(version("1.10.2"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenBuildSnapshotForReleaseShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.2.BUILD-SNAPSHOT").isSnapshotFor(version("1.10.2.RELEASE"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForReleaseCandidateShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.2-SNAPSHOT").isSnapshotFor(version("1.10.2-RC2"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenBuildSnapshotForReleaseCandidateShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.2.BUILD-SNAPSHOT").isSnapshotFor(version("1.10.2.RC2"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForMilestoneShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.2-SNAPSHOT").isSnapshotFor(version("1.10.2-M1"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenBuildSnapshotForMilestoneShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.2.BUILD-SNAPSHOT").isSnapshotFor(version("1.10.2.M1"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForDifferentReleaseShouldReturnFalse() {
|
||||||
|
assertThat(version("1.10.1-SNAPSHOT").isSnapshotFor(version("1.10.2"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenBuildSnapshotForDifferentReleaseShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.1.BUILD-SNAPSHOT").isSnapshotFor(version("1.10.2.RELEASE"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForDifferentReleaseCandidateShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.1-SNAPSHOT").isSnapshotFor(version("1.10.2-RC2"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenBuildSnapshotForDifferentReleaseCandidateShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.1.BUILD-SNAPSHOT").isSnapshotFor(version("1.10.2.RC2"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForDifferentMilestoneShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.1-SNAPSHOT").isSnapshotFor(version("1.10.2-M1"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenBuildSnapshotForDifferentMilestoneShouldReturnTrue() {
|
||||||
|
assertThat(version("1.10.1.BUILD-SNAPSHOT").isSnapshotFor(version("1.10.2.M1"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenNotSnapshotShouldReturnFalse() {
|
||||||
|
assertThat(version("1.10.1-M1").isSnapshotFor(version("1.10.1"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
private ArtifactVersionDependencyVersion version(String version) {
|
private ArtifactVersionDependencyVersion version(String version) {
|
||||||
return ArtifactVersionDependencyVersion.parse(version);
|
return ArtifactVersionDependencyVersion.parse(version);
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,46 @@ class ReleaseTrainDependencyVersionTests {
|
|||||||
assertThat(version("Kay-SR6").isSameMinor(calendarVersion("2020.0.0"))).isFalse();
|
assertThat(version("Kay-SR6").isSameMinor(calendarVersion("2020.0.0"))).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForServiceReleaseShouldReturnTrue() {
|
||||||
|
assertThat(version("Kay-BUILD-SNAPSHOT").isSnapshotFor(version("Kay-SR2"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForReleaseShouldReturnTrue() {
|
||||||
|
assertThat(version("Kay-BUILD-SNAPSHOT").isSnapshotFor(version("Kay-RELEASE"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForReleaseCandidateShouldReturnTrue() {
|
||||||
|
assertThat(version("Kay-BUILD-SNAPSHOT").isSnapshotFor(version("Kay-RC1"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForMilestoneShouldReturnTrue() {
|
||||||
|
assertThat(version("Kay-BUILD-SNAPSHOT").isSnapshotFor(version("Kay-M2"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForDifferentReleaseShouldReturnFalse() {
|
||||||
|
assertThat(version("Kay-BUILD-SNAPSHOT").isSnapshotFor(version("Lovelace-RELEASE"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForDifferentReleaseCandidateShouldReturnTrue() {
|
||||||
|
assertThat(version("Kay-BUILD-SNAPSHOT").isSnapshotFor(version("Lovelace-RC2"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenSnapshotForDifferentMilestoneShouldReturnTrue() {
|
||||||
|
assertThat(version("Kay-BUILD-SNAPSHOT").isSnapshotFor(version("Lovelace-M1"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isSnapshotForWhenNotSnapshotShouldReturnFalse() {
|
||||||
|
assertThat(version("Kay-M1").isSnapshotFor(version("Kay-RELEASE"))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
private static ReleaseTrainDependencyVersion version(String input) {
|
private static ReleaseTrainDependencyVersion version(String input) {
|
||||||
return ReleaseTrainDependencyVersion.parse(input);
|
return ReleaseTrainDependencyVersion.parse(input);
|
||||||
}
|
}
|
||||||
|
272
buildSrc/src/test/resources/releases.json
Normal file
272
buildSrc/src/test/resources/releases.json
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-22",
|
||||||
|
"title": "Spring Modulith 1.0.1",
|
||||||
|
"url": "https://github.com/spring-projects/spring-modulith/milestone/15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-22",
|
||||||
|
"title": "Spring Modulith 1.1 M1",
|
||||||
|
"url": "https://github.com/spring-projects/spring-modulith/milestone/16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor 2020.0.36",
|
||||||
|
"url": "https://github.com/reactor/reactor/milestone/51"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor 2022.0.11",
|
||||||
|
"url": "https://github.com/reactor/reactor/milestone/52"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor 2023.0.0-M3",
|
||||||
|
"url": "https://github.com/reactor/reactor/milestone/53"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor Core 3.4.33",
|
||||||
|
"url": "https://github.com/reactor/reactor-core/milestone/158"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor Core 3.5.10",
|
||||||
|
"url": "https://github.com/reactor/reactor-core/milestone/159"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor Core 3.6.0-M3",
|
||||||
|
"url": "https://github.com/reactor/reactor-core/milestone/160"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-13",
|
||||||
|
"title": "Sts4 4.20.0.RELEASE",
|
||||||
|
"url": "https://github.com/spring-projects/sts4/milestone/66"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-20",
|
||||||
|
"title": "Spring Batch 5.1.0-M3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-batch/milestone/150"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-19",
|
||||||
|
"title": "Spring Integration 6.2.0-M3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-integration/milestone/306"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-19",
|
||||||
|
"title": "Spring Integration 5.5.19",
|
||||||
|
"url": "https://github.com/spring-projects/spring-integration/milestone/309"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-19",
|
||||||
|
"title": "Spring Integration 6.1.3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-integration/milestone/310"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-15",
|
||||||
|
"title": "Spring Data Release 2023.1.0-M3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-data-release/milestone/30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-15",
|
||||||
|
"title": "Spring Data Release 2021.2.16",
|
||||||
|
"url": "https://github.com/spring-projects/spring-data-release/milestone/39"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-15",
|
||||||
|
"title": "Spring Data Release 2022.0.10",
|
||||||
|
"url": "https://github.com/spring-projects/spring-data-release/milestone/40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-15",
|
||||||
|
"title": "Spring Data Release 2023.0.4",
|
||||||
|
"url": "https://github.com/spring-projects/spring-data-release/milestone/41"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-19",
|
||||||
|
"title": "Spring Graphql 1.0.5",
|
||||||
|
"url": "https://github.com/spring-projects/spring-graphql/milestone/27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-19",
|
||||||
|
"title": "Spring Graphql 1.1.6",
|
||||||
|
"url": "https://github.com/spring-projects/spring-graphql/milestone/33"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-19",
|
||||||
|
"title": "Spring Graphql 1.2.3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-graphql/milestone/34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-19",
|
||||||
|
"title": "Spring Authorization Server 1.2.0-M1",
|
||||||
|
"url": "https://github.com/spring-projects/spring-authorization-server/milestone/34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-18",
|
||||||
|
"title": "Spring Kafka 3.1.0-M1",
|
||||||
|
"url": "https://github.com/spring-projects/spring-kafka/milestone/225"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-14",
|
||||||
|
"title": "Spring Cloud Dataflow 2.11.0",
|
||||||
|
"url": "https://github.com/spring-cloud/spring-cloud-dataflow/milestone/159"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-11",
|
||||||
|
"title": "Micrometer 1.9.15",
|
||||||
|
"url": "https://github.com/micrometer-metrics/micrometer/milestone/217"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-11",
|
||||||
|
"title": "Micrometer 1.10.11",
|
||||||
|
"url": "https://github.com/micrometer-metrics/micrometer/milestone/218"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-11",
|
||||||
|
"title": "Micrometer 1.11.4",
|
||||||
|
"url": "https://github.com/micrometer-metrics/micrometer/milestone/219"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-11",
|
||||||
|
"title": "Micrometer 1.12.0-M3",
|
||||||
|
"url": "https://github.com/micrometer-metrics/micrometer/milestone/220"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-11",
|
||||||
|
"title": "Tracing 1.0.10",
|
||||||
|
"url": "https://github.com/micrometer-metrics/tracing/milestone/33"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-11",
|
||||||
|
"title": "Tracing 1.1.5",
|
||||||
|
"url": "https://github.com/micrometer-metrics/tracing/milestone/34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-26",
|
||||||
|
"title": "Spring Cloud Release 2023.0.0-M2",
|
||||||
|
"url": "https://github.com/spring-cloud/spring-cloud-release/milestone/134"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-11",
|
||||||
|
"title": "Context Propagation 1.0.6",
|
||||||
|
"url": "https://github.com/micrometer-metrics/context-propagation/milestone/19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-14",
|
||||||
|
"title": "Spring Ldap 3.2.0-M3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-ldap/milestone/63"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-21",
|
||||||
|
"title": "Spring Boot 3.2.0-M3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-boot/milestone/306"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-21",
|
||||||
|
"title": "Spring Boot 2.7.16",
|
||||||
|
"url": "https://github.com/spring-projects/spring-boot/milestone/315"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-21",
|
||||||
|
"title": "Spring Boot 3.0.11",
|
||||||
|
"url": "https://github.com/spring-projects/spring-boot/milestone/316"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-21",
|
||||||
|
"title": "Spring Boot 3.1.4",
|
||||||
|
"url": "https://github.com/spring-projects/spring-boot/milestone/317"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-14",
|
||||||
|
"title": "Spring Cloud Deployer 2.9.0",
|
||||||
|
"url": "https://github.com/spring-cloud/spring-cloud-deployer/milestone/116"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor Kafka 1.3.21",
|
||||||
|
"url": "https://github.com/reactor/reactor-kafka/milestone/38"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-18",
|
||||||
|
"title": "Spring Security 6.2.0-M3",
|
||||||
|
"url": "https://github.com/spring-projects/spring-security/milestone/308"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-22",
|
||||||
|
"title": "Stream Applications 4.0.0",
|
||||||
|
"url": "https://github.com/spring-cloud/stream-applications/milestone/7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor Netty 1.1.11",
|
||||||
|
"url": "https://github.com/reactor/reactor-netty/milestone/153"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-12",
|
||||||
|
"title": "Reactor Netty 1.0.36",
|
||||||
|
"url": "https://github.com/reactor/reactor-netty/milestone/154"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-14",
|
||||||
|
"title": "Spring Framework 6.0.12",
|
||||||
|
"url": "https://github.com/spring-projects/spring-framework/milestone/331"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-14",
|
||||||
|
"title": "Spring Framework 5.3.30",
|
||||||
|
"url": "https://github.com/spring-projects/spring-framework/milestone/332"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allDay": true,
|
||||||
|
"start": "2023-09-14",
|
||||||
|
"title": "Spring Framework 6.1.0-RC1",
|
||||||
|
"url": "https://github.com/spring-projects/spring-framework/milestone/333"
|
||||||
|
}
|
||||||
|
]
|
@ -1003,6 +1003,7 @@ bom {
|
|||||||
}
|
}
|
||||||
library("Micrometer Tracing", "1.2.0-M2") {
|
library("Micrometer Tracing", "1.2.0-M2") {
|
||||||
considerSnapshots()
|
considerSnapshots()
|
||||||
|
calendarName = "Tracing"
|
||||||
group("io.micrometer") {
|
group("io.micrometer") {
|
||||||
imports = [
|
imports = [
|
||||||
"micrometer-tracing-bom"
|
"micrometer-tracing-bom"
|
||||||
@ -1320,6 +1321,7 @@ bom {
|
|||||||
}
|
}
|
||||||
library("Reactor Bom", "2023.0.0-M2") {
|
library("Reactor Bom", "2023.0.0-M2") {
|
||||||
considerSnapshots()
|
considerSnapshots()
|
||||||
|
calendarName = "Reactor"
|
||||||
group("io.projectreactor") {
|
group("io.projectreactor") {
|
||||||
imports = [
|
imports = [
|
||||||
"reactor-bom"
|
"reactor-bom"
|
||||||
@ -1508,11 +1510,17 @@ bom {
|
|||||||
}
|
}
|
||||||
library("Spring Data Bom", "2023.1.0-M2") {
|
library("Spring Data Bom", "2023.1.0-M2") {
|
||||||
considerSnapshots()
|
considerSnapshots()
|
||||||
|
calendarName = "Spring Data Release"
|
||||||
|
prohibit {
|
||||||
|
versionRange "[2022.0.0-M1,)"
|
||||||
|
because "it uses Spring Framework 6"
|
||||||
|
}
|
||||||
group("org.springframework.data") {
|
group("org.springframework.data") {
|
||||||
imports = [
|
imports = [
|
||||||
"spring-data-bom"
|
"spring-data-bom"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
library("Spring Framework", "${springFrameworkVersion}") {
|
library("Spring Framework", "${springFrameworkVersion}") {
|
||||||
considerSnapshots()
|
considerSnapshots()
|
||||||
|
Loading…
Reference in New Issue
Block a user