From eec48c142b783904cff8362284d8ef40864d3f65 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Mon, 19 Aug 2019 13:58:25 +0200 Subject: [PATCH] Will create an issue in start.spring.io for a new release train --- .../asciidoc/spring-cloud-release-tools.adoc | 2 + .../cloud/release/internal/Releaser.java | 26 +++++ .../release/internal/ReleaserProperties.java | 13 +++ .../release/internal/git/GithubIssues.java | 45 ++++++--- .../internal/git/ProjectGitHandler.java | 6 +- .../internal/git/GithubIssuesTests.java | 97 +++++++++++++++++-- .../cloud/release/internal/spring/Tasks.java | 6 ++ .../internal/spring/AcceptanceTests.java | 20 ++++ 8 files changed, 194 insertions(+), 21 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-release-tools.adoc b/docs/src/main/asciidoc/spring-cloud-release-tools.adoc index e03b2758..ca86b26e 100644 --- a/docs/src/main/asciidoc/spring-cloud-release-tools.adoc +++ b/docs/src/main/asciidoc/spring-cloud-release-tools.adoc @@ -42,6 +42,7 @@ After project release - Generates a release notes template under `target/notes.md` (ONLY FOR NON-SNAPSHOT VERSIONS) - Updates project information in Sagan (https://spring.io) (ONLY FOR SNAPSHOT / RELEASE VERSIONS) - For `GA`/ `SR` release will create an issue in Spring Guides under https://github.com/spring-guides/getting-started-guides/issues/ +- For `GA`/ `SR` release will create an issue in start.spring.io under https://github.com/spring-io/start.spring.io/issues/ - For `GA`/ `SR` release will update the links under https://github.com/spring-cloud/spring-cloud-static/tree/gh-pages/current - Will update the release train project page (for Spring Cloud it will be `https://github.com/spring-projects/spring-cloud`) @@ -285,6 +286,7 @@ Defaults to Sleuth and Contract samples. - `releaser.git.release-train-docs-branch` - Branch to check out for release train documentation. Defaults to `master`. - `releaser.git.update-release-train-docs` - If `true` then will update the release train documentation project and run the generation. Defaults to `true`. - `releaser.git.update-spring-guides` - If `true` then will update Spring Guides with the current release train. Defaults to `true`. +- `releaser.git.update-start-spring-io` - If `true` then will update start.spring.io with the current release train. Defaults to `true`. The following properties are used for both meta release and a release of an individual module. 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 7c2f9a1d..171ae4a8 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 @@ -234,6 +234,18 @@ public class Releaser { } } + public void updateStartSpringIo(ProjectVersion releaseVersion, Projects projects) { + if (!(releaseVersion.isRelease() || releaseVersion.isServiceRelease())) { + log.info( + "\nWon't update start.spring.io for a non Release / Service Release version"); + return; + } + Exception exception = createIssueInStartSpringIo(releaseVersion, projects); + if (exception != null) { + throw new MakeBuildUnstableException("Failed to update start.spring.io"); + } + } + private Exception createIssueInSpringGuides(ProjectVersion releaseVersion, Projects projects) { try { @@ -248,6 +260,20 @@ public class Releaser { } } + private Exception createIssueInStartSpringIo(ProjectVersion releaseVersion, + Projects projects) { + try { + this.projectGitHandler.createIssueInStartSpringIo(projects, releaseVersion); + log.info("\nSuccessfully created an issue in start.spring.io"); + return null; + } + catch (Exception ex) { + log.error("Failed to update start.spring.io repo", ex); + return new MakeBuildUnstableException("Failed to update start.spring.io repo", + ex); + } + } + private Exception deployGuides(List processedProjects) { try { this.postReleaseActions.deployGuides(processedProjects); 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 c73441f2..f0389ae8 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 @@ -360,6 +360,11 @@ public class ReleaserProperties implements Serializable { */ private boolean updateSpringGuides = true; + /** + * If set to {@code false}, will not update start.spring.io for a release train. + */ + private boolean updateStartSpringIo = true; + /** * If set to {@code false}, will not update the Spring Project for a release * train. E.g. for Spring Cloud will not update https://cloud.spring.io . @@ -539,6 +544,14 @@ public class ReleaserProperties implements Serializable { this.updateSpringGuides = updateSpringGuides; } + public boolean isUpdateStartSpringIo() { + return this.updateStartSpringIo; + } + + public void setUpdateStartSpringIo(boolean updateStartSpringIo) { + this.updateStartSpringIo = updateStartSpringIo; + } + public boolean isUpdateSpringProject() { return this.updateSpringProject; } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GithubIssues.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GithubIssues.java index 39d8ff6b..b914182e 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GithubIssues.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GithubIssues.java @@ -58,44 +58,61 @@ class GithubIssues { this.properties = properties; } - void fileIssue(Projects projects, ProjectVersion version) { + void fileIssueInSpringGuides(Projects projects, ProjectVersion version) { if (!this.properties.getGit().isUpdateSpringGuides()) { log.info("Will not file an issue to Spring Guides, since the switch to do so " + "is off. Set [releaser.git.update-spring-guides] to [true] to change that"); return; } + fileAGitHubIssue("spring-guides", "getting-started-guides", projects, version); + // iterate over projects, checkout the tag, build the guides project + // only with -Pintegration,guides profile + } + + void fileIssueInStartSpringIo(Projects projects, ProjectVersion version) { + if (!this.properties.getGit().isUpdateStartSpringIo()) { + log.info( + "Will not file an issue to Start Spring Io, since the switch to do so " + + "is off. Set [releaser.git.update-start-spring-io] to [true] to change that"); + return; + } + fileAGitHubIssue("spring-io", "start.spring.io", projects, version); + // iterate over projects, checkout the tag, build the guides project + // only with -Pintegration,guides profile + } + + private void fileAGitHubIssue(String user, String repo, Projects projects, + ProjectVersion version) { Assert.hasText(this.properties.getGit().getOauthToken(), "You have to pass Github OAuth token for milestone closing to be operational"); // do this only for RELEASE & SR String releaseVersion = parsedVersion(); if (!(version.isRelease() || version.isServiceRelease())) { log.info( - "Guide issue creation will occur only for Release or Service Release versions. Your version is [{}]", + "Github issue creation will occur only for Release or Service Release versions. Your version is [{}]", releaseVersion); return; } - fileAGithubIssue(projects, releaseVersion); - // iterate over projects, checkout the tag, build the guides project - // only with -Pintegration,guides profile + fileAGithubIssue(user, repo, projects, releaseVersion); } - private void fileAGithubIssue(Projects projects, String releaseVersion) { - Repo springGuides = this.github.repos() - .get(new Coordinates.Simple("spring-guides", "getting-started-guides")); + private void fileAGithubIssue(String user, String repo, Projects projects, + String releaseVersion) { + Repo ghRepo = this.github.repos().get(new Coordinates.Simple(user, repo)); String issueTitle = StringUtils.capitalize(releaseVersion) + " " + GITHUB_ISSUE_TITLE; // check if the issue is not already there - boolean issueAlreadyFiled = issueAlreadyFiled(springGuides, issueTitle); + boolean issueAlreadyFiled = issueAlreadyFiled(ghRepo, issueTitle); if (issueAlreadyFiled) { log.info("Issue already filed, will not do that again"); return; } try { - int number = springGuides.issues().create(issueTitle, issueText(projects)) - .number(); - log.info("Successfully created an issue with " - + "title [{}] in Spring Guides under: https://github.com/spring-guides/getting-started-guides/issues/" - + number, issueTitle); + int number = ghRepo.issues().create(issueTitle, issueText(projects)).number(); + log.info( + "Successfully created an issue with " + + "title [{}] for the [{}/{}] GitHub repository" + number, + issueTitle, user, repo); } catch (IOException e) { log.error("Exception occurred while trying to create the issue in guides", 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 ec54c510..df376bab 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 @@ -273,7 +273,11 @@ public class ProjectGitHandler implements ReleaserPropertiesAware { } public void createIssueInSpringGuides(Projects projects, ProjectVersion version) { - this.githubIssues.fileIssue(projects, version); + this.githubIssues.fileIssueInSpringGuides(projects, version); + } + + public void createIssueInStartSpringIo(Projects projects, ProjectVersion version) { + this.githubIssues.fileIssueInStartSpringIo(projects, version); } public String milestoneUrl(ProjectVersion releaseVersion) { diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GithubIssuesTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GithubIssuesTests.java index 55d539ae..7472117b 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GithubIssuesTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GithubIssuesTests.java @@ -56,16 +56,26 @@ public class GithubIssuesTests { @Before public void setup() throws IOException { - this.github = new MkGithub("spring-guides"); + this.github = github("spring-guides"); this.repo = createGettingStartedGuides(this.github); } + public void setupStartSpringIo() throws IOException { + this.github = github("spring-io"); + this.repo = createStartSpringIo(this.github); + } + + private MkGithub github(String login) throws IOException { + return new MkGithub(login); + } + @Test public void should_not_do_anything_for_non_release_train_version() { Github github = BDDMockito.mock(Github.class); GithubIssues issues = new GithubIssues(github, withToken()); - issues.fileIssue(new Projects(new ProjectVersion("foo", "1.0.0.BUILD-SNAPSHOT")), + issues.fileIssueInSpringGuides( + new Projects(new ProjectVersion("foo", "1.0.0.BUILD-SNAPSHOT")), new ProjectVersion("sc-release", "Edgware.BUILD-SNAPSHOT")); BDDMockito.then(github).shouldHaveZeroInteractions(); @@ -78,7 +88,7 @@ public class GithubIssuesTests { properties.getGit().setUpdateSpringGuides(false); GithubIssues issues = new GithubIssues(github, properties); - issues.fileIssue( + issues.fileIssueInSpringGuides( new Projects(new ProjectVersion("foo", "1.0.0.RELEASE"), new ProjectVersion("bar", "2.0.0.RELEASE"), new ProjectVersion("baz", "3.0.0.RELEASE")), @@ -91,7 +101,7 @@ public class GithubIssuesTests { public void should_file_an_issue_for_release_version() throws IOException { GithubIssues issues = new GithubIssues(this.github, withToken()); - issues.fileIssue( + issues.fileIssueInSpringGuides( new Projects(new ProjectVersion("foo", "1.0.0.RELEASE"), new ProjectVersion("bar", "2.0.0.RELEASE"), new ProjectVersion("baz", "3.0.0.RELEASE")), @@ -115,8 +125,79 @@ public class GithubIssuesTests { public void should_throw_exception_when_no_token_was_passed() { GithubIssues issues = new GithubIssues(new ReleaserProperties()); - thenThrownBy(() -> issues.fileIssue(new Projects(Collections.emptySet()), - nonGaSleuthProject())).isInstanceOf(IllegalArgumentException.class) + thenThrownBy(() -> issues.fileIssueInSpringGuides( + new Projects(Collections.emptySet()), nonGaSleuthProject())) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining( + "You have to pass Github OAuth token for milestone closing to be operational"); + } + + @Test + public void should_not_do_anything_for_non_release_train_version_when_updating_startspringio() + throws IOException { + setupStartSpringIo(); + Github github = BDDMockito.mock(Github.class); + GithubIssues issues = new GithubIssues(github, withToken()); + + issues.fileIssueInStartSpringIo( + new Projects(new ProjectVersion("foo", "1.0.0.BUILD-SNAPSHOT")), + new ProjectVersion("sc-release", "Edgware.BUILD-SNAPSHOT")); + + BDDMockito.then(github).shouldHaveZeroInteractions(); + } + + @Test + public void should_not_do_anything_if_switch_is_not_set_when_updating_startspringio() + throws IOException { + setupStartSpringIo(); + Github github = BDDMockito.mock(Github.class); + ReleaserProperties properties = withToken(); + properties.getGit().setUpdateStartSpringIo(false); + GithubIssues issues = new GithubIssues(github, properties); + + issues.fileIssueInStartSpringIo( + new Projects(new ProjectVersion("foo", "1.0.0.RELEASE"), + new ProjectVersion("bar", "2.0.0.RELEASE"), + new ProjectVersion("baz", "3.0.0.RELEASE")), + new ProjectVersion("sc-release", "Edgware.RELEASE")); + + BDDMockito.then(github).shouldHaveZeroInteractions(); + } + + @Test + public void should_file_an_issue_for_release_version_when_updating_startspringio() + throws IOException { + setupStartSpringIo(); + GithubIssues issues = new GithubIssues(this.github, withToken()); + + issues.fileIssueInStartSpringIo( + new Projects(new ProjectVersion("foo", "1.0.0.RELEASE"), + new ProjectVersion("bar", "2.0.0.RELEASE"), + new ProjectVersion("baz", "3.0.0.RELEASE")), + new ProjectVersion("sc-release", "Edgware.RELEASE")); + + then(this.capture.toString()).doesNotContain("will occur only"); + Issue issue = this.github.repos() + .get(new Coordinates.Simple("spring-io", "start.spring.io")).issues() + .get(1); + then(issue.exists()).isTrue(); + Issue.Smart smartIssue = new Issue.Smart(issue); + then(smartIssue.title()) + .isEqualTo("Edgware.RELEASE Spring Cloud Release took place"); + then(smartIssue.body()).contains("Spring Cloud [Edgware.RELEASE]") + .contains("foo : `1.0.0.RELEASE`").contains("bar : `2.0.0.RELEASE`") + .contains("baz : `3.0.0.RELEASE`"); + } + + @Test + public void should_throw_exception_when_no_token_was_passed_when_updating_startspringio() + throws IOException { + setupStartSpringIo(); + GithubIssues issues = new GithubIssues(new ReleaserProperties()); + + thenThrownBy(() -> issues.fileIssueInStartSpringIo( + new Projects(Collections.emptySet()), nonGaSleuthProject())) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining( "You have to pass Github OAuth token for milestone closing to be operational"); } @@ -126,6 +207,10 @@ public class GithubIssuesTests { .create(new Repos.RepoCreate("getting-started-guides", false)); } + private Repo createStartSpringIo(MkGithub github) throws IOException { + return github.repos().create(new Repos.RepoCreate("start.spring.io", false)); + } + private ProjectVersion nonGaSleuthProject() { return new ProjectVersion("spring-cloud-sleuth", "0.2.0.BUILD-SNAPSHOT"); } 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 ce1d3c9c..9f2f915c 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 @@ -71,6 +71,11 @@ final class Tasks { args.releaser.updateSpringGuides(args.versionFromScRelease, args.projects, args.processedProjects); }, TaskType.POST_RELEASE); + static Task UPDATE_START_SPRING_IO = task("updateStartSpringIo", "us", + "UPDATE START.SPRING.IO", "Updating start.spring.io", args -> { + args.releaser.updateStartSpringIo(args.versionFromScRelease, + args.projects); + }, TaskType.POST_RELEASE); static Task UPDATE_SAGAN = task("updateSagan", "g", "UPDATE SAGAN", "Updating Sagan with release info", args -> { args.releaser.updateSagan(args.project, args.versionFromScRelease); @@ -113,6 +118,7 @@ final class Tasks { static final List DEFAULT_TASKS_PER_RELEASE = Stream .of(Tasks.RUN_UPDATED_SAMPLES, Tasks.CREATE_TEMPLATES, Tasks.UPDATE_GUIDES, + Tasks.UPDATE_START_SPRING_IO, Tasks.UPDATE_RELEASE_TRAIN_DOCUMENTATION, Tasks.UPDATE_DOCUMENTATION, Tasks.UPDATE_RELEASE_TRAIN_WIKI, Tasks.UPDATE_ALL_SAMPLES) .collect(Collectors.toList()); 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 13846cf2..2c4ea330 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 @@ -239,6 +239,7 @@ public class AcceptanceTests { BDDMockito.then(this.saganClient).should(BDDMockito.never()) .deleteRelease("spring-cloud-build", "2.0.0.M8"); then(this.gitHandler.issueCreatedInSpringGuides).isTrue(); + then(this.gitHandler.issueCreatedInStartSpringIo).isTrue(); then(text(new File(this.documentationFolder, "current/index.html"))) .doesNotContain("Angel.SR3").contains("Camden.SR5"); thenRunUpdatedTestsWereCalled(); @@ -458,6 +459,7 @@ public class AcceptanceTests { BDDMockito.then(this.saganClient).should(BDDMockito.never()) .deleteRelease("spring-cloud-build", "2.0.0.M8"); then(this.gitHandler.issueCreatedInSpringGuides).isTrue(); + then(this.gitHandler.issueCreatedInStartSpringIo).isTrue(); then(text(new File(this.documentationFolder, "current/index.html"))) .doesNotContain("Angel.SR3").contains("Camden.SR5"); } @@ -508,6 +510,7 @@ public class AcceptanceTests { "1.2.0.RC1"); // we update guides only for SR / RELEASE then(this.gitHandler.issueCreatedInSpringGuides).isFalse(); + then(this.gitHandler.issueCreatedInStartSpringIo).isFalse(); // haven't even checked out the branch then(new File(this.documentationFolder, "current/index.html")).doesNotExist(); } @@ -544,6 +547,7 @@ public class AcceptanceTests { BDDMockito.then(this.saganClient).should(BDDMockito.never()) .updateRelease(BDDMockito.anyString(), BDDMockito.anyList()); then(this.gitHandler.issueCreatedInSpringGuides).isFalse(); + then(this.gitHandler.issueCreatedInStartSpringIo).isFalse(); } private Iterable listOfCommits(File project) throws GitAPIException { @@ -855,6 +859,8 @@ public class AcceptanceTests { boolean issueCreatedInSpringGuides = false; + boolean issueCreatedInStartSpringIo = false; + TestProjectGitHandler(ReleaserProperties properties, String expectedVersion, String projectName) { super(properties); @@ -874,6 +880,12 @@ public class AcceptanceTests { this.issueCreatedInSpringGuides = true; } + @Override + public void createIssueInStartSpringIo(Projects projects, + ProjectVersion version) { + this.issueCreatedInStartSpringIo = true; + } + @Override public String milestoneUrl(ProjectVersion releaseVersion) { return "https://foo.bar.com/" + releaseVersion.toString(); @@ -887,6 +899,8 @@ public class AcceptanceTests { boolean issueCreatedInSpringGuides = false; + boolean issueCreatedInStartSpringIo = false; + List clonedProjects = new ArrayList<>(); NonAssertingTestProjectGitHandler(ReleaserProperties properties) { @@ -903,6 +917,12 @@ public class AcceptanceTests { this.issueCreatedInSpringGuides = true; } + @Override + public void createIssueInStartSpringIo(Projects projects, + ProjectVersion version) { + this.issueCreatedInStartSpringIo = true; + } + @Override public String milestoneUrl(ProjectVersion releaseVersion) { return "https://foo.bar.com/" + releaseVersion.toString();