Will create an issue in start.spring.io for a new release train

This commit is contained in:
Marcin Grzejszczak
2019-08-19 13:58:25 +02:00
parent 5ced6c71af
commit eec48c142b
8 changed files with 194 additions and 21 deletions

View File

@@ -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.

View File

@@ -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<ProcessedProject> processedProjects) {
try {
this.postReleaseActions.deployGuides(processedProjects);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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");
}

View File

@@ -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<Task> 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());

View File

@@ -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<RevCommit> 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<File> 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();