diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java index 9bcb75da..f4d81f70 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java @@ -83,6 +83,13 @@ public class ProjectVersion { return this.version.matches(".*.SR[0-9]+"); } + public boolean isSameMinor(String version) { + String[] splitThis = this.version.split("\\."); + String[] splitThat = version.split("\\."); + return splitThis.length == splitThat.length && + splitThis[0].equals(splitThat[0]) && splitThis[1].equals(splitThat[1]); + } + @Override public String toString() { return this.version; } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java index b9577edd..a8d32f67 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java @@ -1,5 +1,8 @@ package org.springframework.cloud.release.internal.sagan; +import java.util.List; +import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.release.internal.pom.ProjectVersion; @@ -21,14 +24,22 @@ public class SaganUpdater { public void updateSagan(String branch, ProjectVersion originalVersion, ProjectVersion version) { ReleaseUpdate update = releaseUpdate(branch, originalVersion, version); + updateSaganForGa(branch, originalVersion, version); log.info("Updating Sagan with \n\n{}", update); this.saganClient.updateRelease(version.projectName, Collections.singletonList(update)); + } + + private void updateSaganForGa(String branch, ProjectVersion originalVersion, + ProjectVersion version) { if (version.isRelease() || version.isServiceRelease()) { - log.info("Version is GA [{}]. Will remove old snapshot and add a new one", version); + log.info("Version is GA [{}]. Will remove all older versions and mark this as current", version); + Project project = this.saganClient.getProject(version.projectName); + if (project != null) { + removeAllSameMinorVersions(version, project); + } String snapshot = toSnapshot(version.version); + removeVersionFromSagan(version, snapshot); String bumpedSnapshot = toSnapshot(version.bumpedVersion()); - log.info("Removing [{}/{}] from Sagan", version.projectName, snapshot); - this.saganClient.deleteRelease(version.projectName, snapshot); ReleaseUpdate snapshotUpdate = releaseUpdate(branch, originalVersion, new ProjectVersion(version.projectName, bumpedSnapshot)); log.info("Updating Sagan with \n\n[{}]", snapshotUpdate); @@ -36,6 +47,18 @@ public class SaganUpdater { } } + private void removeAllSameMinorVersions(ProjectVersion version, Project project) { + project.projectReleases.stream() + .filter(release -> version.isSameMinor(release.version)) + .collect(Collectors.toList()) + .forEach(release -> removeVersionFromSagan(version, release.version)); + } + + private void removeVersionFromSagan(ProjectVersion version, String snapshot) { + log.info("Removing [{}/{}] from Sagan", version.projectName, snapshot); + this.saganClient.deleteRelease(version.projectName, snapshot); + } + private ReleaseUpdate releaseUpdate(String branch, ProjectVersion originalVersion, ProjectVersion version) { ReleaseUpdate update = new ReleaseUpdate(); @@ -45,6 +68,7 @@ public class SaganUpdater { update.releaseStatus = version(version); update.apiDocUrl = referenceUrl(branch, version); update.refDocUrl = referenceUrl(branch, version); + update.current = true; return update; } diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectVersionTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectVersionTests.java index 22eae825..ecd132ec 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectVersionTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectVersionTests.java @@ -152,6 +152,30 @@ public class ProjectVersionTests { then(projectVersion(version).isRc()).isFalse(); } + @Test + public void should_return_true_when_versions_are_from_same_minor() { + String thisVersion = "1.3.1.RC3"; + String thatVersion = "1.3.2.SR3"; + + then(projectVersion(thisVersion).isSameMinor(thatVersion)).isTrue(); + } + + @Test + public void should_return_false_when_versions_of_different_sizes() { + String thisVersion = "1.3.1.RC3"; + String thatVersion = "1.3.RC3"; + + then(projectVersion(thisVersion).isSameMinor(thatVersion)).isFalse(); + } + + @Test + public void should_return_false_when_versions_not_of_same_minor() { + String thisVersion = "1.3.1.RC3"; + String thatVersion = "1.4.2.RC3"; + + then(projectVersion(thisVersion).isSameMinor(thatVersion)).isFalse(); + } + @Test public void should_return_empty_group_id_when_it_is_missing() { ProjectVersion projectVersion = projectVersion("1.0.0.RC1"); diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java index 4f1d8c89..a1e5f219 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java @@ -1,9 +1,11 @@ package org.springframework.cloud.release.internal.sagan; +import java.util.Arrays; import java.util.List; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.BDDMockito; @@ -12,6 +14,10 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.cloud.release.internal.pom.ProjectVersion; +import static org.mockito.BDDMockito.then; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.never; + /** * @author Marcin Grzejszczak */ @@ -21,10 +27,29 @@ public class SaganUpdaterTest { @Mock SaganClient saganClient; @InjectMocks SaganUpdater saganUpdater; + @Before + public void setup() { + Project project = new Project(); + project.projectReleases.addAll(Arrays.asList( + release("1.0.0.RC1"), + release("1.1.0.BUILD-SNAPSHOT"), + release("2.0.0.M4")) + ); + BDDMockito.given(this.saganClient.getProject(anyString())) + .willReturn(project); + } + + private Release release(String version) { + Release release = new Release(); + release.version = version; + release.current = true; + return release; + } + @Test public void should_update_sagan_for_milestone() throws Exception { this.saganUpdater.updateSagan("master", version("1.0.0.M1"), version("1.0.0.M1")); - BDDMockito.then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), + then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.0.0.M1", "http://cloud.spring.io/spring-cloud-static/foo/{version}/", "PRERELEASE"))); } @@ -32,7 +57,7 @@ public class SaganUpdaterTest { @Test public void should_update_sagan_for_rc() throws Exception { this.saganUpdater.updateSagan("master", version("1.0.0.RC1"), version("1.0.0.RC1")); - BDDMockito.then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), + then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.0.0.RC1", "http://cloud.spring.io/spring-cloud-static/foo/{version}/", "PRERELEASE"))); } @@ -46,7 +71,7 @@ public class SaganUpdaterTest { this.saganUpdater.updateSagan("master", projectVersion, projectVersion); - BDDMockito.then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), + then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.0.0.BUILD-SNAPSHOT", "http://cloud.spring.io/foo/foo.html", "SNAPSHOT"))); } @@ -56,11 +81,13 @@ public class SaganUpdaterTest { this.saganUpdater.updateSagan("master", projectVersion, projectVersion); - BDDMockito.then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), + then(this.saganClient).should().deleteRelease("foo", "1.0.0.RC1"); + then(this.saganClient).should().deleteRelease("foo", "1.0.0.BUILD-SNAPSHOT"); + then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.0.0.RELEASE", "http://cloud.spring.io/spring-cloud-static/foo/{version}/", "GENERAL_AVAILABILITY"))); - BDDMockito.then(this.saganClient).should().deleteRelease("foo", "1.0.0.BUILD-SNAPSHOT"); - BDDMockito.then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), + then(this.saganClient).should().deleteRelease("foo", "1.0.0.BUILD-SNAPSHOT"); + then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.0.1.BUILD-SNAPSHOT", "http://cloud.spring.io/foo/foo.html", "SNAPSHOT"))); } @@ -70,7 +97,8 @@ public class SaganUpdaterTest { this.saganUpdater.updateSagan("1.1.x", projectVersion, projectVersion); - BDDMockito.then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), + then(this.saganClient).should(never()).deleteRelease(anyString(), anyString()); + then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.1.0.BUILD-SNAPSHOT", "http://cloud.spring.io/foo/1.1.x/", "SNAPSHOT"))); } @@ -84,7 +112,8 @@ public class SaganUpdaterTest { releaseStatus.equals(item.releaseStatus) && version.equals(item.version) && refDocUrl.equals(item.apiDocUrl) && - refDocUrl.equals(item.refDocUrl); + refDocUrl.equals(item.refDocUrl) && + item.current; } @Override public void describeTo(Description description) { diff --git a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java index bb616c79..9bf3361c 100644 --- a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java +++ b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java @@ -1,11 +1,13 @@ package org.springframework.cloud.release.internal.spring; import static org.assertj.core.api.BDDAssertions.then; +import static org.mockito.Matchers.anyString; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; +import java.util.Arrays; import java.util.Iterator; import org.apache.maven.model.Model; @@ -29,6 +31,8 @@ import org.springframework.cloud.release.internal.pom.Projects; import org.springframework.cloud.release.internal.pom.TestPomReader; import org.springframework.cloud.release.internal.pom.TestUtils; import org.springframework.cloud.release.internal.project.ProjectBuilder; +import org.springframework.cloud.release.internal.sagan.Project; +import org.springframework.cloud.release.internal.sagan.Release; import org.springframework.cloud.release.internal.sagan.SaganClient; import org.springframework.cloud.release.internal.sagan.SaganUpdater; import org.springframework.cloud.release.internal.template.TemplateGenerator; @@ -52,6 +56,26 @@ public class AcceptanceTests { this.springCloudConsulProject = new File(AcceptanceTests.class.getResource("/projects/spring-cloud-consul").toURI()); TestUtils.prepareLocalRepo(); FileSystemUtils.copyRecursively(file("/projects/"), this.temporaryFolder); + BDDMockito.given(this.saganClient.getProject(anyString())) + .willReturn(newProject()); + } + + private Project newProject() { + Project project = new Project(); + project.projectReleases.addAll(Arrays.asList( + release("1.0.0.M8"), + release("1.1.0.M8"), + release("1.2.0.M8"), + release("2.0.0.M8")) + ); + return project; + } + + private Release release(String version) { + Release release = new Release(); + release.version = version; + release.current = true; + return release; } @Test @@ -104,7 +128,14 @@ public class AcceptanceTests { // second time to update SNAPSHOT BDDMockito.then(this.saganClient).should(BDDMockito.times(2)).updateRelease(BDDMockito.eq("spring-cloud-consul"), BDDMockito.anyList()); - BDDMockito.then(this.saganClient).should().deleteRelease("spring-cloud-consul", "1.1.2.BUILD-SNAPSHOT"); + BDDMockito.then(this.saganClient).should().deleteRelease("spring-cloud-consul", + "1.1.2.BUILD-SNAPSHOT"); + BDDMockito.then(this.saganClient).should().deleteRelease("spring-cloud-consul", + "1.1.0.M8"); + BDDMockito.then(this.saganClient).should(BDDMockito.never()) + .deleteRelease("spring-cloud-build", "1.0.0.M8"); + BDDMockito.then(this.saganClient).should(BDDMockito.never()) + .deleteRelease("spring-cloud-build", "2.0.0.M8"); then(this.gitHandler.issueCreatedInSpringGuides).isTrue(); } @@ -141,6 +172,12 @@ public class AcceptanceTests { BDDMockito.anyList()); BDDMockito.then(this.saganClient).should() .deleteRelease("spring-cloud-build", "1.2.2.BUILD-SNAPSHOT"); + BDDMockito.then(this.saganClient).should() + .deleteRelease("spring-cloud-build", "1.2.0.M8"); + BDDMockito.then(this.saganClient).should(BDDMockito.never()) + .deleteRelease("spring-cloud-build", "1.1.0.M8"); + BDDMockito.then(this.saganClient).should(BDDMockito.never()) + .deleteRelease("spring-cloud-build", "2.0.0.M8"); then(this.gitHandler.issueCreatedInSpringGuides).isTrue(); } @@ -181,6 +218,8 @@ public class AcceptanceTests { .contains("- Spring Cloud Bus `1.3.0.M1` ([issues](http://foo.bar.com/1.3.0.M1))"); BDDMockito.then(this.saganClient).should().updateRelease(BDDMockito.eq("spring-cloud-consul"), BDDMockito.anyList()); + BDDMockito.then(this.saganClient).should(BDDMockito.never()).deleteRelease( + BDDMockito.anyString(), BDDMockito.anyString()); // we update guides only for SR / RELEASE then(this.gitHandler.issueCreatedInSpringGuides).isFalse(); }