Added the ability to run a single step without skipping

fixes #9
This commit is contained in:
Marcin Grzejszczak
2017-04-20 14:51:46 +02:00
parent 42024e1a2b
commit 2131efcdc4
6 changed files with 284 additions and 82 deletions

View File

@@ -2,6 +2,10 @@ package org.springframework.cloud.release.internal.spring;
import java.io.File;
import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,6 +14,8 @@ import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
import org.springframework.cloud.release.internal.pom.Projects;
import static org.springframework.cloud.release.internal.spring.Task.task;
/**
* Releaser that gets input from console
*
@@ -18,10 +24,6 @@ import org.springframework.cloud.release.internal.pom.Projects;
public class SpringReleaser {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String MSG = "'q' to quit and 's' to skip\n\n";
private static final String SKIP = "s";
private static final String QUIT = "q";
private final Releaser releaser;
private final ReleaserProperties properties;
@@ -30,80 +32,168 @@ public class SpringReleaser {
this.properties = properties;
}
private final List<Task> TASKS = Stream.of(
task("UPDATING POMS",
"Update poms with versions from Spring Cloud Release",
args -> args.releaser.updateProjectFromScRelease(args.project, args.projects)),
task("BUILD PROJECT",
"Build the project",
args -> args.releaser.buildProject()),
task("COMMITTING (ALL) AND PUSHING TAGS (NON-SNAPSHOTS)",
"Commit, tag and push the tag",
args -> args.releaser.commitAndPushTags(args.project, args.versionFromScRelease)),
task("ARTIFACT DEPLOYMENT",
"Deploy the artifacts to Artifactory",
args -> args.releaser.deploy()),
task("PUBLISHING DOCS",
"Publish the docs",
args -> args.releaser.publishDocs(args.versionFromScRelease)),
task("REVERTING CHANGES & BUMPING VERSION (RELEASE ONLY)",
"Go back to snapshots and bump originalVersion by patch",
args -> args.releaser.rollbackReleaseVersion(args.project, args.originalVersion, args.versionFromScRelease)),
task("PUSHING CHANGES",
"Push the commits",
args -> args.releaser.pushCurrentBranch(args.project)),
task("CLOSING MILESTONE",
"Close the milestone at Github",
args -> args.releaser.closeMilestone(args.versionFromScRelease)),
task("CREATING TEMPLATES",
"Create email / tweet etc. templates",
args -> {
args.releaser.createEmail(args.versionFromScRelease);
args.releaser.createBlog(args.versionFromScRelease, args.projects);
})
).collect(Collectors.toList());
private final List<Task> COMPOSITE_TASKS = Stream.of(
task("FULL RELEASE",
"Perform a full release of this project without interruptions",
args -> TASKS.forEach(task -> task.execute(args))),
task("FULL VERBOSE RELEASE",
"Perform a full release of this project in a verbose mode (you'll be asked about skipping steps)",
args -> TASKS.forEach(task -> task.execute(args)))
).collect(Collectors.toList());
private final List<Task> ALL_TASKS = Stream.of(
COMPOSITE_TASKS,
TASKS
).flatMap(List::stream).collect(Collectors.toList());
public void release() {
log.info("\n\n\n=== RETRIEVING VERSIONS ===\n\nWill clone Spring Cloud Release"
+ " to retrieve all versions for the branch [{}]", this.properties.getPom().getBranch());
log.info(buildOptionsText().toString());
printVersionRetreival();
String workingDir = this.properties.getWorkingDir();
File project = new File(workingDir);
ProjectVersion originalVersion = new ProjectVersion(project);
Projects projects = this.releaser.retrieveVersionsFromSCRelease();
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) {
versionFromScRelease = this.releaser.updateProjectFromScRelease(project, projects);
int chosenOption = chosenOption();
log.info("\n\n\nYou chose [{}]: [{}]\n\n\n", chosenOption, ALL_TASKS.get(chosenOption).description);
boolean verbose = chosenOption == 1;
Task task = taskFromOption(chosenOption);
Args args = new Args(this.releaser, project, projects, originalVersion, versionFromScRelease,
this.properties, verbose);
task.consumer.accept(args);
}
private StringBuilder buildOptionsText() {
StringBuilder msg = new StringBuilder();
msg.append("\n\n\n=== WHAT DO YOU WANT TO DO? ===\n\n");
for (int i = 0; i < ALL_TASKS.size(); i++) {
msg.append(i).append(") ").append(ALL_TASKS.get(i).description).append("\n");
}
log.info("\n\n\n=== BUILD PROJECT ===\n\nPress ENTER to build the project {}", MSG);
boolean skipBuild = skipStep();
if (!skipBuild) {
this.releaser.buildProject();
msg.append("\n\n").append("You can press 'q' to quit\n\n");
return msg;
}
private void printVersionRetreival() {
log.info("\n\n\n=== RETRIEVING VERSIONS ===\n\nWill clone Spring Cloud Release"
+ " to retrieve all versions for the branch [{}]", this.properties.getPom().getBranch());
}
private Task taskFromOption(int option) {
return ALL_TASKS.get(option);
}
int chosenOption() {
String input = System.console().readLine();
switch (input.toLowerCase()) {
case "q":
System.exit(0);
default:
return Integer.parseInt(input);
}
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, versionFromScRelease);
}
log.info("\n\n\n=== ARTIFACT DEPLOYMENT ===\n\nPress ENTER to deploy the artifacts {}", MSG);
boolean skipDeployment = skipStep();
if (!skipDeployment) {
this.releaser.deploy();
}
log.info("\n\n\n=== PUBLISHING DOCS ===\n\nPress ENTER to publish the docs {}", MSG);
boolean skipDocs = skipStep();
if (!skipDocs) {
this.releaser.publishDocs(versionFromScRelease);
}
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, versionFromScRelease);
}
}
log.info("\n\n\n=== PUSHING CHANGES===\n\nPress ENTER to push the commits {}", MSG);
boolean skipPush = skipStep();
if (!skipPush) {
this.releaser.pushCurrentBranch(project);
}
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(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);
this.releaser.createBlog(versionFromScRelease, projects);
}
}
class Task {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String MSG = "'q' to quit and 's' to skip\n\n";
final String header;
final String description;
final Consumer<Args> consumer;
Task(String header, String description, Consumer<Args> consumer) {
this.header = header;
this.description = description;
this.consumer = consumer;
}
void execute(Args args) {
boolean verbose = args.verbose;
printLog(verbose);
if (verbose) {
boolean skipStep = skipStep();
if (!skipStep) {
consumer.accept(args);
}
} else {
consumer.accept(args);
}
}
private void printLog(boolean shouldSkip) {
log.info("\n\n\n=== {} ===\n\n{} {}\n\n", header, description, shouldSkip ? MSG : "");
}
boolean skipStep() {
String input = System.console().readLine();
switch (input.toLowerCase()) {
case SKIP:
case "s":
return true;
case QUIT:
case "q":
System.exit(0);
return true;
default:
return false;
}
}
static Task task(String header, String description, Consumer<Args> function) {
return new Task(header, description, function);
}
}
class Args {
final Releaser releaser;
final File project;
final Projects projects;
final ProjectVersion originalVersion;
final ProjectVersion versionFromScRelease;
final ReleaserProperties properties;
final boolean verbose;
Args(Releaser releaser, File project, Projects projects, ProjectVersion originalVersion,
ProjectVersion versionFromScRelease, ReleaserProperties properties,
boolean verbose) {
this.releaser = releaser;
this.project = project;
this.projects = projects;
this.originalVersion = originalVersion;
this.versionFromScRelease = versionFromScRelease;
this.properties = properties;
this.verbose = verbose;
}
}

View File

@@ -7,7 +7,6 @@ import java.nio.file.Files;
import java.util.Iterator;
import org.apache.maven.model.Model;
import org.assertj.core.api.BDDAssertions;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
@@ -16,7 +15,6 @@ 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;
@@ -24,6 +22,7 @@ import org.springframework.cloud.release.internal.pom.ProjectVersion;
import org.springframework.cloud.release.internal.pom.TestPomReader;
import org.springframework.cloud.release.internal.pom.TestUtils;
import org.springframework.cloud.release.internal.project.ProjectBuilder;
import org.springframework.cloud.release.internal.template.TemplateGenerator;
import org.springframework.util.FileSystemUtils;
import static org.assertj.core.api.BDDAssertions.then;
@@ -105,6 +104,27 @@ public class AcceptanceTests {
.contains("I am pleased to announce that the Release Candidate 1 (RC1)");
}
@Test
public void should_generate_templates_only() throws Exception {
File origin = GitTestUtils.clonedProject(this.tmp.newFolder(), this.springCloudConsulProject);
pomVersionIsEqualTo(origin, "1.2.0.BUILD-SNAPSHOT");
pomParentVersionIsEqualTo(origin, "1.2.0.BUILD-SNAPSHOT");
File project = GitTestUtils.clonedProject(this.tmp.newFolder(), tmpFile("spring-cloud-consul"));
GitTestUtils.setOriginOnProjectToTmp(origin, project);
SpringReleaser releaser = templateOnlyReleaser(project, "Dalston.RC1", "1.2.0.RC1");
releaser.release();
then(this.gitUpdater.executed).isFalse();
then(emailTemplate()).exists();
then(emailTemplateContents())
.contains("Spring Cloud Dalston.RC1 available")
.contains("Spring Cloud Dalston RC1 Train release");
then(blogTemplate()).exists();
then(blogTemplateContents())
.contains("I am pleased to announce that the Release Candidate 1 (RC1)");
}
private Iterable<RevCommit> listOfCommits(File project) throws GitAPIException {
return GitTestUtils.openGitProject(project).log().call();
}
@@ -132,8 +152,7 @@ public class AcceptanceTests {
}
private void tagIsPresentInOrigin(File origin, String expectedTag) throws GitAPIException {
BDDAssertions
.then(GitTestUtils.openGitProject(origin).tagList()
then(GitTestUtils.openGitProject(origin).tagList()
.call().iterator().next().getName()).endsWith(expectedTag);
}
@@ -159,6 +178,25 @@ public class AcceptanceTests {
private SpringReleaser releaser(File projectFile, String branch, String expectedVersion) throws Exception {
ReleaserProperties properties = releaserProperties(projectFile, branch);
Releaser releaser = defaultReleaser(expectedVersion, properties);
return new SpringReleaser(releaser, properties) {
@Override int chosenOption() {
return 0;
}
};
}
private SpringReleaser templateOnlyReleaser(File projectFile, String branch, String expectedVersion) throws Exception {
ReleaserProperties properties = releaserProperties(projectFile, branch);
Releaser releaser = defaultReleaser(expectedVersion, properties);
return new SpringReleaser(releaser, properties) {
@Override int chosenOption() {
return 10;
}
};
}
private Releaser defaultReleaser(String expectedVersion, ReleaserProperties properties) throws Exception {
ProjectPomUpdater pomUpdater = new ProjectPomUpdater(properties);
ProjectBuilder projectBuilder = new ProjectBuilder(properties, pomUpdater);
TestProjectGitUpdater gitUpdater = new TestProjectGitUpdater(properties,
@@ -167,11 +205,7 @@ public class AcceptanceTests {
Releaser releaser = new Releaser(pomUpdater, projectBuilder, gitUpdater,
templateGenerator);
this.gitUpdater = gitUpdater;
return new SpringReleaser(releaser, properties) {
@Override boolean skipStep() {
return false;
}
};
return releaser;
}
private ReleaserProperties releaserProperties(File project, String branch) throws URISyntaxException {