@@ -67,16 +67,21 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcabi</groupId>
|
||||
<artifactId>jcabi-github</artifactId>
|
||||
<version>0.23</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.jknack</groupId>
|
||||
<artifactId>handlebars</artifactId>
|
||||
<version>4.0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.lang.invoke.MethodHandles;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.release.internal.template.TemplateGenerator;
|
||||
import org.springframework.cloud.release.internal.git.ProjectGitUpdater;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectPomUpdater;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectVersion;
|
||||
@@ -20,12 +21,14 @@ public class Releaser {
|
||||
private final ProjectPomUpdater projectPomUpdater;
|
||||
private final ProjectBuilder projectBuilder;
|
||||
private final ProjectGitUpdater projectGitUpdater;
|
||||
private final TemplateGenerator templateGenerator;
|
||||
|
||||
public Releaser(ProjectPomUpdater projectPomUpdater,
|
||||
ProjectBuilder projectBuilder, ProjectGitUpdater projectGitUpdater) {
|
||||
public Releaser(ProjectPomUpdater projectPomUpdater, ProjectBuilder projectBuilder,
|
||||
ProjectGitUpdater projectGitUpdater, TemplateGenerator templateGenerator) {
|
||||
this.projectPomUpdater = projectPomUpdater;
|
||||
this.projectBuilder = projectBuilder;
|
||||
this.projectGitUpdater = projectGitUpdater;
|
||||
this.templateGenerator = templateGenerator;
|
||||
}
|
||||
|
||||
public Projects retrieveVersionsFromSCRelease() {
|
||||
@@ -79,4 +82,13 @@ public class Releaser {
|
||||
this.projectGitUpdater.closeMilestone(releaseVersion);
|
||||
log.info("\nSuccessfully closed milestone");
|
||||
}
|
||||
|
||||
public void createEmail(ProjectVersion releaseVersion) {
|
||||
if (releaseVersion.isSnapshot()) {
|
||||
log.info("\nWon't send an email for a SNAPSHOT version");
|
||||
} else {
|
||||
File email = this.templateGenerator.email();
|
||||
log.info("\nSuccessfully created email template at location [{}]", email);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.springframework.cloud.release.internal.template;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.springframework.cloud.release.internal.ReleaserProperties;
|
||||
|
||||
import com.github.jknack.handlebars.Handlebars;
|
||||
import com.github.jknack.handlebars.Template;
|
||||
import com.github.jknack.handlebars.helper.StringHelpers;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class TemplateGenerator {
|
||||
|
||||
private final String emailTemplate = "/templates/email";
|
||||
private final File emailOutput = new File("target/email.txt");
|
||||
private final ReleaserProperties props;
|
||||
|
||||
public TemplateGenerator(ReleaserProperties props) {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
public File email() {
|
||||
try {
|
||||
Template template = uncheckedCompileTemplate();
|
||||
String releaseVersion = parsedVersion();
|
||||
String email = template.apply(releaseVersion);
|
||||
if (emailOutput.exists()) {
|
||||
emailOutput.delete();
|
||||
}
|
||||
if (!emailOutput.createNewFile()) {
|
||||
throw new IllegalStateException("Couldn't create a file with email template");
|
||||
}
|
||||
Files.write(emailOutput.toPath(), email.getBytes());
|
||||
return emailOutput;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String parsedVersion() {
|
||||
String version = this.props.getPom().getBranch();
|
||||
if (version.startsWith("v")) {
|
||||
return version.substring(1);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
private Template uncheckedCompileTemplate() {
|
||||
try {
|
||||
Handlebars handlebars = new Handlebars();
|
||||
handlebars.registerHelper("replace", StringHelpers.replace);
|
||||
handlebars.registerHelper("capitalizeFirst", StringHelpers.capitalizeFirst);
|
||||
return handlebars.compile(this.emailTemplate);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
Title:
|
||||
Spring Cloud {{ this }} available
|
||||
|
||||
Content:
|
||||
All,
|
||||
|
||||
On behalf of the team and the community, I'm excited to announce Spring Cloud {{ replace this "." " " }} Train release.
|
||||
|
||||
link to blog post
|
||||
link to twitter
|
||||
|
||||
Cheers,
|
||||
@@ -10,6 +10,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.cloud.release.internal.template.TemplateGenerator;
|
||||
import org.springframework.cloud.release.internal.git.ProjectGitUpdater;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectPomUpdater;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectVersion;
|
||||
@@ -28,6 +29,7 @@ public class ReleaserTests {
|
||||
@Mock ProjectPomUpdater projectPomUpdater;
|
||||
@Mock ProjectBuilder projectBuilder;
|
||||
@Mock ProjectGitUpdater projectGitUpdater;
|
||||
@Mock TemplateGenerator templateGenerator;
|
||||
@InjectMocks Releaser releaser;
|
||||
File pom;
|
||||
|
||||
@@ -64,4 +66,18 @@ public class ReleaserTests {
|
||||
then(this.projectBuilder).should().bumpVersions(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_generate_email_for_snapshot_version() throws Exception {
|
||||
this.releaser.createEmail(new ProjectVersion("original", "1.0.0.BUILD-SNAPSHOT"));
|
||||
|
||||
then(this.templateGenerator).should(never()).email();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_generate_email_for_release_version() throws Exception {
|
||||
this.releaser.createEmail(new ProjectVersion("original", "1.0.0.RELEASE"));
|
||||
|
||||
then(this.templateGenerator).should().email();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.springframework.cloud.release.internal.template;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.release.internal.ReleaserProperties;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class TemplateGeneratorTests {
|
||||
|
||||
@Test
|
||||
public void should_generate_email_from_template_for_tag_with_v_prefix() {
|
||||
ReleaserProperties props = new ReleaserProperties();
|
||||
props.getPom().setBranch("vDalston.RELEASE");
|
||||
File generatedMail = new TemplateGenerator(props).email();
|
||||
|
||||
then(generatedMail).hasContent(expectedEmail());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_generate_email_from_template_for_tag_without_v_prefix() {
|
||||
ReleaserProperties props = new ReleaserProperties();
|
||||
props.getPom().setBranch("Dalston.RELEASE");
|
||||
File generatedMail = new TemplateGenerator(props).email();
|
||||
|
||||
then(generatedMail).hasContent(expectedEmail());
|
||||
}
|
||||
|
||||
private String expectedEmail() {
|
||||
return "Title:\n"
|
||||
+ "Spring Cloud Dalston.RELEASE available\n\n"
|
||||
+ "Content:\n"
|
||||
+ "All,\n" + "\n"
|
||||
+ "On behalf of the team and the community, I'm excited to announce Spring Cloud Dalston RELEASE Train release.\n"
|
||||
+ "\n"
|
||||
+ "link to blog post\n"
|
||||
+ "link to twitter\n\n"
|
||||
+ "Cheers,\n";
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.release.internal.spring;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.release.internal.Releaser;
|
||||
import org.springframework.cloud.release.internal.ReleaserProperties;
|
||||
import org.springframework.cloud.release.internal.template.TemplateGenerator;
|
||||
import org.springframework.cloud.release.internal.project.ProjectBuilder;
|
||||
import org.springframework.cloud.release.internal.git.ProjectGitUpdater;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectPomUpdater;
|
||||
@@ -31,6 +32,6 @@ class ReleaserConfiguration {
|
||||
@Bean SpringReleaser releaser(ReleaserProperties properties) {
|
||||
ProjectPomUpdater pomUpdater = new ProjectPomUpdater(properties);
|
||||
return new SpringReleaser(new Releaser(pomUpdater, new ProjectBuilder(properties, pomUpdater),
|
||||
new ProjectGitUpdater(properties)), properties);
|
||||
new ProjectGitUpdater(properties), new TemplateGenerator(properties)), properties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,12 +37,12 @@ public class SpringReleaser {
|
||||
File project = new File(workingDir);
|
||||
ProjectVersion originalVersion = new ProjectVersion(project);
|
||||
Projects projects = this.releaser.retrieveVersionsFromSCRelease();
|
||||
ProjectVersion changedVersion = projects.forFile(project);
|
||||
ProjectVersion versionFromScRelease = projects.forFile(project);
|
||||
log.info("\n\n\n=== UPDATING POMS ===\n\nWill run the application "
|
||||
+ "for root folder [{}]. \n\nPress ENTER to continue {}", workingDir, MSG);
|
||||
boolean skipPoms = skipStep();
|
||||
if (!skipPoms) {
|
||||
changedVersion = this.releaser.updateProjectFromScRelease(project, projects);
|
||||
versionFromScRelease = this.releaser.updateProjectFromScRelease(project, projects);
|
||||
}
|
||||
log.info("\n\n\n=== BUILD PROJECT ===\n\nPress ENTER to build the project {}", MSG);
|
||||
boolean skipBuild = skipStep();
|
||||
@@ -52,7 +52,7 @@ public class SpringReleaser {
|
||||
log.info("\n\n\n=== COMMITTING (ALL) AND PUSHING TAGS (NON-SNAPSHOTS) ===\n\nPress ENTER to commit, tag and push the tag {}", MSG);
|
||||
boolean skipCommit = skipStep();
|
||||
if (!skipCommit) {
|
||||
this.releaser.commitAndPushTags(project, changedVersion);
|
||||
this.releaser.commitAndPushTags(project, versionFromScRelease);
|
||||
}
|
||||
log.info("\n\n\n=== ARTIFACT DEPLOYMENT ===\n\nPress ENTER to deploy the artifacts {}", MSG);
|
||||
boolean skipDeployment = skipStep();
|
||||
@@ -62,14 +62,14 @@ public class SpringReleaser {
|
||||
log.info("\n\n\n=== PUBLISHING DOCS ===\n\nPress ENTER to publish the docs {}", MSG);
|
||||
boolean skipDocs = skipStep();
|
||||
if (!skipDocs) {
|
||||
this.releaser.publishDocs(changedVersion);
|
||||
this.releaser.publishDocs(versionFromScRelease);
|
||||
}
|
||||
if (!changedVersion.isSnapshot()) {
|
||||
if (!versionFromScRelease.isSnapshot()) {
|
||||
log.info("\n\n\n=== REVERTING CHANGES & BUMPING VERSION (RELEASE ONLY)===\n\nPress ENTER to go "
|
||||
+ "back to snapshots and bump originalVersion by patch {}", MSG);
|
||||
boolean skipRevert = skipStep();
|
||||
if (!skipRevert) {
|
||||
this.releaser.rollbackReleaseVersion(project, originalVersion, changedVersion);
|
||||
this.releaser.rollbackReleaseVersion(project, originalVersion, versionFromScRelease);
|
||||
}
|
||||
}
|
||||
log.info("\n\n\n=== PUSHING CHANGES===\n\nPress ENTER to push the commits {}", MSG);
|
||||
@@ -77,11 +77,18 @@ public class SpringReleaser {
|
||||
if (!skipPush) {
|
||||
this.releaser.pushCurrentBranch(project);
|
||||
}
|
||||
if (!changedVersion.isSnapshot()) {
|
||||
if (!versionFromScRelease.isSnapshot()) {
|
||||
log.info("\n\n\n=== CLOSING MILESTONE===\n\nPress ENTER to close the milestone at Github {}", MSG);
|
||||
boolean skipMilestone = skipStep();
|
||||
if (!skipMilestone) {
|
||||
this.releaser.closeMilestone(changedVersion);
|
||||
this.releaser.closeMilestone(versionFromScRelease);
|
||||
}
|
||||
}
|
||||
if (!versionFromScRelease.isSnapshot()) {
|
||||
log.info("\n\n\n=== CREATING TEMPLATES===\n\nPress ENTER to create email / tweet etc. templates {}", MSG);
|
||||
boolean skipTemplates = skipStep();
|
||||
if (!skipTemplates) {
|
||||
this.releaser.createEmail(versionFromScRelease);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.springframework.cloud.release.internal.spring;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
@@ -14,6 +16,7 @@ import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.cloud.release.internal.Releaser;
|
||||
import org.springframework.cloud.release.internal.ReleaserProperties;
|
||||
import org.springframework.cloud.release.internal.template.TemplateGenerator;
|
||||
import org.springframework.cloud.release.internal.git.GitTestUtils;
|
||||
import org.springframework.cloud.release.internal.git.ProjectGitUpdater;
|
||||
import org.springframework.cloud.release.internal.pom.ProjectPomUpdater;
|
||||
@@ -64,6 +67,11 @@ public class AcceptanceTests {
|
||||
pomVersionIsEqualTo(project, "1.2.1.BUILD-SNAPSHOT");
|
||||
pomParentVersionIsEqualTo(project, "1.2.1.BUILD-SNAPSHOT");
|
||||
then(this.gitUpdater.executed).isTrue();
|
||||
then(emailTemplate()).exists();
|
||||
String emailTemplateContents = emailTemplateContents();
|
||||
then(emailTemplateContents)
|
||||
.contains("Spring Cloud Camden.SR5 available")
|
||||
.contains("Spring Cloud Camden SR5 Train release");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,6 +93,11 @@ public class AcceptanceTests {
|
||||
commitIsPresent(iterator, "Update SNAPSHOT to 1.2.0.RC1");
|
||||
pomVersionIsEqualTo(project, "1.2.0.BUILD-SNAPSHOT");
|
||||
pomParentVersionIsEqualTo(project, "1.2.0.BUILD-SNAPSHOT");
|
||||
then(emailTemplate()).exists();
|
||||
String emailTemplateContents = emailTemplateContents();
|
||||
then(emailTemplateContents)
|
||||
.contains("Spring Cloud Dalston.RC1 available")
|
||||
.contains("Spring Cloud Dalston RC1 Train release");
|
||||
then(this.gitUpdater.executed).isTrue();
|
||||
}
|
||||
|
||||
@@ -124,13 +137,23 @@ public class AcceptanceTests {
|
||||
return this.testPomReader.readPom(new File(dir, "pom.xml"));
|
||||
}
|
||||
|
||||
private File emailTemplate() throws URISyntaxException {
|
||||
return new File("target/email.txt");
|
||||
}
|
||||
|
||||
private String emailTemplateContents() throws URISyntaxException, IOException {
|
||||
return new String(Files.readAllBytes(emailTemplate().toPath()));
|
||||
}
|
||||
|
||||
private SpringReleaser releaser(File projectFile, String branch, String expectedVersion) throws Exception {
|
||||
ReleaserProperties properties = releaserProperties(projectFile, branch);
|
||||
ProjectPomUpdater pomUpdater = new ProjectPomUpdater(properties);
|
||||
ProjectBuilder projectBuilder = new ProjectBuilder(properties, pomUpdater);
|
||||
TestProjectGitUpdater gitUpdater = new TestProjectGitUpdater(properties,
|
||||
expectedVersion);
|
||||
Releaser releaser = new Releaser(pomUpdater, projectBuilder, gitUpdater);
|
||||
TemplateGenerator templateGenerator = new TemplateGenerator(properties);
|
||||
Releaser releaser = new Releaser(pomUpdater, projectBuilder, gitUpdater,
|
||||
templateGenerator);
|
||||
this.gitUpdater = gitUpdater;
|
||||
return new SpringReleaser(releaser, properties) {
|
||||
@Override boolean skipStep() {
|
||||
|
||||
Reference in New Issue
Block a user