From 9932ff96691fd3c8c1db1d207ea5033b8c6e01dd Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 7 May 2019 14:06:12 +0200 Subject: [PATCH] WIP --- .../cloud/release/internal/Releaser.java | 23 ++++-- .../release/internal/ReleaserProperties.java | 13 ++++ .../cloud/release/internal/git/GitRepo.java | 32 +++++++- .../internal/git/ProjectGitHandler.java | 6 +- .../internal/pom/ProcessedProject.java | 60 +++++++++++++++ .../release/internal/pom/ProjectVersion.java | 11 +++ .../internal/post/PostReleaseActions.java | 55 +++++++++++++- .../internal/project/ProjectBuilder.java | 38 ++++++---- .../internal/pom/ProjectVersionTests.java | 10 +++ .../post/PostReleaseActionsTests.java | 20 ++--- .../cloud/release/internal/spring/Args.java | 15 +++- .../spring/ReleaserConfiguration.java | 2 +- .../spring/ReleaserPropertiesUpdater.java | 1 + .../internal/spring/SpringReleaser.java | 76 +++++++++++++------ .../cloud/release/internal/spring/Tasks.java | 2 +- .../internal/spring/SpringReleaserTests.java | 3 +- 16 files changed, 299 insertions(+), 68 deletions(-) create mode 100644 spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProcessedProject.java 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 b333e79f..fa0f551a 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 @@ -17,6 +17,7 @@ package org.springframework.cloud.release.internal; import java.io.File; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +25,7 @@ import org.slf4j.LoggerFactory; import org.springframework.cloud.release.internal.docs.DocumentationUpdater; import org.springframework.cloud.release.internal.git.ProjectGitHandler; import org.springframework.cloud.release.internal.gradle.GradleUpdater; +import org.springframework.cloud.release.internal.pom.ProcessedProject; import org.springframework.cloud.release.internal.pom.ProjectPomUpdater; import org.springframework.cloud.release.internal.pom.ProjectVersion; import org.springframework.cloud.release.internal.pom.Projects; @@ -103,9 +105,8 @@ public class Releaser { log.info("\n\nProject was successfully updated to [{}]", changedVersion); } - public void buildProject(ProjectVersion versionFromScRelease, - ProjectBuilder.MavenProfile... profiles) { - this.projectBuilder.build(versionFromScRelease, profiles); + public void buildProject(ProjectVersion versionFromScRelease) { + this.projectBuilder.build(versionFromScRelease); log.info("\nProject was successfully built"); } @@ -214,18 +215,28 @@ public class Releaser { } } - public void updateSpringGuides(ProjectVersion releaseVersion, Projects projects) { + public void updateSpringGuides(ProjectVersion releaseVersion, Projects projects, + List processedProjects) { if (!(releaseVersion.isRelease() || releaseVersion.isServiceRelease())) { log.info( "\nWon't update Spring Guides for a non Release / Service Release version"); return; } + createIssueInSpringGuides(releaseVersion, projects); try { this.projectGitHandler.createIssueInSpringGuides(projects, releaseVersion); } catch (Exception ex) { - throw new MakeBuildUnstableException( - "Successfully updated Spring Guides issues", ex); + throw new MakeBuildUnstableException("Failed to update Spring Guides", ex); + } + } + + private void createIssueInSpringGuides(ProjectVersion releaseVersion, Projects projects) { + try { + this.projectGitHandler.createIssueInSpringGuides(projects, releaseVersion); + } + catch (Exception ex) { + throw new MakeBuildUnstableException("Failed to update Spring Guides", ex); } } 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 f4430730..c73441f2 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 @@ -725,6 +725,11 @@ public class ReleaserProperties implements Serializable { */ private String deployCommand = "./mvnw deploy -DskipTests -B -Pfast,deploy {{systemProps}}"; + /** + * Command to be executed to build and deploy guides project only. + */ + private String deployGuidesCommand = "./mvnw clean verify deploy -B -Pguides,integration -pl guides {{systemProps}}"; + /** * Command to be executed to publish documentation. If present "{{version}}" will * be replaced by the provided version. @@ -777,6 +782,14 @@ public class ReleaserProperties implements Serializable { this.deployCommand = deployCommand; } + public String getDeployGuidesCommand() { + return this.deployGuidesCommand; + } + + public void setDeployGuidesCommand(String deployGuidesCommand) { + this.deployGuidesCommand = deployGuidesCommand; + } + public String[] getPublishDocsCommands() { return this.publishDocsCommands; } 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 7edca6d2..ba0fd7e1 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 @@ -38,6 +38,7 @@ import org.eclipse.jgit.api.FetchCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.eclipse.jgit.api.PushCommand; +import org.eclipse.jgit.api.ResetCommand; import org.eclipse.jgit.api.TransportConfigCallback; import org.eclipse.jgit.api.errors.EmtpyCommitException; import org.eclipse.jgit.api.errors.GitAPIException; @@ -129,7 +130,7 @@ class GitRepo { } /** - * Pull changes. + * Fetch changes. */ void fetch() { try { @@ -142,6 +143,20 @@ class GitRepo { } } + /** + * Reset changes. + */ + void reset() { + try { + log.info("Resetting changes for repo [{}]", this.basedir); + reset(this.basedir); + log.info("Successfully reset any changes"); + } + catch (Exception e) { + throw new IllegalStateException(e); + } + } + /** * Performs a commit. * @param message - commit message @@ -313,6 +328,21 @@ class GitRepo { } } + private Ref reset(File projectDir) throws GitAPIException { + Git git = this.gitFactory.open(projectDir); + ResetCommand command = git.reset().setMode(ResetCommand.ResetType.HARD); + try { + return command.call(); + } + catch (GitAPIException e) { + deleteBaseDirIfExists(); + throw e; + } + finally { + git.close(); + } + } + private Ref checkoutBranch(File projectDir, String branch) throws GitAPIException { Git git = this.gitFactory.open(projectDir); CheckoutCommand command = git.checkout().setName(branch); 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 8dead480..00a398ae 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 @@ -200,11 +200,13 @@ public class ProjectGitHandler implements ReleaserPropertiesAware { File cloneProject(String url) { try { URIish urIish = new URIish(url); - // retrieve from cache and fetch if from cache + // retrieve from cache + // reset any changes and fetch the latest data File clonedProject = CACHE.get(urIish); if (clonedProject != null) { log.info( - "Project has already been cloned. Will fetch the latest changes and return the cached location"); + "Project has already been cloned. Will reset the current branch and fetch the latest changes."); + gitRepo(clonedProject).reset(); gitRepo(clonedProject).fetch(); return clonedProject; } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProcessedProject.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProcessedProject.java new file mode 100644 index 00000000..c4072a88 --- /dev/null +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProcessedProject.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013-2019 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.cloud.release.internal.pom; + +import org.springframework.cloud.release.internal.ReleaserProperties; + +/** + * Represents a processed project. + * + * @author Marcin Grzejszczak + */ +public class ProcessedProject { + + /** + * Updated properties for a given project. When doing a meta-release this will + * represent a merge of the global properties with the per-application ones. For + * non-meta-release these will be the application properties. + */ + public final ReleaserProperties propertiesForProject; + + /** + * Version to which the project should be updated. + */ + public final ProjectVersion newProjectVersion; + + public ProcessedProject(ReleaserProperties propertiesForProject, + ProjectVersion newProjectVersion) { + this.propertiesForProject = propertiesForProject; + this.newProjectVersion = newProjectVersion; + } + + @Override + public String toString() { + return "ProcessedProject{" + "name=" + projectName() + ",version=" + + projectVersion() + '}'; + } + + public String projectName() { + return this.newProjectVersion.projectName; + } + + private String projectVersion() { + return this.newProjectVersion.version; + } + +} 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 62381b99..8fdf8c96 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 @@ -232,6 +232,17 @@ public class ProjectVersion implements Comparable { .compareTo(new TrainVersionNumber(thatValue)); } + /** + * Returns the release tag name. + * @return tag name or empty if non ga or sr. + */ + public String releaseTagName() { + if (isReleaseOrServiceRelease()) { + return "v" + this.version; + } + return ""; + } + @Override public String toString() { return this.version; 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 d4c17989..5415c579 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 @@ -34,10 +34,12 @@ import org.slf4j.LoggerFactory; import org.springframework.cloud.release.internal.ReleaserProperties; import org.springframework.cloud.release.internal.git.ProjectGitHandler; import org.springframework.cloud.release.internal.gradle.GradleUpdater; +import org.springframework.cloud.release.internal.pom.ProcessedProject; import org.springframework.cloud.release.internal.pom.ProjectPomUpdater; import org.springframework.cloud.release.internal.pom.ProjectVersion; import org.springframework.cloud.release.internal.pom.Projects; import org.springframework.cloud.release.internal.project.ProjectBuilder; +import org.springframework.cloud.release.internal.versions.VersionsFetcher; import org.springframework.core.NestedExceptionUtils; import org.springframework.util.StringUtils; @@ -60,14 +62,41 @@ public class PostReleaseActions implements Closeable { private final ReleaserProperties properties; + private final VersionsFetcher versionsFetcher; + public PostReleaseActions(ProjectGitHandler projectGitHandler, ProjectPomUpdater projectPomUpdater, GradleUpdater gradleUpdater, - ProjectBuilder projectBuilder, ReleaserProperties properties) { + ProjectBuilder projectBuilder, ReleaserProperties properties, + VersionsFetcher versionsFetcher) { this.projectGitHandler = projectGitHandler; this.projectPomUpdater = projectPomUpdater; this.gradleUpdater = gradleUpdater; this.projectBuilder = projectBuilder; this.properties = properties; + this.versionsFetcher = versionsFetcher; + } + + /** + * Clones the projects, checks out the proper branch and runs guides building and + * deployment. + * @param processedProjects - set of project with versions to assert against + */ + public void deployGuides(List processedProjects) { + if (!this.properties.getGit().isUpdateSpringGuides()) { + log.info( + "Will not build and deploy latest Spring Guides, since the switch to do so " + + "is off. Set [releaser.git.update-spring-guides] to [true] to change that"); + return; + } + List latestGaProcessedProjects = processedProjects.stream() + .filter(processedProject -> this.versionsFetcher + .isLatestGa(processedProject.newProjectVersion)) + .collect(Collectors.toList()); + log.info("Found the following latest ga processed projects " + + latestGaProcessedProjects); + List projectUrlAndExceptions = runDeployGuides(latestGaProcessedProjects); + log.info("Deployed all guides!"); + assertExceptions(projectUrlAndExceptions); } /** @@ -108,6 +137,10 @@ public class PostReleaseActions implements Closeable { .map(e -> updateAllProjects(projects, e)).map(this::getResult) .flatMap(Collection::stream).collect(Collectors.toList()); log.info("Updated all samples!"); + assertExceptions(projectUrlAndExceptions); + } + + private void assertExceptions(List projectUrlAndExceptions) { String exceptionMessages = projectUrlAndExceptions.stream() .filter(ProjectUrlAndException::hasException) .map(e -> "Project [" + e.key + "] for url [" + e.url + "] " @@ -126,6 +159,22 @@ public class PostReleaseActions implements Closeable { } } + private List runDeployGuides( + List latestGaProcessedProjects) { + return latestGaProcessedProjects.stream().map( + processedProject -> run(processedProject.projectName(), "", () -> SERVICE.submit(() -> { + String tagName = processedProject.newProjectVersion + .releaseTagName(); + File clonedProject = this.projectGitHandler + .cloneProjectFromOrg(processedProject.projectName()); + this.projectGitHandler.checkout(clonedProject, tagName); + new ProjectBuilder(processedProject.propertiesForProject) + .deployGuides(processedProject.newProjectVersion); + }))) + .map(this::getSingleResult) + .collect(Collectors.toList()); + } + private Future> updateAllProjects(Projects projects, Map.Entry> e) { return SERVICE.submit(() -> { @@ -142,7 +191,7 @@ public class PostReleaseActions implements Closeable { .map(url -> run(key, url, () -> commitUpdatedProject(projects, key, projectVersionForReleaseTrain, postRelease, url))) - .map(this::getResult).collect(Collectors.toList()); + .map(this::getSingleResult).collect(Collectors.toList()); }); } @@ -201,7 +250,7 @@ public class PostReleaseActions implements Closeable { return new ProjectAndFuture(key, url, SERVICE.submit(runnable)); } - private ProjectUrlAndException getResult(ProjectAndFuture projectAndFuture) { + private ProjectUrlAndException getSingleResult(ProjectAndFuture projectAndFuture) { Exception e = null; try { projectAndFuture.future.get(10, TimeUnit.MINUTES); diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java index 09c853ca..d1fd189f 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java @@ -47,7 +47,7 @@ public class ProjectBuilder implements ReleaserPropertiesAware { /** * Enumeration over commonly used Maven profiles. */ - public enum MavenProfile { + private enum Profile { /** * Profile used for milestone versions. @@ -89,16 +89,14 @@ public class ProjectBuilder implements ReleaserPropertiesAware { this.properties = properties; } - public void build(ProjectVersion versionFromReleaseTrain, MavenProfile... profiles) { - build(versionFromReleaseTrain, this.properties.getWorkingDir(), profiles); + public void build(ProjectVersion versionFromReleaseTrain) { + build(versionFromReleaseTrain, this.properties.getWorkingDir()); } - public void build(ProjectVersion versionFromReleaseTrain, String projectRoot, - MavenProfile... profiles) { + public void build(ProjectVersion versionFromReleaseTrain, String projectRoot) { try { String[] commands = commandWithSystemProps( - this.properties.getMaven().getBuildCommand(), versionFromReleaseTrain, - profiles).split(" "); + this.properties.getMaven().getBuildCommand(), versionFromReleaseTrain).split(" "); runCommand(projectRoot, commands); assertNoHtmlFilesInDocsContainUnresolvedTags(projectRoot); log.info("No HTML files from docs contain unresolved tags"); @@ -123,7 +121,7 @@ public class ProjectBuilder implements ReleaserPropertiesAware { } private String commandWithSystemProps(String command, ProjectVersion version, - MavenProfile... profiles) { + Profile... profiles) { if (command.contains(ReleaserProperties.Maven.SYSTEM_PROPS_PLACEHOLDER)) { return appendProfile(command, version, profiles); } @@ -132,16 +130,16 @@ public class ProjectBuilder implements ReleaserPropertiesAware { } private String appendProfile(String command, ProjectVersion version, - MavenProfile... profiles) { + Profile... profiles) { String trimmedCommand = command.trim(); if (version.isMilestone() || version.isRc()) { log.info("Adding the milestone profile to the Maven build"); - return trimmedCommand + " " + MavenProfile.MILESTONE.asMavenProfile() + return trimmedCommand + " " + Profile.MILESTONE.asMavenProfile() + profilesToString(profiles); } else if (version.isRelease() || version.isServiceRelease()) { log.info("Adding the central profile to the Maven build"); - return trimmedCommand + " " + MavenProfile.CENTRAL.asMavenProfile() + return trimmedCommand + " " + Profile.CENTRAL.asMavenProfile() + profilesToString(profiles); } else { @@ -150,7 +148,7 @@ public class ProjectBuilder implements ReleaserPropertiesAware { return trimmedCommand; } - private String profilesToString(MavenProfile... profiles) { + private String profilesToString(Profile... profiles) { return Arrays.stream(profiles).map(profile -> "-P" + profile) .collect(Collectors.joining(" ")); } @@ -168,11 +166,19 @@ public class ProjectBuilder implements ReleaserPropertiesAware { } } - public void deploy(ProjectVersion version, MavenProfile... profiles) { + public void deploy(ProjectVersion version) { + doDeploy(version, this.properties.getMaven().getDeployCommand()); + } + + public void deployGuides(ProjectVersion version) { + doDeploy(version, this.properties.getMaven().getDeployGuidesCommand(), Profile.GUIDES, Profile.INTEGRATION); + } + + private void doDeploy(ProjectVersion version, String command, + Profile... profiles) { try { - String[] commands = commandWithSystemProps( - this.properties.getMaven().getDeployCommand(), version, profiles) - .split(" "); + String[] commands = commandWithSystemProps(command, version, profiles) + .split(" "); runCommand(commands); log.info("The project has successfully been deployed"); } 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 9462f85c..592f00cd 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 @@ -463,6 +463,16 @@ public class ProjectVersionTests { unknownTypeOfVersion); } + @Test + public void should_return_v100RELEASE_when_tag_name_is_requested() { + then(projectVersion("1.0.0.RELEASE").releaseTagName()).isEqualTo("v1.0.0.RELEASE"); + } + + @Test + public void should_return_empty_when_tag_name_is_non_ga() { + then(projectVersion("1.0.0.BUILD-SNAPSHOT").releaseTagName()).isEmpty(); + } + private void thenPatternsForSnapshotMilestoneAndReleaseCandidateArePresent( List unknownTypeOfVersion) { then(unknownTypeOfVersion).isNotEmpty(); 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 9d3d2150..5ceb4a02 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 @@ -107,7 +107,7 @@ public class PostReleaseActionsTests { public void should_do_nothing_when_is_not_meta_release_and_update_test_is_called() { this.properties.getMetaRelease().setEnabled(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.runUpdatedTests(currentGa()); @@ -119,7 +119,7 @@ public class PostReleaseActionsTests { public void should_do_nothing_when_the_switch_for_sample_check_is_off_and_update_test_is_called() { this.properties.getGit().setRunUpdatedSamples(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.runUpdatedTests(currentGa()); @@ -134,7 +134,7 @@ public class PostReleaseActionsTests { tmpFile("spring-cloud-core-tests/").getAbsolutePath() + "/"); this.properties.getMaven().setBuildCommand("touch build.log"); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.runUpdatedTests(currentGa()); @@ -156,7 +156,7 @@ public class PostReleaseActionsTests { public void should_do_nothing_when_is_not_meta_release_and_release_train_docs_generation_is_called() { this.properties.getMetaRelease().setEnabled(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.generateReleaseTrainDocumentation(currentGa()); @@ -167,7 +167,7 @@ public class PostReleaseActionsTests { public void should_do_nothing_when_the_switch_for_sample_check_is_off_and_release_train_docs_generation_is_called() { this.properties.getGit().setUpdateReleaseTrainDocs(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.generateReleaseTrainDocumentation(currentGa()); @@ -182,7 +182,7 @@ public class PostReleaseActionsTests { this.properties.getMaven() .setGenerateReleaseTrainDocsCommand("touch generate.log"); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.generateReleaseTrainDocumentation(currentGa()); @@ -198,7 +198,7 @@ public class PostReleaseActionsTests { 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.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.updateAllTestSamples(currentGa()); @@ -210,7 +210,7 @@ public class PostReleaseActionsTests { public void should_do_nothing_when_the_switch_for_test_samples_update_check_is_off_and_update_is_called() { this.properties.getGit().setUpdateReleaseTrainDocs(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties); + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher); actions.updateAllTestSamples(currentGa()); @@ -228,7 +228,7 @@ public class PostReleaseActionsTests { tmpFile("spring-cloud-core-tests/").getAbsolutePath() + "/")); AtomicReference postReleaseProjects = new AtomicReference<>(); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties) { + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher) { @Override Projects getPostReleaseProjects(Projects projects) { postReleaseProjects.set(super.getPostReleaseProjects(projects)); @@ -270,7 +270,7 @@ public class PostReleaseActionsTests { tmpFile("spring-cloud-static/").getAbsolutePath() + "/")); AtomicReference postReleaseProjects = new AtomicReference<>(); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.gradleUpdater, this.builder, this.properties) { + this.updater, this.gradleUpdater, this.builder, this.properties, versionsFetcher) { @Override Projects getPostReleaseProjects(Projects projects) { postReleaseProjects.set(super.getPostReleaseProjects(projects)); diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java index 222f8e9d..24ae59d7 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java @@ -17,12 +17,15 @@ package org.springframework.cloud.release.internal.spring; import java.io.File; +import java.util.Collections; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.release.internal.Releaser; import org.springframework.cloud.release.internal.ReleaserProperties; +import org.springframework.cloud.release.internal.pom.ProcessedProject; import org.springframework.cloud.release.internal.pom.ProjectVersion; import org.springframework.cloud.release.internal.pom.Projects; import org.springframework.context.ApplicationEvent; @@ -47,6 +50,8 @@ class Args { final ReleaserProperties properties; + final List processedProjects; + final boolean interactive; final TaskType taskType; @@ -63,6 +68,8 @@ class Args { this.originalVersion = originalVersion; this.versionFromScRelease = versionFromScRelease; this.properties = properties; + this.processedProjects = Collections + .singletonList(new ProcessedProject(properties, versionFromScRelease)); this.interactive = interactive; this.taskType = taskType; this.applicationEventPublisher = applicationEventPublisher; @@ -70,14 +77,15 @@ class Args { // Used by meta-release task Args(Releaser releaser, Projects projects, ProjectVersion versionFromScRelease, - ReleaserProperties properties, boolean interactive, - ApplicationEventPublisher applicationEventPublisher) { + ReleaserProperties properties, List processedProjects, + boolean interactive, ApplicationEventPublisher applicationEventPublisher) { this.releaser = releaser; this.project = null; this.projects = projects; this.originalVersion = null; this.versionFromScRelease = versionFromScRelease; this.properties = properties; + this.processedProjects = processedProjects; this.interactive = interactive; this.taskType = TaskType.POST_RELEASE; this.applicationEventPublisher = applicationEventPublisher; @@ -91,6 +99,7 @@ class Args { this.originalVersion = null; this.versionFromScRelease = null; this.properties = null; + this.processedProjects = Collections.emptyList(); this.interactive = false; this.taskType = taskType; this.applicationEventPublisher = null; @@ -112,7 +121,7 @@ class Args { public String toString() { return "Args{" + "releaser=" + this.releaser + ", project=" + this.project + ", projects=" + this.projects + ", originalVersion=" - + this.originalVersion + ", versionFromScRelease=" + + this.originalVersion + ", versionFromBom=" + this.versionFromScRelease + ", properties=" + this.properties + ", interactive=" + this.interactive + ", taskType=" + this.taskType + '}'; diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java index d9eb36e5..7fd1c90d 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java @@ -96,7 +96,7 @@ class ReleaserConfiguration { ProjectPomUpdater pomUpdater, GradleUpdater gradleUpdater, ProjectBuilder projectBuilder, ReleaserProperties releaserProperties) { return new PostReleaseActions(handler, pomUpdater, gradleUpdater, projectBuilder, - releaserProperties); + releaserProperties, versionsFetcher); } @Bean diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdater.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdater.java index f458532e..c0dcdc17 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdater.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdater.java @@ -50,6 +50,7 @@ class ReleaserPropertiesUpdater { File clonedProjectFromOrg) { ReleaserProperties props = updatePropertiesFromFile(properties, clonedProjectFromOrg); + props.setWorkingDir(clonedProjectFromOrg.getAbsolutePath()); log.info("Updated properties [\n\n{}\n\n]", props); updateProperties(props); return props; diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java index aa16c725..df28923c 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java @@ -19,6 +19,8 @@ package org.springframework.cloud.release.internal.spring; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import org.slf4j.Logger; @@ -28,6 +30,7 @@ import org.springframework.cloud.release.internal.Releaser; import org.springframework.cloud.release.internal.ReleaserProperties; import org.springframework.cloud.release.internal.options.Options; import org.springframework.cloud.release.internal.options.OptionsBuilder; +import org.springframework.cloud.release.internal.pom.ProcessedProject; import org.springframework.cloud.release.internal.pom.ProjectVersion; import org.springframework.cloud.release.internal.pom.Projects; import org.springframework.context.ApplicationEventPublisher; @@ -40,6 +43,8 @@ import org.springframework.util.StringUtils; */ public class SpringReleaser { + private static final Map CACHE = new ConcurrentHashMap<>(); + private static final Logger log = LoggerFactory.getLogger(SpringReleaser.class); private final Releaser releaser; @@ -81,33 +86,46 @@ public class SpringReleaser { } public void release(Options options) { - ProjectsAndVersion projectsAndVersion = null; if (options.metaRelease) { prepareForMetaRelease(options); } if (this.properties.isPostReleaseTasksOnly()) { log.info("Skipping release process and moving only to post release"); - this.optionsProcessor.postReleaseOptions(options, - postReleaseOptionsAgs(options, projectsAndVersion)); + this.optionsProcessor.postReleaseOptions(options, postReleaseOptionsAgs( + options, null, postReleaseTaskOnlyProcessedProjects(options))); buildCompleted(); return; } - performReleaseAndPostRelease(options, projectsAndVersion); + performReleaseAndPostRelease(options, null); buildCompleted(); } + private List postReleaseTaskOnlyProcessedProjects(Options options) { + return metaReleaseProjects(options).stream().map(project -> { + File clonedProjectFromOrg = this.releaser.clonedProjectFromOrg(project); + ReleaserProperties properties = updatePropertiesIfCustomConfigPresent( + this.properties.copy(), clonedProjectFromOrg); + log.info("Successfully cloned the project [{}] to [{}]", project, + clonedProjectFromOrg); + ProjectsAndVersion projects = projects(clonedProjectFromOrg); + return new ProcessedProject(properties, projects.versionFromBom); + }).collect(Collectors.toList()); + } + private void buildCompleted() { this.applicationEventPublisher.publishEvent(new BuildCompleted(this)); } private void performReleaseAndPostRelease(Options options, ProjectsAndVersion projectsAndVersion) { + List processedProjects = new ArrayList<>(); if (options.metaRelease) { ReleaserProperties original = this.properties.copy(); log.debug("The following properties were found [{}]", original); - metaReleaseProjects(options) - .forEach(project -> processProjectForMetaRelease(original.copy(), - options, project)); + processedProjects = metaReleaseProjects(options).stream() + .map(project -> processProjectForMetaRelease(original.copy(), options, + project)) + .collect(Collectors.toList()); } else { log.info( @@ -116,7 +134,7 @@ public class SpringReleaser { projectsAndVersion = processProject(options, projectFolder, TaskType.RELEASE); } this.optionsProcessor.postReleaseOptions(options, - postReleaseOptionsAgs(options, projectsAndVersion)); + postReleaseOptionsAgs(options, projectsAndVersion, processedProjects)); } private void prepareForMetaRelease(Options options) { @@ -126,21 +144,23 @@ public class SpringReleaser { this.properties.getMetaRelease().setEnabled(options.metaRelease); } - void processProjectForMetaRelease(ReleaserProperties copy, Options options, - String project) { + ProcessedProject processProjectForMetaRelease(ReleaserProperties copy, + Options options, String project) { log.info("Original properties [\n\n{}\n\n]", copy); File clonedProjectFromOrg = this.releaser.clonedProjectFromOrg(project); - updatePropertiesIfCustomConfigPresent(copy, clonedProjectFromOrg); + copy = updatePropertiesIfCustomConfigPresent(copy, clonedProjectFromOrg); log.info("Successfully cloned the project [{}] to [{}]", project, clonedProjectFromOrg); + ProjectsAndVersion projectsAndVersion; try { - processProject(options, clonedProjectFromOrg, TaskType.RELEASE); + projectsAndVersion = processProject(options, clonedProjectFromOrg, TaskType.RELEASE); } catch (Exception e) { log.error("\n\n\nBUILD FAILED!!!\n\nException occurred for project <" + project + "> \n\n", e); throw e; } + return new ProcessedProject(copy, projectsAndVersion.versionFromBom); } private ReleaserProperties updatePropertiesIfCustomConfigPresent( @@ -196,7 +216,8 @@ public class SpringReleaser { return new File(workingDir); } - Args postReleaseOptionsAgs(Options options, ProjectsAndVersion projectsAndVersion) { + Args postReleaseOptionsAgs(Options options, ProjectsAndVersion projectsAndVersion, + List processedProjects) { Projects projects = projectsAndVersion == null ? projectsToUpdateForFixedVersions() : projectsAndVersion.projectVersions; ProjectVersion version = projects.containsProject( @@ -206,7 +227,7 @@ public class SpringReleaser { this.properties.getPom().setBranch(version.version); } return new Args(this.releaser, projects, version, this.properties, - options.interactive, this.applicationEventPublisher); + processedProjects, options.interactive, this.applicationEventPublisher); } private ProjectVersion versionFromBranch() { @@ -216,7 +237,12 @@ public class SpringReleaser { } private ProjectsAndVersion projects(File project) { - ProjectVersion versionFromScRelease; + ProjectsAndVersion projectsAndVersion = CACHE.get(project); + if (projectsAndVersion != null) { + log.info("Found cached version of projects and version [{}]", projectsAndVersion); + return projectsAndVersion; + } + ProjectVersion versionFromBom; Projects projectsToUpdate; log.info("Fetch from git [{}], meta release [{}]", this.properties.getGit().isFetchVersionsFromGit(), @@ -225,25 +251,27 @@ public class SpringReleaser { && !this.properties.getMetaRelease().isEnabled()) { printVersionRetrieval(); projectsToUpdate = this.releaser.retrieveVersionsFromSCRelease(); - versionFromScRelease = projectsToUpdate.forFile(project); + versionFromBom = projectsToUpdate.forFile(project); assertNoSnapshotsForANonSnapshotProject(projectsToUpdate, - versionFromScRelease); + versionFromBom); } else { ProjectVersion originalVersion = new ProjectVersion(project); String fixedVersionForProject = this.properties.getFixedVersions() .get(project.getName()); - versionFromScRelease = StringUtils.hasText(fixedVersionForProject) + versionFromBom = StringUtils.hasText(fixedVersionForProject) ? new ProjectVersion(originalVersion.projectName, fixedVersionForProject) : new ProjectVersion(project); projectsToUpdate = this.properties.getFixedVersions().entrySet().stream() .map(entry -> new ProjectVersion(entry.getKey(), entry.getValue())) .collect(Collectors.toCollection(Projects::new)); - projectsToUpdate.add(versionFromScRelease); + projectsToUpdate.add(versionFromBom); printSettingVersionFromFixedVersions(projectsToUpdate); } - return new ProjectsAndVersion(projectsToUpdate, versionFromScRelease); + projectsAndVersion = new ProjectsAndVersion(projectsToUpdate, versionFromBom); + CACHE.put(project, projectsAndVersion); + return projectsAndVersion; } ProjectsAndVersion processProject(Options options, File project, TaskType taskType) { @@ -251,7 +279,7 @@ public class SpringReleaser { ProjectVersion originalVersion = new ProjectVersion(project); final Args defaultArgs = new Args(this.releaser, project, projectsAndVersion.projectVersions, originalVersion, - projectsAndVersion.versionFromScRelease, this.properties, + projectsAndVersion.versionFromBom, this.properties, options.interactive, taskType, this.applicationEventPublisher); log.debug("Processing project [{}] with args [{}]", project, defaultArgs); this.optionsProcessor.processOptions(options, defaultArgs); @@ -293,12 +321,12 @@ public class SpringReleaser { final Projects projectVersions; - final ProjectVersion versionFromScRelease; + final ProjectVersion versionFromBom; ProjectsAndVersion(Projects projectVersions, - ProjectVersion versionFromScRelease) { + ProjectVersion versionFromBom) { this.projectVersions = projectVersions; - this.versionFromScRelease = versionFromScRelease; + this.versionFromBom = versionFromBom; } } 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 85f90835..2f746874 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 @@ -69,7 +69,7 @@ final class Tasks { static Task UPDATE_GUIDES = task("updateGuides", "ug", "UPDATE GUIDES", "Updating Spring Guides", args -> { args.releaser.updateSpringGuides(args.versionFromScRelease, - args.projects); + args.projects, args.processedProjects); }, TaskType.POST_RELEASE); static Task UPDATE_SAGAN = task("updateSagan", "g", "UPDATE SAGAN", "Updating Sagan with release info", args -> { diff --git a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/SpringReleaserTests.java b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/SpringReleaserTests.java index 416d8203..e81e9fec 100644 --- a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/SpringReleaserTests.java +++ b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/SpringReleaserTests.java @@ -40,6 +40,7 @@ import org.springframework.cloud.release.internal.ReleaserProperties; import org.springframework.cloud.release.internal.ReleaserPropertiesAware; import org.springframework.cloud.release.internal.options.Options; import org.springframework.cloud.release.internal.options.OptionsBuilder; +import org.springframework.cloud.release.internal.pom.ProcessedProject; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEventPublisher; @@ -147,7 +148,7 @@ public class SpringReleaserTests { @Override Args postReleaseOptionsAgs(Options options, - ProjectsAndVersion projectsAndVersion) { + ProjectsAndVersion projectsAndVersion, List processedProjects) { return new Args(TaskType.RELEASE); }