#151 - Adapt project metadata update to new Sagan API.

This commit is contained in:
Mark Paluch
2020-10-15 08:20:29 +02:00
parent fca3466a42
commit d487333b78
16 changed files with 223 additions and 192 deletions

View File

@@ -21,12 +21,15 @@ import lombok.experimental.FieldDefaults;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.TimeZone;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
@@ -38,10 +41,12 @@ import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.LogCommand;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -67,6 +72,7 @@ import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
import org.springframework.data.release.utils.ExecutionUtils;
import org.springframework.data.release.utils.Logger;
import org.springframework.data.util.Streamable;
import org.springframework.plugin.core.PluginRegistry;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
@@ -309,11 +315,38 @@ public class GitOperations {
return doWithGit(project, git -> {
return new VersionTags(git.tagList().call().stream()//
.map(ref -> Tag.of(ref.getName()))//
.map(ref -> {
RevCommit commit = getCommit(git.getRepository(), ref);
PersonIdent authorIdent = commit.getAuthorIdent();
Date authorDate = authorIdent.getWhen();
TimeZone authorTimeZone = authorIdent.getTimeZone();
LocalDateTime localDate = authorDate.toInstant().atZone(authorTimeZone.toZoneId()).toLocalDateTime();
return Tag.of(ref.getName(), localDate);
})//
.collect(Collectors.toList()));
});
}
private RevCommit getCommit(Repository repository, Ref ref) {
return doWithGit(repository, git -> {
Ref peeledRef = git.getRepository().getRefDatabase().peel(ref);
LogCommand log = git.log();
if (peeledRef.getPeeledObjectId() != null) {
log.add(peeledRef.getPeeledObjectId());
} else {
log.add(ref.getObjectId());
}
return Streamable.of(log.call()).stream().findFirst()
.orElseThrow(() -> new IllegalStateException("Cannot resolve commit for " + ref));
});
}
/**
* Retrieve a list of remote branches where their related ticket is resolved.
*
@@ -788,9 +821,16 @@ public class GitOperations {
private <T> T doWithGit(Project project, GitCallback<T> callback) {
try (Git git = new Git(getRepository(project))) {
T result = callback.doWithGit(git);
Thread.sleep(100);
return result;
return callback.doWithGit(git);
} catch (Exception o_O) {
throw new RuntimeException(o_O);
}
}
private <T> T doWithGit(Repository repository, GitCallback<T> callback) {
try (Git git = new Git(repository)) {
return callback.doWithGit(git);
} catch (Exception o_O) {
throw new RuntimeException(o_O);
}

View File

@@ -17,34 +17,43 @@ package org.springframework.data.release.git;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.time.LocalDateTime;
import java.util.Optional;
import org.springframework.data.release.model.ArtifactVersion;
/**
* Value object to represent an SCM tag.
*
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@EqualsAndHashCode
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
public class Tag implements Comparable<Tag> {
private final String name;
private final LocalDateTime creationDate;
public static Tag of(String source) {
return of(source, LocalDateTime.now());
}
public static Tag of(String source, LocalDateTime creationDate) {
int slashIndex = source.lastIndexOf('/');
return new Tag(source.substring(slashIndex == -1 ? 0 : slashIndex + 1));
return new Tag(source.substring(slashIndex == -1 ? 0 : slashIndex + 1), creationDate);
}
/**
* Returns the part of the name of the tag that is suitable to derive a version from the tag. Will transparently strip
* a {@code v} prefix from the name.
*
*
* @return
*/
private String getVersionSource() {
@@ -66,15 +75,15 @@ public class Tag implements Comparable<Tag> {
/**
* Creates a new {@link Tag} for the given {@link ArtifactVersion} based on the format of the current one.
*
*
* @param version
* @return
*/
public Tag createNew(ArtifactVersion version) {
return new Tag(name.startsWith("v") ? "v".concat(version.toString()) : version.toString());
return new Tag(name.startsWith("v") ? "v".concat(version.toString()) : version.toString(), LocalDateTime.now());
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@@ -83,7 +92,7 @@ public class Tag implements Comparable<Tag> {
return name;
}
/*
/*
* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/

View File

@@ -272,4 +272,8 @@ public class ArtifactVersion implements Comparable<ArtifactVersion> {
private String getSnapshotSuffix() {
return modifierFormat ? SNAPSHOT_MODIFIER : SNAPSHOT_SUFFIX;
}
public String getGeneration() {
return String.format("%s.%s.x", version.getMajor(), version.getMinor());
}
}

View File

@@ -21,6 +21,7 @@ import lombok.experimental.FieldDefaults;
import net.minidev.json.JSONArray;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -67,9 +68,9 @@ class DefaultSaganClient implements SaganClient {
@Override
public String getProjectMetadata(Project project) {
URI resource = properties.getProjectMetadataResource(project);
URI resource = properties.getProjectReleasesResource(project);
logger.log(project, "Getting project metadata from %s…", resource);
logger.log(project, "Getting project releases from %s…", resource);
return operations.getForObject(resource, String.class);
}
@@ -81,28 +82,44 @@ class DefaultSaganClient implements SaganClient {
@Override
public void updateProjectMetadata(Project project, MaintainedVersions versions) {
URI resource = properties.getProjectMetadataResource(project);
URI resource = properties.getProjectReleasesResource(project);
String versionsString = versions.stream()//
.map(MaintainedVersion::getVersion)//
.map(Object::toString) //
.collect(Collectors.joining(", "));
List<String> versionsToRetain = versions.stream() //
.map(version -> new ProjectMetadata(version, versions)).map(ProjectMetadata::getVersion)
.collect(Collectors.toList());
List<String> versionsInSagan = new ArrayList<>();
logger.log(project, "Updating project metadata to %s via %s…", versionsString, resource);
logger.log(project, "Updating project version to %s via %s…", versionsString, resource);
// Delete all existing versions first
Arrays.stream(JsonPath.compile("$..version").<JSONArray> read(getProjectMetadata(project)).toArray())//
.map(version -> properties.getProjectMetadataResource(project, version.toString()))//
.peek(uri -> logger.log(project, "Deleting existing project metadata at %s…", uri)) //
.forEach(operations::delete);
deleteExistingVersions(project, versionsToRetain, versionsInSagan);
logger.log(project, "Writing project metadata for versions %s!", versionsString);
logger.log(project, "Writing project versions %s.", versionsString);
// Write new ones
List<ProjectMetadata> payload = versions.stream() //
.map(version -> new ProjectMetadata(version, versions)) //
.collect(Collectors.toList());
createVersions(versions, resource, versionsInSagan);
}
operations.put(resource, payload);
private void createVersions(MaintainedVersions versions, URI resource, List<String> versionsInSagan) {
versions.stream() //
.map(it -> new ProjectMetadata(it, versions)) //
.filter(version -> !versionsInSagan.contains(version.getVersion())) //
.forEach(payload -> operations.postForObject(resource, payload, String.class));
}
private void deleteExistingVersions(Project project, List<String> versionsToRetain, List<String> versionsInSagan) {
Arrays.stream(JsonPath.compile("$..version").<JSONArray> read(getProjectMetadata(project)).toArray())//
.map(Object::toString) //
.peek(versionsInSagan::add) //
.filter(version -> !versionsToRetain.contains(version)) //
.map(version -> properties.getProjectReleaseResource(project, version))//
.peek(uri -> logger.log(project, "Deleting existing project version at %s…", uri)) //
.forEach(operations::delete);
}
}

View File

@@ -19,6 +19,7 @@ import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@@ -31,8 +32,9 @@ import com.fasterxml.jackson.databind.ObjectWriter;
/**
* Dummy implementation of {@link SaganClient} to just dump the request payloads into {@link System#out} instead of
* communicating with a real server.
*
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@@ -61,7 +63,7 @@ class DummySaganClient implements SaganClient {
}
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.release.sagan.SaganClient#getProjectMetadata(org.springframework.data.release.sagan.MaintainedVersion)
*/
@@ -69,13 +71,13 @@ class DummySaganClient implements SaganClient {
public String getProjectMetadata(MaintainedVersion version) {
try {
return mapper.writeValueAsString(new ProjectMetadata(version, MaintainedVersions.of(version)));
return mapper.writeValueAsString(new ProjectMetadata(version, MaintainedVersions.of(Collections.emptyList())));
} catch (JsonProcessingException o_O) {
throw new RuntimeException(o_O);
}
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.release.sagan.SaganClient#getProjectMetadata(org.springframework.data.release.model.Project)
*/

View File

@@ -17,6 +17,7 @@ package org.springframework.data.release.sagan;
import lombok.Value;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.stream.Stream;
@@ -24,12 +25,14 @@ import org.springframework.data.release.model.ArtifactVersion;
import org.springframework.data.release.model.Module;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.Train;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Represents a maintained project version to be represented in Sagan.
*
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@Value(staticConstructor = "of")
class MaintainedVersion implements Comparable<MaintainedVersion> {
@@ -37,16 +40,19 @@ class MaintainedVersion implements Comparable<MaintainedVersion> {
Project project;
ArtifactVersion version;
Train train;
@Nullable LocalDate releaseDate;
@Nullable LocalDate generationInception;
/**
* Creates a new {@link MaintainedVersion} representing the snaphot version of the given {@link Module} and
* Creates a new {@link MaintainedVersion} representing the snapshot version of the given {@link Module} and
* {@link Train}.
*
*
* @param module must not be {@literal null}.
* @param train must not be {@literal null}.
* @param train can be {@literal null}.
* @return
*/
public static MaintainedVersion snapshot(Module module, Train train) {
public static MaintainedVersion snapshot(Module module, Train train, LocalDate generationInception) {
Assert.notNull(module, "Module must not be null!");
Assert.notNull(train, "Train must not be null!");
@@ -54,13 +60,13 @@ class MaintainedVersion implements Comparable<MaintainedVersion> {
ArtifactVersion snapshotVersion = ArtifactVersion.of(module.getVersion()).withModifierFormat(train.usesCalver())
.getSnapshotVersion();
return MaintainedVersion.of(module.getProject(), snapshotVersion, train);
return MaintainedVersion.of(module.getProject(), snapshotVersion, train, null, generationInception);
}
/**
* Returns a {@link Stream} of {@link MaintainedVersion} that are related to the current one. In case the current one
* is not a snapshot version in the first place, the next development version is added, too.
*
*
* @return
*/
Stream<MaintainedVersion> all() {
@@ -69,14 +75,14 @@ class MaintainedVersion implements Comparable<MaintainedVersion> {
/**
* Creates the {@link MaintainedVersion} for the next development version of the current one.
*
*
* @return
*/
MaintainedVersion nextDevelopmentVersion() {
return MaintainedVersion.of(project, version.getNextBugfixVersion(), train);
return MaintainedVersion.of(project, version.getNextBugfixVersion(), train, LocalDate.now(), generationInception);
}
/*
/*
* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/

View File

@@ -17,7 +17,6 @@ package org.springframework.data.release.sagan;
import java.util.Locale;
import org.springframework.data.release.build.MavenArtifact;
import org.springframework.data.release.model.ArtifactVersion;
import org.springframework.data.release.model.Projects;
import org.springframework.data.release.model.Train;
@@ -25,11 +24,13 @@ import org.springframework.util.Assert;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Simple value object to create payloads to update project metadata in Sagan.
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@JsonInclude(Include.NON_NULL)
class ProjectMetadata {
@@ -38,13 +39,11 @@ class ProjectMetadata {
private static String DOCS = DOCS_BASE.concat("/reference/html/");
private static String JAVADOC = DOCS_BASE.concat("/api");
private final MaintainedVersions versions;
private final MaintainedVersion version;
private final MavenArtifact artifact;
private final MaintainedVersions versions;
/**
* Creates a new {@link ProjectMetadata} instace from the given {@link MaintainedVersion} in the context of the
* {@link MaintainedVersions}.
* Creates a new {@link ProjectMetadata} instance from the given {@link MaintainedVersion}.
*
* @param version must not be {@literal null}.
* @param versions must not be {@literal null}.
@@ -52,67 +51,9 @@ class ProjectMetadata {
public ProjectMetadata(MaintainedVersion version, MaintainedVersions versions) {
Assert.notNull(version, "MaintainedVersion must not be null!");
Assert.notNull(versions, "MaintainedVersions must not be null!");
this.version = version;
this.versions = versions;
this.artifact = new MavenArtifact(version.getProject(), version.getVersion());
}
/**
* Returns the release status used on Sagan.
*
* @return
*/
public String getReleaseStatus() {
ArtifactVersion artifactVersion = version.getVersion();
if (artifactVersion.isReleaseVersion()) {
return "GENERAL_AVAILABILITY";
}
if (artifactVersion.isMilestoneVersion()) {
return "PRERELEASE";
}
if (artifactVersion.isSnapshotVersion()) {
return "SNAPSHOT";
}
throw new IllegalStateException();
}
/**
* Returns the group identifier of the release.
*
* @return
*/
public String getGroupId() {
return artifact.getGroupId();
}
/**
* Returns the artifact identifier.
*
* @return
*/
public String getArtifactId() {
if (Projects.BUILD.equals(version.getProject())) {
return "spring-data-releasetrain";
}
return artifact.getArtifactId();
}
/**
* Returns whether the version is the most current one.
*
* @return
*/
public Boolean getCurrent() {
return versions.isMainVersion(version) ? true : null;
}
/**
@@ -120,13 +61,23 @@ class ProjectMetadata {
*
* @return
*/
public String getRefDocUrl() {
public String getReferenceDocUrl() {
return version.getVersion().isSnapshotVersion() || Projects.BUILD.equals(version.getProject()) //
? "" //
: String.format(DOCS, version.getProject().getName().toLowerCase(Locale.US));
}
/**
* Returns whether the version is the most current one.
*
* @return
*/
@JsonProperty("isCurrent")
public boolean getCurrent() {
return versions.isMainVersion(version);
}
/**
* Returns the JavaDoc URL for non-snapshot versions and not the build project.
*
@@ -139,10 +90,6 @@ class ProjectMetadata {
: String.format(JAVADOC, version.getProject().getName().toLowerCase(Locale.US));
}
public Repository getRepository() {
return new Repository();
}
/**
* Return the version to use. For the build project that's the release train name, for everything else the artifact
* version.
@@ -172,38 +119,4 @@ class ProjectMetadata {
return version.toString();
}
public class Repository {
public String getId() {
return artifact.getRepository().getId();
}
public boolean isSnapshotsEnabled() {
return version.getVersion().isSnapshotVersion();
}
public String getUrl() {
return artifact.getRepository().getUrl();
}
public String getName() {
String result = "Spring ";
if (version.getVersion().isMilestoneVersion()) {
return result.concat("Milestones");
}
if (version.getVersion().isReleaseVersion()) {
return result.concat("Releases");
}
if (isSnapshotsEnabled()) {
return result.concat("Snapshots");
}
throw new IllegalStateException();
}
}
}

View File

@@ -29,6 +29,7 @@ import org.springframework.web.client.RestTemplate;
* Configuration for the Sagan interaction subsystem.
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@Configuration
class SaganConfiguration {
@@ -50,6 +51,6 @@ class SaganConfiguration {
@Bean
RestTemplate saganRestTemplate() {
return new RestTemplateBuilder().basicAuthentication(properties.key, "").build();
return new RestTemplateBuilder().basicAuthentication("mp911de", properties.key).build();
}
}

View File

@@ -19,12 +19,14 @@ import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.data.release.git.GitOperations;
@@ -106,22 +108,25 @@ class SaganOperations {
return ExecutionUtils.runAndReturn(executor,
Streamable.of(() -> train.stream().filter(module -> !TO_FILTER.contains(module.getProject()))), module -> {
return getLatestVersion(module, train);
}).stream().flatMap(MaintainedVersion::all);
}).stream().flatMap(Function.identity()).collect(
});
}).stream().flatMap(Collection::stream).flatMap(Collection::stream).collect(
Collectors.groupingBy(MaintainedVersion::getProject, ListWrapperCollector.collectInto(MaintainedVersions::of)));
}
private MaintainedVersion getLatestVersion(Module module, Train train) {
private List<MaintainedVersion> getLatestVersion(Module module, Train train) {
Project project = module.getProject();
MaintainedVersion version = git.getTags(project).stream()//
List<MaintainedVersion> version = git.getTags(project).stream()//
.filter(tag -> matches(tag, module.getVersion())).max(Comparator.naturalOrder()) //
.flatMap(Tag::toArtifactVersion) //
.map(it -> MaintainedVersion.of(module.getProject(), it, train)) //
.orElseGet(() -> MaintainedVersion.snapshot(module, train));
.map(it -> {
MaintainedVersion maintainedVersion = MaintainedVersion.of(module.getProject(), it.toArtifactVersion().get(),
train, it.getCreationDate().toLocalDate(), it.getCreationDate().toLocalDate());
return Arrays.asList(maintainedVersion, maintainedVersion.nextDevelopmentVersion());
}) //
.orElseGet(() -> Collections.singletonList(MaintainedVersion.snapshot(module, train, LocalDate.now())));
logger.log(project, "Found version %s for train %s!", version.getVersion(), train.getName());
logger.log(project, "Found version %s for train %s!", version, train.getName());
return version;
}

View File

@@ -20,74 +20,78 @@ import lombok.Setter;
import java.net.URI;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.release.model.Password;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.Projects;
import org.springframework.data.release.utils.HttpBasicCredentials;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.util.UriTemplate;
/**
* Configuration properties for the Sagan instance to talk to.
*
*
* @author Oliver Gierke
*/
@Component
@ConfigurationProperties(prefix = "sagan")
class SaganProperties {
private static String SAGAN_PROJECT_METADATA = "https://spring.io/project_metadata/{project}/releases";
private static String SAGAN_PROJECT_VERSION_METADATA = SAGAN_PROJECT_METADATA.concat("/{version}");
private static String SAGAN_BASE = "https://spring.io/api/";
private static String SAGAN_RELEASES = SAGAN_BASE.concat("projects/{project}/releases");
private static String SAGAN_GENERATIONS = SAGAN_BASE.concat("projects/{project}/generations");
private static String SAGAN_RELEASE_VERSION = SAGAN_RELEASES.concat("/{version}");
@Setter String key;
/**
* Returns the {@link HttpBasicCredentials} to be used when talking to the server.
*
* @return
*/
HttpBasicCredentials getCredentials() {
return new HttpBasicCredentials(key, Password.NONE);
}
/**
* Returns the URI to the resource exposing the project metadata for the given {@link Project}.
*
* Returns the URI to the resource exposing the project releases for the given {@link Project}.
*
* @param project must not be {@literal null}.
* @return
*/
URI getProjectMetadataResource(Project project) {
URI getProjectReleasesResource(Project project) {
Assert.notNull(project, "Project must not be null!");
Assert.notNull(project, "Project must not be null!");
return new UriTemplate(SAGAN_PROJECT_METADATA).expand(getProjectPathSegment(project));
return new UriTemplate(SAGAN_RELEASES).expand(getProjectPathSegment(project));
}
/**
* Returns the URI to the resource exposing the project metadata for the given {@link Project} and version
* Returns the URI to the resource exposing the project generations for the given {@link Project}.
*
* @param project must not be {@literal null}.
* @return
*/
URI getProjectGenerationsResource(Project project) {
Assert.notNull(project, "Project must not be null!");
return new UriTemplate(SAGAN_GENERATIONS).expand(getProjectPathSegment(project));
}
/**
* Returns the URI to the resource exposing the project version for the given {@link Project} and version
* {@link String}.
*
*
* @param project must not be {@literal null}.
* @param version must not be {@literal null}.
* @return
*/
URI getProjectMetadataResource(Project project, String version) {
URI getProjectReleaseResource(Project project, String version) {
Assert.notNull(project, "Project must not be null!");
Assert.hasText(version, "Version must not be null!");
return new UriTemplate(SAGAN_PROJECT_VERSION_METADATA).expand(getProjectPathSegment(project), version);
return new UriTemplate(SAGAN_RELEASE_VERSION).expand(getProjectPathSegment(project), version);
}
/**
* Returns the {@link URI} to the resource exposing the project metadata for the given {@link MaintainedVersion}.
*
* Returns the {@link URI} to the resource exposing the project version for the given {@link MaintainedVersion}.
*
* @param version must not be {@literal null}.
* @return
*/
URI getProjectMetadataResource(MaintainedVersion version) {
return getProjectMetadataResource(version.getProject(), version.getVersion().toString());
return getProjectReleaseResource(version.getProject(), version.getVersion().toString());
}
private static String getProjectPathSegment(Project project) {

View File

@@ -91,6 +91,6 @@ class MavenIntegrationTests extends AbstractIntegrationTests {
@Test
void findsSnapshotDependencies() throws Exception {
Pom pom = projection.io().file(workspace.getFile("bom/pom.xml", Projects.BUILD)).read(Pom.class);
Pom pom = projection.io().file(workspace.getFile("pom.xml", Projects.BUILD)).read(Pom.class);
}
}

View File

@@ -105,14 +105,25 @@ class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests {
}
@Test // #5
void noReleaseTicketFound() {
void noMilestoneNoReleaseTicketFound() {
mockGetMilestonesWith("emptyMilestones.json");
assertThatIllegalArgumentException().isThrownBy(() -> github.getReleaseTicketFor(BUILD_HOPPER_RC1))
assertThatIllegalStateException().isThrownBy(() -> github.getReleaseTicketFor(BUILD_HOPPER_RC1))
.withMessageContaining("No milestone for Spring Data Build found containing 1.8 RC1 (Hopper)!");
}
@Test // #5
void noReleaseTicketFound() {
mockGetMilestonesWith("milestones.json");
mockGetIssuesWith("emptyIssues.json");
assertThatIllegalArgumentException().isThrownBy(() -> github.getReleaseTicketFor(BUILD_HOPPER_RC1))
.withMessageContaining(
"Did not find a release ticket for Spring Data Build 1.8 RC1 (Hopper) containing Release 1.8 RC1 (Hopper)!");
}
@Test // #5
void createReleaseVersionShouldCreateAVersion() {
@@ -156,7 +167,7 @@ class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests {
mockGetIssuesWith("emptyIssues.json");
mockGetMilestonesWith("emptyMilestones.json");
assertThatIllegalArgumentException().isThrownBy(() -> github.createReleaseTicket(moduleIteration))
assertThatIllegalStateException().isThrownBy(() -> github.createReleaseTicket(moduleIteration))
.withMessageContaining("No milestone for Spring Data Build found containing 1.8 RC1 (Hopper)!");
}

View File

@@ -24,7 +24,7 @@ import org.springframework.data.release.model.ReleaseTrains;
/**
* Unit tests for {@link MaintainedVersion}.
*
*
* @author Oliver Gierke
*/
class MaintainedVersionUnitTests {
@@ -33,9 +33,9 @@ class MaintainedVersionUnitTests {
void newerVersionIsOrderedFirst() {
MaintainedVersion ingalls = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.13.0.RELEASE"),
ReleaseTrains.INGALLS);
ReleaseTrains.INGALLS, null, null);
MaintainedVersion hopper = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.12.0.RELEASE"),
ReleaseTrains.HOPPER);
ReleaseTrains.HOPPER, null, null);
assertThat(ingalls.compareTo(hopper)).isGreaterThan(0);
}

View File

@@ -24,7 +24,7 @@ import org.springframework.data.release.model.ReleaseTrains;
/**
* Unit tests for {@link MaintainedVersions}.
*
*
* @author Oliver Gierke
*/
class MaintainedVersionsUnitTests {
@@ -33,9 +33,9 @@ class MaintainedVersionsUnitTests {
void considersMostRecentReleaseVersionTheMainOne() {
MaintainedVersion ingalls = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.13.0.RELEASE"),
ReleaseTrains.INGALLS);
ReleaseTrains.INGALLS, null, null);
MaintainedVersion hopper = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.12.0.RELEASE"),
ReleaseTrains.HOPPER);
ReleaseTrains.HOPPER, null, null);
MaintainedVersions versions = MaintainedVersions.of(ingalls, hopper);

View File

@@ -25,8 +25,9 @@ import com.fasterxml.jackson.databind.ObjectWriter;
/**
* Tests for serialization of {@link ProjectMetadata}.
*
*
* @author Oliver Gierke
* @author Mark Paluch
*/
class ProjectMetadataSerializationTests {
@@ -35,14 +36,15 @@ class ProjectMetadataSerializationTests {
ObjectWriter mapper = new ObjectMapper().writerWithDefaultPrettyPrinter();
MaintainedVersion kay = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("2.0.0.RC1"), ReleaseTrains.KAY);
MaintainedVersion kay = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("2.0.0.RC1"), ReleaseTrains.KAY,
null, null);
MaintainedVersion ingalls = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.13.5.RELEASE"),
ReleaseTrains.INGALLS);
ReleaseTrains.INGALLS, null, null);
MaintainedVersion ingallsSnapshot = ingalls.nextDevelopmentVersion();
MaintainedVersion hopper = MaintainedVersion.of(Projects.COMMONS, ArtifactVersion.of("1.12.8.RELEASE"),
ReleaseTrains.HOPPER);
ReleaseTrains.HOPPER, null, null);
MaintainedVersions versions = MaintainedVersions.of(kay, ingalls, ingallsSnapshot, hopper);
MaintainedVersions versions = MaintainedVersions.of(kay, ingalls, hopper);
System.out.println(mapper.writeValueAsString(new ProjectMetadata(kay, versions)));
System.out.println(mapper.writeValueAsString(new ProjectMetadata(ingallsSnapshot, versions)));

View File

@@ -15,11 +15,17 @@
*/
package org.springframework.data.release.sagan;
import static org.assertj.core.api.Assertions.*;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.release.AbstractIntegrationTests;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.Projects;
import org.springframework.data.release.model.ReleaseTrains;
@@ -48,8 +54,6 @@ class SaganOperationsIntegrationTests extends AbstractIntegrationTests {
String output = version.toString();
System.out.println(versions.isMainVersion(version) ? output.concat(" (main release)") : output);
});
System.out.println();
});
}
@@ -58,6 +62,19 @@ class SaganOperationsIntegrationTests extends AbstractIntegrationTests {
sagan.updateProjectMetadata(ReleaseTrains.KAY, ReleaseTrains.INGALLS, ReleaseTrains.HOPPER);
}
@Test
void findVersions() {
Map<Project, MaintainedVersions> versions = sagan.findVersions(ReleaseTrains.LOVELACE, ReleaseTrains.MOORE,
ReleaseTrains.NEUMANN);
List<MaintainedVersion> maintainedVersions = versions.get(Projects.ELASTICSEARCH)
.filter(it -> it.getVersion().isReleaseVersion()).toList();
assertThat(maintainedVersions).isNotEmpty();
assertThat(maintainedVersions.get(0).getGenerationInception()).isNotNull();
assertThat(maintainedVersions.get(0).getReleaseDate()).isNotNull();
}
@Test
void updateJpa() {