diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java index 6a7e61f2..4e501e12 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java @@ -241,4 +241,13 @@ public class Releaser { log.warn("\nUnable to update and generate release train documentation", e); } } + + public void updateAllSamples(Projects projects) { + try { + this.postReleaseActions.updateAllTestSamples(projects); + log.info("\nSuccessfully updated all samples"); + } catch (Exception e) { + log.warn("\nUnable to update all samples", e); + } + } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java index 38e1f675..a8ceae4c 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java @@ -238,6 +238,25 @@ public class ReleaserProperties implements Serializable { */ private boolean updateReleaseTrainDocs = true; + /** + * If set to {@code false}, will not clone and update the samples for all projects + */ + private boolean updateAllTestSamples = true; + + private Map> allTestSampleUrls = new HashMap>() { + { + this.put("spring-cloud-sleuth" , Arrays.asList( + "https://github.com/spring-cloud-samples/sleuth-issues/", + "https://github.com/spring-cloud-samples/sleuth-documentation-apps/") + ); + this.put("spring-cloud-contract" , Arrays.asList( + "https://github.com/spring-cloud-samples/spring-cloud-contract-samples/", + "https://github.com/spring-cloud-samples/the-legacy-app/", + "https://github.com/spring-cloud-samples/sc-contract-car-rental/") + ); + } + }; + public String getReleaseTrainBomUrl() { return this.releaseTrainBomUrl; } @@ -306,6 +325,14 @@ public class ReleaserProperties implements Serializable { return this.runUpdatedSamples; } + public boolean isUpdateAllTestSamples() { + return this.updateAllTestSamples; + } + + public void setUpdateAllTestSamples(boolean updateAllTestSamples) { + this.updateAllTestSamples = updateAllTestSamples; + } + public void setRunUpdatedSamples(boolean runUpdatedSamples) { this.runUpdatedSamples = runUpdatedSamples; } @@ -398,6 +425,14 @@ public class ReleaserProperties implements Serializable { this.updateReleaseTrainDocs = updateReleaseTrainDocs; } + public Map> getAllTestSampleUrls() { + return this.allTestSampleUrls; + } + + public void setAllTestSampleUrls(Map> allTestSampleUrls) { + this.allTestSampleUrls = allTestSampleUrls; + } + @Override public String toString() { return "Git{" + @@ -413,6 +448,7 @@ public class ReleaserProperties implements Serializable { ", numberOfCheckedMilestones=" + this.numberOfCheckedMilestones + ", updateSpringGuides=" + this.updateSpringGuides + ", updateSpringProject=" + this.updateSpringProject + + ", sampleUrlsSize=" + this.allTestSampleUrls.size() + '}'; } } @@ -612,7 +648,14 @@ public class ReleaserProperties implements Serializable { * version. Then it's enough to do the mapping like this for this Releaser's property: * {@code verifierVersion=spring-cloud-contract} */ - private Map gradlePropsSubstitution = new HashMap<>(); + private Map gradlePropsSubstitution = new HashMap() { + { + this.put("bootVersion", "spring-boot"); + this.put("BOOT_VERSION", "spring-boot"); + this.put("bomVersion", "spring-cloud-release"); + this.put("BOM_VERSION", "spring-cloud-release"); + } + }; /** * List of regular expressions of ignored gradle props. diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java index 8c4daf2f..1148caf6 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java @@ -146,7 +146,11 @@ class GitRepo { try(Git git = this.gitFactory.open(file(this.basedir))) { List refs = git.branchList().setListMode(ListBranchCommand.ListMode.ALL) .call(); - return refs.stream().anyMatch(ref -> branch.equals(nameOfBranch(ref.getName()))); + boolean present = refs.stream().anyMatch(ref -> branch.equals(nameOfBranch(ref.getName()))); + if (log.isDebugEnabled()) { + log.debug("Branch [{}] is present [{}]", branch, present); + } + return present; } catch (Exception e) { throw new IllegalStateException(e); } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java index 93639461..b42851e2 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java @@ -2,6 +2,7 @@ package org.springframework.cloud.release.internal.git; import java.io.File; import java.nio.file.Files; +import java.util.Arrays; import org.eclipse.jgit.transport.URIish; import org.slf4j.Logger; @@ -119,14 +120,44 @@ public class ProjectGitHandler implements ReleaserPropertiesAware { if (StringUtils.isEmpty(version)) { throw new IllegalStateException("You haven't provided a version for project [" + projectName + "]"); } - String branchFromVersion = branchFromVersion(version); - boolean branchExists = gitRepo(clonedProject).hasBranch(branchFromVersion); - if (!branchExists) { - log.info("Branch [{}] does not exist. Assuming that should work with master branch", branchFromVersion); + return findAndCheckOutBranchForVersion(clonedProject, new String[] { version }); + } + + + /** + * From the version analyzes the branch and checks it out. E.g. + * - for spring-cloud-release’s `Finchley.RELEASE version will resolve either Finchley + * branch or will fallback to master if there’s no Finchley branch + * - for spring-cloud-sleuth’s `2.1.0.RELEASE version will resolve 2.1.x branch + * + * @param url - of project to clone + * @param versions - list of versions to check against, if none matches, will fallback to master + * @return location of the cloned project + */ + public File cloneAndGuessBranch(String url, String... versions) { + File clonedProject = cloneProject(url); + if (log.isDebugEnabled()) { + log.debug("Successfully cloned the project to [{}]", clonedProject); + } + return findAndCheckOutBranchForVersion(clonedProject, versions); + } + + private File findAndCheckOutBranchForVersion(File clonedProject, String[] versions) { + if (log.isDebugEnabled()) { + log.debug("Checking versions {} for project [{}]", versions, clonedProject); + } + String branchToCheckout = Arrays.stream(versions) + .map(this::branchFromVersion) + .map(version -> gitRepo(clonedProject).hasBranch(version) ? version : "") + .filter(StringUtils::hasText) + .findFirst() + .orElse("master"); + if ("master".equals(branchToCheckout)) { + log.info("None of the versions {} matches a branch. Assuming that should work with master branch", (Object) versions); return clonedProject; } - log.info("Branch [{}] exists. Will check it out", branchFromVersion); - checkout(clonedProject, branchFromVersion); + log.info("Branch [{}] exists. Will check it out", branchToCheckout); + checkout(clonedProject, branchToCheckout); return clonedProject; } 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 e06960ce..5d1c7d3e 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 @@ -41,6 +41,19 @@ public class ProjectVersion { } public String bumpedVersion() { + return bumpedVersion(assertVersion()); + } + + private String bumpedVersion(String[] splitVersion) { + if (splitVersion.length == 2 && !isNumeric(splitVersion[0])) { + return this.version; + } + Integer incrementedPatch = Integer.valueOf(splitVersion[2]) + 1; + return String.format("%s.%s.%s.%s", splitVersion[0], splitVersion[1], incrementedPatch, splitVersion[3]); + } + + + private String[] assertVersion() { if (this.version == null) { throw new IllegalStateException("Version can't be null!"); } @@ -49,11 +62,26 @@ public class ProjectVersion { if (splitVersion.length < 4 && isNumeric(splitVersion[0])) { throw new IllegalStateException("Version is invalid. Should be of format [1.2.3.A]"); } - if (splitVersion.length == 2 && !isNumeric(splitVersion[0])) { - return this.version; + return splitVersion; + } + + /** + * For GA and SR will bump the snapshots + * in the rest of cases will return snapshot of the current version + * @return + */ + public String postReleaseSnapshotVersion() { + String[] strings = assertVersion(); + if (isReleaseOrServiceRelease()) { + String bumpedVersion = bumpedVersion(strings); + return appendBuildSnapshot(bumpedVersion); } - Integer incrementedPatch = Integer.valueOf(splitVersion[2]) + 1; - return String.format("%s.%s.%s.%s", splitVersion[0], splitVersion[1], incrementedPatch, splitVersion[3]); + return appendBuildSnapshot(this.version); + } + + private String appendBuildSnapshot(String bumpedVersion) { + int lastIndexOfDot = bumpedVersion.lastIndexOf("."); + return bumpedVersion.substring(0, lastIndexOfDot) + ".BUILD-SNAPSHOT"; } private boolean isNumeric(String string) { diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java index ba2974ed..5acba180 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java @@ -38,6 +38,24 @@ public class Projects extends HashSet { return super.add(projectVersion); } + public Projects filter(List projectsToSkip) { + return this.stream() + .filter(v -> !projectsToSkip.contains(v.projectName)) + .collect(Collectors.toCollection(Projects::new)); + } + + public Projects postReleaseSnapshotVersion(List projectsToSkip) { + Projects projects = this.stream() + .filter(v -> projectsToSkip.contains(v.projectName)) + .collect(Collectors.toCollection(Projects::new)); + Projects bumped = this.stream() + .map(v -> new ProjectVersion(v.projectName, v.postReleaseSnapshotVersion())) + .collect(Collectors.toCollection(Projects::new)); + Projects merged = new Projects(projects); + merged.addAll(bumped); + return merged; + } + public void remove(String projectName) { ProjectVersion projectVersion = forName(projectName); remove(projectVersion); diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java index ae72f32b..f298b377 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java @@ -1,6 +1,16 @@ package org.springframework.cloud.release.internal.post; +import java.io.Closeable; import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,10 +25,12 @@ import org.springframework.cloud.release.internal.project.ProjectBuilder; /** * @author Marcin Grzejszczak */ -public class PostReleaseActions { +public class PostReleaseActions implements Closeable { private static final Logger log = LoggerFactory.getLogger(PostReleaseActions.class); + private static final ExecutorService SERVICE = Executors.newCachedThreadPool(); + private final ProjectGitHandler projectGitHandler; private final ProjectPomUpdater projectPomUpdater; private final ProjectBuilder projectBuilder; @@ -55,6 +67,105 @@ public class PostReleaseActions { this.projectBuilder.build(projectVersion, file.getAbsolutePath()); } + /** + * Clones all samples for the given project. For each of them, checks out the proper + * branch, updates all the poms with the new, bumped versions of release train projects, + * commits the changes and pushes them. + * + * @param projects - set of project with versions to assert against + */ + public void updateAllTestSamples(Projects projects) { + if (!this.properties.getGit().isUpdateAllTestSamples() || + !this.properties.getMetaRelease().isEnabled()) { + log.info("Will not update all test samples, since the switch to do so " + + "is off. Set [releaser.git.update-all-test-samples] to [true] to change that"); + return; + } + List projectAndExceptions = this.properties.getGit() + .getAllTestSampleUrls() + .entrySet() + .stream() + .map(e -> updateAllProjects(projects, e)) + .map(this::getResult) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + log.info("Updated all samples!"); + List exceptionMessages = projectAndExceptions.stream() + .filter(ProjectAndException::hasException) + .map(e -> "Project [" + e.key + "] for url [" + e.url + "] has exception [" + e.ex + "]") + .collect(Collectors.toList()); + if (!exceptionMessages.isEmpty()) { + log.warn("Exceptions were found while updating samples"); + log.warn(String.join("\n", exceptionMessages)); + } else { + log.info("No exceptions were found while updating the samples"); + } + } + + private Future> updateAllProjects(Projects projects, Map.Entry> e) { + return SERVICE.submit(() -> { + String key = e.getKey(); + List value = e.getValue(); + log.info("Running version update for project [{}] and samples {}", key, value); + ProjectVersion projectVersionForReleaseTrain = projects.forName(key); + Projects postRelease = projects + .postReleaseSnapshotVersion(this.properties.getMetaRelease().getProjectsToSkip()); + log.info("Versions to update the samples with \n" + postRelease.stream() + .map(v -> "[" + v.projectName + ":" + v.version + "]") + .collect(Collectors.joining("\n"))); + return value.stream() + .map(url -> run(key, url, () -> + commitUpdatedProject(projects, key, projectVersionForReleaseTrain, postRelease, url))) + .map(this::getResult) + .collect(Collectors.toList()); + }); + } + + private void commitUpdatedProject(Projects projects, String key, ProjectVersion projectVersionForReleaseTrain, Projects postRelease, String url) { + String releaseTrainVersion = projects + .forName(this.properties.getMetaRelease().getReleaseTrainProjectName()).version; + String projectVersion = projects.forName(key).version; + log.info("Running version update for project [{}], url [{}], " + + "release train version [{}] and project version [{}]", key, url, + releaseTrainVersion, projectVersion); + File file = this.projectGitHandler + .cloneAndGuessBranch(url, releaseTrainVersion, projectVersion); + Projects newPostRelease = new Projects(postRelease); + newPostRelease.add(new ProjectVersion(file)); + this.projectPomUpdater + .updateProjectFromReleaseTrain(file, newPostRelease, + new ProjectVersion(file), false); + this.projectGitHandler + .commit(file, "Updated versions after [" + releaseTrainVersion + "] " + + "release train and [" + projectVersionForReleaseTrain.version + "] [" + + key + "] project release"); + } + + private ProjectAndFuture run(String key, String url, Runnable runnable) { + return new ProjectAndFuture(key, url, SERVICE.submit(runnable)); + } + + private ProjectAndException getResult(ProjectAndFuture projectAndFuture) { + Exception e = null; + try { + projectAndFuture.future.get(10, TimeUnit.MINUTES); + log.info("Done!"); + } + catch (Exception ex) { + e = ex; + } + return new ProjectAndException(projectAndFuture.key, projectAndFuture.url, e); + } + + private List getResult(Future> future) { + try { + return future.get(10, TimeUnit.MINUTES); + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + /** * Clones the release train documentation project * @@ -83,4 +194,38 @@ public class PostReleaseActions { newProjects.add(new ProjectVersion(projectVersion.projectName, releaseTrainVersion)); return newProjects; } + + @Override + public void close() throws IOException { + SERVICE.shutdown(); + } } + + +class ProjectAndFuture { + final String key; + final String url; + final Future future; + + ProjectAndFuture(String key, String url, Future future) { + this.key = key; + this.url = url; + this.future = future; + } +} + +class ProjectAndException { + final String key; + final String url; + final Exception ex; + + ProjectAndException(String key, String url, Exception ex) { + this.key = key; + this.url = url; + this.ex = ex; + } + + boolean hasException() { + return ex != null; + } +} \ No newline at end of file diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java index c93076dd..f677416f 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java @@ -106,7 +106,7 @@ public class ProjectGitHandlerTests { this.updater.cloneProjectFromOrg("spring-cloud-sleuth"); - then(this.gitRepo).should(never()).checkout(anyString()); + then(this.gitRepo).should(never()).checkout("2.3.x"); } @Test @@ -131,6 +131,47 @@ public class ProjectGitHandlerTests { then(this.gitRepo).should().checkout("Finchley"); } + @Test + public void should_not_check_out_a_branch_if_it_does_not_exist_when_cloning_and_guessing_branch() { + given(this.gitRepo.hasBranch(anyString())).willReturn(true); + given(this.gitRepo.hasBranch("2.3.x")).willReturn(false); + + this.updater.cloneAndGuessBranch(new File(".").getAbsolutePath(), "2.3.4.RELEASE"); + + then(this.gitRepo).should(never()).checkout("2.3.x"); + } + + @Test + public void should_check_out_a_branch_if_it_exists_when_cloning_and_guessing_branch() { + given(this.gitRepo.hasBranch(anyString())).willReturn(false); + given(this.gitRepo.hasBranch("2.3.x")).willReturn(true); + + this.updater.cloneAndGuessBranch(new File(".").getAbsolutePath(), "2.3.4.RELEASE"); + + then(this.gitRepo).should().checkout("2.3.x"); + } + + @Test + public void should_check_out_a_branch_if_it_exists_when_cloning_and_guessing_release_train_branch() { + given(this.gitRepo.hasBranch(anyString())).willReturn(false); + given(this.gitRepo.hasBranch("Finchley")).willReturn(true); + + this.updater.cloneAndGuessBranch(new File(".").getAbsolutePath(), "Finchley.SR6"); + + then(this.gitRepo).should().checkout("Finchley"); + } + + @Test + public void should_check_out_a_branch_if_one_of_it_exists() { + given(this.gitRepo.hasBranch(anyString())).willReturn(false); + given(this.gitRepo.hasBranch("Finchley")).willReturn(true); + + this.updater.cloneAndGuessBranch(new File(".").getAbsolutePath(), "2.0.0.RELEASE", "Finchley.SR6"); + + then(this.gitRepo).should(never()).checkout("2.0.0"); + then(this.gitRepo).should().checkout("Finchley"); + } + private ProjectVersion projectVersion(String version) { return new ProjectVersion("foo", version); } 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 5a123bd3..4d79e9b5 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 @@ -89,6 +89,49 @@ public class ProjectVersionTests { then(projectVersion(version).bumpedVersion()).isEqualTo("Edgware.BUILD-SNAPSHOT"); } + @Test + public void should_throw_exception_if_version_is_not_long_enough_when_bumping_snapshots() { + String version = "1.0"; + + thenThrownBy(() -> projectVersion(version).postReleaseSnapshotVersion()) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Version is invalid"); + } + + @Test + public void should_not_bump_version_by_patch_version_when_non_ga_or_sr() { + then(projectVersion("1.0.1.BUILD-SNAPSHOT").postReleaseSnapshotVersion()).isEqualTo("1.0.1.BUILD-SNAPSHOT"); + then(projectVersion("1.0.1.M1").postReleaseSnapshotVersion()).isEqualTo("1.0.1.BUILD-SNAPSHOT"); + then(projectVersion("1.0.1.RC1").postReleaseSnapshotVersion()).isEqualTo("1.0.1.BUILD-SNAPSHOT"); + then(projectVersion("Finchley.SR1").postReleaseSnapshotVersion()).isEqualTo("Finchley.BUILD-SNAPSHOT"); + } + + @Test + public void should_bump_version_by_patch_version_when_bumping_snapshots_for_ga() { + then(projectVersion("1.0.1.RELEASE").postReleaseSnapshotVersion()).isEqualTo("1.0.2.BUILD-SNAPSHOT"); + } + + @Test + public void should_return_the_previous_version_for_release_train_version_when_bumping_snapshots() { + String version = "Edgware.BUILD-SNAPSHOT"; + + then(projectVersion(version).postReleaseSnapshotVersion()).isEqualTo("Edgware.BUILD-SNAPSHOT"); + } + + @Test + public void should_bump_version_by_patch_version_when_bumping_releases() { + String version = "1.0.1.RELEASE"; + + then(projectVersion(version).postReleaseSnapshotVersion()).isEqualTo("1.0.2.BUILD-SNAPSHOT"); + } + + @Test + public void should_return_the_previous_version_for_release_train_version_when_bumping_releases() { + String version = "Edgware.RELEASE"; + + then(projectVersion(version).postReleaseSnapshotVersion()).isEqualTo("Edgware.BUILD-SNAPSHOT"); + } + @Test public void should_return_true_for_snapshot_version() { String version = "1.0.1.BUILD-SNAPSHOT"; diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java index 5174120f..0c36a3fc 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java @@ -5,6 +5,7 @@ import static org.assertj.core.api.BDDAssertions.thenThrownBy; import java.io.File; import java.net.URISyntaxException; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -104,6 +105,41 @@ public class ProjectsTests { then(projects.containsSnapshots()).isFalse(); } + @Test + public void should_return_filtered_project() { + Set projectVersions = new HashSet<>(); + projectVersions.add(new ProjectVersion("foo", "1.0.0")); + projectVersions.add(new ProjectVersion("bar", "1.0.0")); + Projects projects = new Projects(projectVersions); + + Projects filtered = projects.filter(Collections.singletonList("foo")); + then(filtered).hasSize(1); + then(filtered.forName("bar").version).isEqualTo("1.0.0"); + } + + @Test + public void should_return_projects_with_bumped_versions() { + Set projectVersions = new HashSet<>(); + projectVersions.add(new ProjectVersion("dont_touch", "2.0.0.RELEASE")); + projectVersions.add(new ProjectVersion("foo", "1.0.0.RELEASE")); + projectVersions.add(new ProjectVersion("bar", "1.0.1.M1")); + projectVersions.add(new ProjectVersion("baz", "1.0.2.BUILD-SNAPSHOT")); + projectVersions.add(new ProjectVersion("foo2", "1.0.0.SR1")); + projectVersions.add(new ProjectVersion("foo3", "Finchley.BUILD-SNAPSHOT")); + projectVersions.add(new ProjectVersion("foo4", "Finchley.SR4")); + Projects projects = new Projects(projectVersions); + + Projects bumped = projects.postReleaseSnapshotVersion(Collections.singletonList("dont_touch")); + + then(bumped.forName("dont_touch").version).isEqualTo("2.0.0.RELEASE"); + then(bumped.forName("foo").version).isEqualTo("1.0.1.BUILD-SNAPSHOT"); + then(bumped.forName("bar").version).isEqualTo("1.0.1.BUILD-SNAPSHOT"); + then(bumped.forName("baz").version).isEqualTo("1.0.2.BUILD-SNAPSHOT"); + then(bumped.forName("foo2").version).isEqualTo("1.0.1.BUILD-SNAPSHOT"); + then(bumped.forName("foo3").version).isEqualTo("Finchley.BUILD-SNAPSHOT"); + then(bumped.forName("foo4").version).isEqualTo("Finchley.BUILD-SNAPSHOT"); + } + @Test public void should_throw_exception_when_project_is_not_present_when_searching_by_file() { Set projectVersions = new HashSet<>(); diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java index 22beb1e9..2da2d591 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java @@ -2,9 +2,17 @@ package org.springframework.cloud.release.internal.post; import java.io.File; import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import org.apache.maven.model.Model; import org.assertj.core.api.BDDAssertions; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -12,6 +20,7 @@ import org.junit.rules.TemporaryFolder; import org.springframework.cloud.release.internal.PomUpdateAcceptanceTests; import org.springframework.cloud.release.internal.ReleaserProperties; +import org.springframework.cloud.release.internal.git.GitTestUtils; import org.springframework.cloud.release.internal.git.ProjectGitHandler; import org.springframework.cloud.release.internal.pom.ProjectPomUpdater; import org.springframework.cloud.release.internal.pom.ProjectVersion; @@ -20,6 +29,7 @@ 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.util.FileSystemUtils; +import org.springframework.util.LinkedMultiValueMap; /** * @author Marcin Grzejszczak @@ -32,6 +42,7 @@ public class PostReleaseActionsTests { TestPomReader testPomReader = new TestPomReader(); ReleaserProperties properties = new ReleaserProperties(); File cloned; + LinkedMultiValueMap clonedTestProjects = new LinkedMultiValueMap<>(); ProjectGitHandler projectGitHandler = new ProjectGitHandler(this.properties) { @Override public File cloneTestSamplesProject() { @@ -44,6 +55,13 @@ public class PostReleaseActionsTests { cloned = super.cloneTestSamplesProject(); return cloned; } + + @Override + public File cloneAndGuessBranch(String url, String... versions) { + File file = super.cloneAndGuessBranch(url, versions); + clonedTestProjects.add(url, file); + return file; + } }; ProjectPomUpdater updater = new ProjectPomUpdater(this.properties); ProjectBuilder builder = new ProjectBuilder(this.properties); @@ -133,6 +151,55 @@ public class PostReleaseActionsTests { BDDAssertions.then(new File(cloned, "generate.log")).exists(); } + @Test + public void should_do_nothing_when_is_not_meta_release_and_test_samples_update_is_called() { + this.properties.getMetaRelease().setEnabled(false); + PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, + this.updater, this.builder, this.properties); + + actions.updateAllTestSamples(currentGa()); + + BDDAssertions.then(cloned).isNull(); + } + + @Test + public void should_do_nothing_when_the_switch_for_test_samples_update_check_is_off_and_test_samples_update_is_called() { + this.properties.getGit().setUpdateReleaseTrainDocs(false); + PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, + this.updater, this.builder, this.properties); + + actions.updateAllTestSamples(currentGa()); + + BDDAssertions.then(cloned).isNull(); + } + + @Test + public void should_update_test_sample_projects_when_test_samples_update_is_called() throws Exception { + this.properties.getMetaRelease().setEnabled(true); + this.properties.getGit().getAllTestSampleUrls().clear(); + this.properties.getGit().getAllTestSampleUrls().put("spring-cloud-sleuth", + Collections.singletonList(tmpFile("spring-cloud-core-tests/") + .getAbsolutePath() + "/")); + PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, + this.updater, this.builder, this.properties); + + actions.updateAllTestSamples(currentGa()); + + Map.Entry> entry = clonedTestProjects.entrySet() + .stream() + .filter(s -> s.getKey().contains("spring-cloud-core-tests")) + .findFirst().orElseThrow(() -> new IllegalStateException("Not found")); + File clonedFile = entry.getValue().get(0); + Model pomWithCloud = this.testPomReader.readPom(new File(clonedFile, "zuul-proxy-eureka/pom.xml")); + Git git = GitTestUtils.openGitProject(clonedFile); + BDDAssertions.then(pomWithCloud.getProperties().getProperty("spring-cloud.version")).isEqualTo("Finchley.BUILD-SNAPSHOT"); + BDDAssertions.then(pomWithCloud.getParent().getVersion()).isEqualTo("2.0.4.RELEASE"); + Iterator iterator = git.log().call().iterator(); + RevCommit commit = iterator.next(); + BDDAssertions.then(commit.getShortMessage()) + .isEqualTo("Updated versions after [Finchley.SR1] release train and [2.0.1.RELEASE] [spring-cloud-sleuth] project release"); + } + private String sleuthParentPomVersion() { return this.testPomReader.readPom(new File(cloned, "sleuth/pom.xml")) .getParent().getVersion(); diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java index 4118cf9f..b9c3911f 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java @@ -89,6 +89,12 @@ class Tasks { args -> { args.releaser.generateReleaseTrainDocumentation(args.projects); },TaskType.POST_RELEASE); + static Task UPDATE_ALL_SAMPLES = task("updateAllSamples", "ua", + "UPDATE ALL SAMPLES WITH RELEASE TRAIN BUMPED VERSIONS", + "Update all samples with release train bumped versions", + args -> { + args.releaser.updateAllSamples(args.projects); + },TaskType.POST_RELEASE); static final List DEFAULT_TASKS_PER_PROJECT = Stream.of( Tasks.UPDATING_POMS, @@ -108,7 +114,8 @@ class Tasks { Tasks.UPDATE_GUIDES, Tasks.UPDATE_RELEASE_TRAIN_DOCUMENTATION, Tasks.UPDATE_DOCUMENTATION, - Tasks.UPDATE_SPRING_PROJECT_PAGE + Tasks.UPDATE_SPRING_PROJECT_PAGE, + Tasks.UPDATE_ALL_SAMPLES ).collect(Collectors.toList()); static final List NON_COMPOSITE_TASKS = new ArrayList() {