Table done; fixes gh-111

This commit is contained in:
Marcin Grzejszczak
2018-11-19 18:38:43 +01:00
parent 4ab19000ab
commit 03666265f8
29 changed files with 333 additions and 147 deletions

View File

@@ -346,7 +346,7 @@ class PropertyVersionChanger extends AbstractVersionChanger {
this.propertyStorer = propertyStorer;
}
@Override public void apply(final VersionChange versionChange) throws XMLStreamException {
@Override public void apply(final VersionChange versionChange) {
this.versions.projects
.stream()
.filter(project -> {

View File

@@ -2,7 +2,6 @@ package org.springframework.cloud.release.internal.post;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -84,7 +83,7 @@ public class PostReleaseActions implements Closeable {
+ "is off. Set [releaser.git.update-all-test-samples] to [true] to change that");
return;
}
List<ProjectAndException> projectAndExceptions = this.properties.getGit()
List<ProjectUrlAndException> projectUrlAndExceptions = this.properties.getGit()
.getAllTestSampleUrls()
.entrySet()
.stream()
@@ -93,22 +92,21 @@ public class PostReleaseActions implements Closeable {
.flatMap(Collection::stream)
.collect(Collectors.toList());
log.info("Updated all samples!");
List<String> exceptionMessages = projectAndExceptions.stream()
.filter(ProjectAndException::hasException)
List<String> exceptionMessages = projectUrlAndExceptions.stream()
.filter(ProjectUrlAndException::hasException)
.map(e -> "Project [" + e.key + "] for url [" + e.url + "] "
+ "has exception [" + Arrays
.toString(NestedExceptionUtils.getMostSpecificCause(e.ex)
.getStackTrace()) + "]")
.collect(Collectors.toList());
if (!exceptionMessages.isEmpty()) {
log.warn("Exceptions were found while updating samples");
log.warn(String.join("\n", exceptionMessages));
throw new IllegalStateException("Exceptions were found while updating samples\n" + String.join("\n", exceptionMessages));
} else {
log.info("No exceptions were found while updating the samples");
}
}
private Future<List<ProjectAndException>> updateAllProjects(Projects projects, Map.Entry<String, List<String>> e) {
private Future<List<ProjectUrlAndException>> updateAllProjects(Projects projects, Map.Entry<String, List<String>> e) {
return SERVICE.submit(() -> {
String key = e.getKey();
List<String> value = e.getValue();
@@ -162,7 +160,7 @@ public class PostReleaseActions implements Closeable {
return new ProjectAndFuture(key, url, SERVICE.submit(runnable));
}
private ProjectAndException getResult(ProjectAndFuture projectAndFuture) {
private ProjectUrlAndException getResult(ProjectAndFuture projectAndFuture) {
Exception e = null;
try {
projectAndFuture.future.get(10, TimeUnit.MINUTES);
@@ -171,10 +169,10 @@ public class PostReleaseActions implements Closeable {
catch (Exception ex) {
e = ex;
}
return new ProjectAndException(projectAndFuture.key, projectAndFuture.url, e);
return new ProjectUrlAndException(projectAndFuture.key, projectAndFuture.url, e);
}
private List<ProjectAndException> getResult(Future<List<ProjectAndException>> future) {
private List<ProjectUrlAndException> getResult(Future<List<ProjectUrlAndException>> future) {
try {
return future.get(10, TimeUnit.MINUTES);
}
@@ -211,7 +209,7 @@ public class PostReleaseActions implements Closeable {
}
@Override
public void close() throws IOException {
public void close() {
SERVICE.shutdown();
}
}
@@ -229,12 +227,12 @@ class ProjectAndFuture {
}
}
class ProjectAndException {
class ProjectUrlAndException {
final String key;
final String url;
final Exception ex;
ProjectAndException(String key, String url, Exception ex) {
ProjectUrlAndException(String key, String url, Exception ex) {
this.key = key;
this.url = url;
this.ex = ex;

View File

@@ -66,8 +66,7 @@ class BlogTemplateGenerator {
return this.blogOutput;
}
catch (Exception e) {
log.warn("Exception occurred while trying to create a blog entry", e);
return null;
throw new IllegalStateException("Exception occurred while trying to create a blog entry", e);
}
}

View File

@@ -32,8 +32,7 @@ class EmailTemplateGenerator {
return this.emailOutput;
}
catch (Exception e) {
log.warn("Exception occurred while trying to generate an email template", e);
return null;
throw new IllegalStateException("Exception occurred while trying to generate an email template", e);
}
}
}

View File

@@ -52,6 +52,7 @@ class Notes {
return this.version;
}
@SuppressWarnings("unused")
public String getClosedMilestoneUrl() {
return this.closedMilestoneUrl;
}

View File

@@ -49,22 +49,7 @@ class ReleaseNotesTemplateGenerator {
return this.blogOutput;
}
catch (IOException e) {
log.warn("Exception occurred while trying to generate release notes", e);
return null;
}
}
private int fileSize(File cached) {
try {
int length = Files.readAllBytes(cached.toPath()).length;
if (length == 0) {
log.warn("Cached file has no contents!");
}
return length;
}
catch (IOException e) {
log.warn("Exception [" + e + "] occurred while trying to retrieve file length - will assume it's empty");
return 0;
throw new IllegalStateException("Exception occurred while trying to generate release notes", e);
}
}
}

View File

@@ -31,8 +31,7 @@ class TwitterTemplateGenerator {
return this.output;
}
catch (Exception e) {
log.warn("Exception occurred while trying to generate a twitter template", e);
return null;
throw new IllegalStateException("Exception occurred while trying to generate a twitter template", e);
}
}
}

View File

@@ -14,7 +14,7 @@ import static org.assertj.core.api.BDDAssertions.then;
*/
public class ReleaserPropertiesTests {
@Test
public void should_return_provided_working_dir_when_it_was_set() throws Exception {
public void should_return_provided_working_dir_when_it_was_set() {
String workingDir = "foo";
ReleaserProperties properties = new ReleaserProperties();
@@ -24,14 +24,14 @@ public class ReleaserPropertiesTests {
}
@Test
public void should_return_current_working_dir_when_it_was_not_previously_set() throws Exception {
public void should_return_current_working_dir_when_it_was_not_previously_set() {
ReleaserProperties properties = new ReleaserProperties();
then(properties.getWorkingDir()).isNotEmpty();
}
@Test
public void should_return_a_copy_of_properties() throws Exception {
public void should_return_a_copy_of_properties() {
ReleaserProperties properties = new ReleaserProperties();
properties.setWorkingDir("foo");
properties.setFixedVersions(map());

View File

@@ -68,7 +68,7 @@ public class ReleaserTests {
}
@Test
public void should_not_bump_versions_for_original_release_project() throws Exception {
public void should_not_bump_versions_for_original_release_project() {
releaser(() -> new ProjectVersion("original", "1.0.0.RELEASE"))
.rollbackReleaseVersion(this.pom,
new Projects(new ProjectVersion("changed", "1.0.0.RELEASE")),
@@ -79,7 +79,7 @@ public class ReleaserTests {
}
@Test
public void should_not_bump_versions_for_original_snapshot_project_and_current_snapshot() throws Exception {
public void should_not_bump_versions_for_original_snapshot_project_and_current_snapshot() {
releaser(() -> new ProjectVersion("original", "1.0.0.BUILD-SNAPSHOT"))
.rollbackReleaseVersion(this.pom,
new Projects(new ProjectVersion("changed", "1.0.0.BUILD-SNAPSHOT")),
@@ -90,7 +90,7 @@ public class ReleaserTests {
}
@Test
public void should_bump_versions_for_original_snapshot_project() throws Exception {
public void should_bump_versions_for_original_snapshot_project() {
ProjectVersion scReleaseVersion = new ProjectVersion("changed", "1.0.0.RELEASE");
releaser(() -> new ProjectVersion("original", "1.0.0.BUILD-SNAPSHOT"))
.rollbackReleaseVersion(this.pom,
@@ -105,28 +105,28 @@ public class ReleaserTests {
}
@Test
public void should_not_generate_email_for_snapshot_version() throws Exception {
public void should_not_generate_email_for_snapshot_version() {
releaser().createEmail(new ProjectVersion("original", "1.0.0.BUILD-SNAPSHOT"), projects());
then(this.templateGenerator).should(never()).email(any(Projects.class));
}
@Test
public void should_generate_email_for_release_version() throws Exception {
public void should_generate_email_for_release_version() {
releaser().createEmail(new ProjectVersion("original", "1.0.0.RELEASE"), projects());
then(this.templateGenerator).should().email(any(Projects.class));
}
@Test
public void should_not_close_milestone_for_snapshots() throws Exception {
public void should_not_close_milestone_for_snapshots() {
releaser().closeMilestone(new ProjectVersion("original", "1.0.0.BUILD-SNAPSHOT"));
then(this.projectGitHandler).should(never()).closeMilestone(any(ProjectVersion.class));
}
@Test
public void should_not_rollback_for_snapshots() throws Exception {
public void should_not_rollback_for_snapshots() {
releaser(() -> new ProjectVersion("original", "1.0.0.BUILD-SNAPSHOT"))
.rollbackReleaseVersion(null,
new Projects(new ProjectVersion("original", "1.0.0.BUILD-SNAPSHOT")),

View File

@@ -67,8 +67,7 @@ public class ProjectDocumentationUpdaterTests {
BDDAssertions.thenThrownBy(() ->
new ProjectDocumentationUpdater(properties, new ProjectGitHandler(properties)) {
@Override String readIndexHtmlContents(File indexHtml)
throws IOException {
@Override String readIndexHtmlContents(File indexHtml) {
return "";
}
}.updateDocsRepo(releaseTrainVersion, "vAngel.SR33"))
@@ -104,8 +103,7 @@ public class ProjectDocumentationUpdaterTests {
}
@Test
public void should_not_commit_if_the_same_version_is_already_there()
throws URISyntaxException {
public void should_not_commit_if_the_same_version_is_already_there() {
ProjectVersion releaseTrainVersion = new ProjectVersion("spring-cloud-sleuth", "1.3.4.SR10");
ReleaserProperties properties = new ReleaserProperties();
properties.getGit().setDocumentationUrl(this.clonedDocProject.toURI().toString());
@@ -120,7 +118,7 @@ public class ProjectDocumentationUpdaterTests {
@Test
public void should_not_update_current_version_in_the_docs_if_current_release_starts_with_lower_letter_than_the_stored_release()
throws URISyntaxException, IOException {
throws IOException {
ProjectVersion releaseTrainVersion = new ProjectVersion("spring-cloud-sleuth", "1.3.4.SR10");
ReleaserProperties properties = new ReleaserProperties();
properties.getGit().setDocumentationUrl(this.clonedDocProject.toURI().toString());
@@ -136,7 +134,7 @@ public class ProjectDocumentationUpdaterTests {
@Test
public void should_update_current_version_in_the_docs_if_current_release_starts_with_v_and_then_higher_letter_than_the_stored_release()
throws URISyntaxException, IOException {
throws IOException {
ProjectVersion releaseTrainVersion = new ProjectVersion("spring-cloud-sleuth", "2.0.0.SR33");
ReleaserProperties properties = new ReleaserProperties();
properties.getGit().setDocumentationUrl(this.clonedDocProject.toURI().toString());
@@ -152,7 +150,7 @@ public class ProjectDocumentationUpdaterTests {
@Test
public void should_update_current_version_in_the_docs_if_current_release_starts_with_higher_letter_than_the_stored_release()
throws URISyntaxException, IOException {
throws IOException {
ProjectVersion releaseTrainVersion = new ProjectVersion("spring-cloud-sleuth", "2.0.0.SR33");
ReleaserProperties properties = new ReleaserProperties();
properties.getGit().setDocumentationUrl(this.clonedDocProject.toURI().toString());
@@ -167,8 +165,7 @@ public class ProjectDocumentationUpdaterTests {
}
@Test
public void should_not_update_current_version_in_the_docs_if_switch_is_off()
throws URISyntaxException, IOException {
public void should_not_update_current_version_in_the_docs_if_switch_is_off() {
ProjectVersion releaseTrainVersion = new ProjectVersion("spring-cloud-sleuth", "2.0.0.SR33");
ReleaserProperties properties = new ReleaserProperties();
properties.getGit().setDocumentationUrl(this.clonedDocProject.toURI().toString());

View File

@@ -54,7 +54,7 @@ public class GitRepoTests {
}
@Test
public void should_throw_exception_when_there_is_no_repo() throws IOException, URISyntaxException {
public void should_throw_exception_when_there_is_no_repo() {
thenThrownBy(() -> this.gitRepo
.cloneProject(new URIish(GitRepoTests.class.getResource("/projects/").toURI().toURL())))
.isInstanceOf(IllegalStateException.class)
@@ -62,7 +62,7 @@ public class GitRepoTests {
}
@Test
public void should_throw_an_exception_when_failed_to_initialize_the_repo() throws IOException {
public void should_throw_an_exception_when_failed_to_initialize_the_repo() {
thenThrownBy(() -> new GitRepo(this.tmpFolder,
new ExceptionThrowingJGitFactory()).cloneProject(new URIish(this.springCloudReleaseProject.toURI().toURL())))
.isInstanceOf(IllegalStateException.class)

View File

@@ -35,13 +35,13 @@ public class GithubIssuesTests {
@Rule public OutputCapture capture = new OutputCapture();
@Before
public void setup() throws URISyntaxException, IOException {
public void setup() throws IOException {
this.github = new MkGithub("spring-guides");
this.repo = createGettingStartedGuides(this.github);
}
@Test
public void should_not_do_anything_for_non_release_train_version() throws IOException {
public void should_not_do_anything_for_non_release_train_version() {
Github github = BDDMockito.mock(Github.class);
GithubIssues issues = new GithubIssues(github, withToken());
@@ -53,7 +53,7 @@ public class GithubIssuesTests {
}
@Test
public void should_not_do_anything_if_switch_is_not_set() throws IOException {
public void should_not_do_anything_if_switch_is_not_set() {
Github github = BDDMockito.mock(Github.class);
ReleaserProperties properties = withToken();
properties.getGit().setUpdateSpringGuides(false);

View File

@@ -32,7 +32,7 @@ public class GithubMilestonesTests {
@Rule public OutputCapture capture = new OutputCapture();
@Before
public void setup() throws URISyntaxException, IOException {
public void setup() throws IOException {
this.github = new MkGithub();
this.repo = createSleuthRepo(this.github);
}
@@ -44,8 +44,7 @@ public class GithubMilestonesTests {
return GithubMilestonesTests.this.repo.coordinates().user();
}
@Override String milestoneTitle(Milestone.Smart milestone)
throws IOException {
@Override String milestoneTitle(Milestone.Smart milestone) {
return "0.2.0.BUILD-SNAPSHOT";
}
};
@@ -63,8 +62,7 @@ public class GithubMilestonesTests {
return GithubMilestonesTests.this.repo.coordinates().user();
}
@Override String milestoneTitle(Milestone.Smart milestone)
throws IOException {
@Override String milestoneTitle(Milestone.Smart milestone) {
return "0.2.0";
}
};
@@ -86,8 +84,7 @@ public class GithubMilestonesTests {
return GithubMilestonesTests.this.repo.coordinates().user();
}
@Override String milestoneTitle(Milestone.Smart milestone)
throws IOException {
@Override String milestoneTitle(Milestone.Smart milestone) {
return "0.2.0";
}
};
@@ -105,8 +102,7 @@ public class GithubMilestonesTests {
return GithubMilestonesTests.this.repo.coordinates().user();
}
@Override String milestoneTitle(Milestone.Smart milestone)
throws IOException {
@Override String milestoneTitle(Milestone.Smart milestone) {
return "0.2.0.RELEASE";
}
@@ -123,7 +119,7 @@ public class GithubMilestonesTests {
}
@Test
public void should_fetch_url_of_a_closed_matching_milestone_from_cache() throws IOException {
public void should_fetch_url_of_a_closed_matching_milestone_from_cache() {
GithubMilestones milestones = new GithubMilestones(this.github, withToken());
GithubMilestones.MILESTONE_URL_CACHE.put(gaSleuthProject(), "https://github.com/spring-cloud/spring-cloud-sleuth/milestone/33?closed=1");
@@ -133,14 +129,13 @@ public class GithubMilestonesTests {
}
@Test
public void should_return_null_if_no_matching_milestone_was_found() throws IOException {
public void should_return_null_if_no_matching_milestone_was_found() {
GithubMilestones milestones = new GithubMilestones(this.github, withToken()) {
@Override String org() {
return GithubMilestonesTests.this.repo.coordinates().user();
}
@Override String milestoneTitle(Milestone.Smart milestone)
throws IOException {
@Override String milestoneTitle(Milestone.Smart milestone) {
return "0.9.0.RELEASE";
}
@@ -162,8 +157,7 @@ public class GithubMilestonesTests {
return GithubMilestonesTests.this.repo.coordinates().user();
}
@Override String milestoneTitle(Milestone.Smart milestone)
throws IOException {
@Override String milestoneTitle(Milestone.Smart milestone) {
return "0.2.0";
}
};
@@ -185,8 +179,7 @@ public class GithubMilestonesTests {
return GithubMilestonesTests.this.repo.coordinates().user();
}
@Override String milestoneTitle(Milestone.Smart milestone)
throws IOException {
@Override String milestoneTitle(Milestone.Smart milestone) {
return "0.1.0.BUILD-SNAPSHOT";
}
};

View File

@@ -56,7 +56,7 @@ public class GradleUpdaterTests {
}
@Test
public void should_throw_exception_if_snapshots_remain() throws IOException {
public void should_throw_exception_if_snapshots_remain() {
File projectRoot = tmpFile("gradleproject");
ReleaserProperties properties = new ReleaserProperties();
Map<String, String> props = new HashMap<String, String>() {{

View File

@@ -22,7 +22,7 @@ public class BomParserTests {
ReleaserProperties properties = new ReleaserProperties();
@Before
public void setup() throws IOException, URISyntaxException {
public void setup() throws URISyntaxException {
this.springCloudReleaseProject = new File(GitRepoTests.class.getResource("/projects/spring-cloud-release").toURI());
}

View File

@@ -19,97 +19,97 @@ public class LoggerToMavenLogTests {
@InjectMocks LoggerToMavenLog loggerToMavenLog;
RuntimeException exception = new RuntimeException();
@Test public void isDebugEnabled() throws Exception {
@Test public void isDebugEnabled() {
this.loggerToMavenLog.isDebugEnabled();
then(this.logger).should().isDebugEnabled();
}
@Test public void debug() throws Exception {
@Test public void debug() {
this.loggerToMavenLog.debug("foo");
then(this.logger).should().debug("foo");
}
@Test public void debug1() throws Exception {
@Test public void debug1() {
this.loggerToMavenLog.debug("foo", this.exception);
then(this.logger).should().debug("foo", this.exception);
}
@Test public void debug2() throws Exception {
@Test public void debug2() {
this.loggerToMavenLog.debug(this.exception);
then(this.logger).should().debug("Exception occurred", this.exception);
}
@Test public void isInfoEnabled() throws Exception {
@Test public void isInfoEnabled() {
this.loggerToMavenLog.isInfoEnabled();
then(this.logger).should().isInfoEnabled();
}
@Test public void info() throws Exception {
@Test public void info() {
this.loggerToMavenLog.info("foo");
then(this.logger).should().info("foo");
}
@Test public void info1() throws Exception {
@Test public void info1() {
this.loggerToMavenLog.info("foo", this.exception);
then(this.logger).should().info("foo", this.exception);
}
@Test public void info2() throws Exception {
@Test public void info2() {
this.loggerToMavenLog.info(this.exception);
then(this.logger).should().info("Exception occurred", this.exception);
}
@Test public void isWarnEnabled() throws Exception {
@Test public void isWarnEnabled() {
this.loggerToMavenLog.isWarnEnabled();
then(this.logger).should().isWarnEnabled();
}
@Test public void warn() throws Exception {
@Test public void warn() {
this.loggerToMavenLog.warn("foo");
then(this.logger).should().warn("foo");
}
@Test public void warn1() throws Exception {
@Test public void warn1() {
this.loggerToMavenLog.warn("foo", this.exception);
then(this.logger).should().warn("foo", this.exception);
}
@Test public void warn2() throws Exception {
@Test public void warn2() {
this.loggerToMavenLog.warn(this.exception);
then(this.logger).should().warn("Exception occurred", this.exception);
}
@Test public void isErrorEnabled() throws Exception {
@Test public void isErrorEnabled() {
this.loggerToMavenLog.isErrorEnabled();
then(this.logger).should().isErrorEnabled();
}
@Test public void error() throws Exception {
@Test public void error() {
this.loggerToMavenLog.error("foo");
then(this.logger).should().error("foo");
}
@Test public void error1() throws Exception {
@Test public void error1() {
this.loggerToMavenLog.error("foo", this.exception);
then(this.logger).should().error("foo", this.exception);
}
@Test public void error2() throws Exception {
@Test public void error2() {
this.loggerToMavenLog.error(this.exception);
then(this.logger).should().error("Exception occurred", this.exception);

View File

@@ -21,7 +21,7 @@ public class PropertyStorerTests {
@Mock ModifiedPomXMLEventReader pom;
@InjectMocks PropertyStorer propertyStorer;
@Test public void should_not_set_a_version_when_its_empty() throws Exception {
@Test public void should_not_set_a_version_when_its_empty() {
this.propertyStorer.setPropertyVersionIfApplicable(new Project("foo", ""));
then(this.log).should().warn(containsWarnMsgAboutEmptyVersion());

View File

@@ -196,7 +196,7 @@ public class ProjectBuilderTests {
}
@Test
public void should_throw_exception_when_after_running_there_is_an_html_file_with_unresolved_tag() throws Exception {
public void should_throw_exception_when_after_running_there_is_an_html_file_with_unresolved_tag() {
ReleaserProperties properties = new ReleaserProperties();
properties.getMaven().setBuildCommand("ls -al");
properties.setWorkingDir(tmpFile("/builder/unresolved").getPath());
@@ -207,7 +207,7 @@ public class ProjectBuilderTests {
}
@Test
public void should_throw_exception_when_command_took_too_long_to_execute() throws Exception {
public void should_throw_exception_when_command_took_too_long_to_execute() {
ReleaserProperties properties = new ReleaserProperties();
properties.getMaven().setBuildCommand("sleep 1");
properties.getMaven().setWaitTimeInMinutes(0);
@@ -312,7 +312,7 @@ public class ProjectBuilderTests {
}
@Test
public void should_throw_exception_when_deploy_command_took_too_long_to_execute() throws Exception {
public void should_throw_exception_when_deploy_command_took_too_long_to_execute() {
ReleaserProperties properties = new ReleaserProperties();
properties.getMaven().setDeployCommand("sleep 1");
properties.getMaven().setWaitTimeInMinutes(0);
@@ -404,7 +404,7 @@ public class ProjectBuilderTests {
}
@Test
public void should_throw_exception_when_publish_docs_command_took_too_long_to_execute() throws Exception {
public void should_throw_exception_when_publish_docs_command_took_too_long_to_execute() {
ReleaserProperties properties = new ReleaserProperties();
properties.getMaven().setPublishDocsCommands(new String[] { "sleep 1", "sleep 1" });
properties.getMaven().setWaitTimeInMinutes(0);
@@ -415,7 +415,7 @@ public class ProjectBuilderTests {
}
@Test
public void should_throw_exception_when_process_exits_with_invalid_code() throws Exception {
public void should_throw_exception_when_process_exits_with_invalid_code() {
ReleaserProperties properties = new ReleaserProperties();
properties.getMaven().setBuildCommand("exit 1");
properties.setWorkingDir(tmpFile("/builder/unresolved").getPath());
@@ -423,7 +423,7 @@ public class ProjectBuilderTests {
@Override
ProcessExecutor executor(String workingDir) {
return new ProcessExecutor(properties.getWorkingDir()) {
@Override Process startProcess(ProcessBuilder builder) throws IOException {
@Override Process startProcess(ProcessBuilder builder) {
return processWithInvalidExitCode();
}
};
@@ -448,7 +448,7 @@ public class ProjectBuilderTests {
return null;
}
@Override public int waitFor() throws InterruptedException {
@Override public int waitFor() {
return 0;
}

View File

@@ -44,7 +44,7 @@ public class SaganUpdaterTest {
return release;
}
@Test public void should_not_update_sagan_when_switch_is_off() throws Exception {
@Test public void should_not_update_sagan_when_switch_is_off() {
this.properties.getSagan().setUpdateSagan(false);
this.saganUpdater.updateSagan("master", version("1.0.0.M1"), version("1.0.0.M1"));
@@ -52,7 +52,7 @@ public class SaganUpdaterTest {
then(this.saganClient).shouldHaveZeroInteractions();
}
@Test public void should_update_sagan_for_milestone() throws Exception {
@Test public void should_update_sagan_for_milestone() {
this.saganUpdater.updateSagan("master", version("1.0.0.M1"), version("1.0.0.M1"));
then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"),
@@ -60,7 +60,7 @@ public class SaganUpdaterTest {
"http://cloud.spring.io/spring-cloud-static/foo/{version}/", "PRERELEASE")));
}
@Test public void should_update_sagan_for_rc() throws Exception {
@Test public void should_update_sagan_for_rc() {
this.saganUpdater.updateSagan("master", version("1.0.0.RC1"), version("1.0.0.RC1"));
then(this.saganClient).should().updateRelease(BDDMockito.eq("foo"),
@@ -72,7 +72,7 @@ public class SaganUpdaterTest {
return new ProjectVersion("foo", version);
}
@Test public void should_update_sagan_from_master() throws Exception {
@Test public void should_update_sagan_from_master() {
ProjectVersion projectVersion = version("1.0.0.BUILD-SNAPSHOT");
this.saganUpdater.updateSagan("master", projectVersion, projectVersion);
@@ -82,7 +82,7 @@ public class SaganUpdaterTest {
"http://cloud.spring.io/foo/foo.html", "SNAPSHOT")));
}
@Test public void should_update_sagan_from_release_version() throws Exception {
@Test public void should_update_sagan_from_release_version() {
ProjectVersion projectVersion = version("1.0.0.RELEASE");
this.saganUpdater.updateSagan("master", projectVersion, projectVersion);
@@ -98,7 +98,7 @@ public class SaganUpdaterTest {
"http://cloud.spring.io/foo/foo.html", "SNAPSHOT")));
}
@Test public void should_update_sagan_from_non_master() throws Exception {
@Test public void should_update_sagan_from_non_master() {
ProjectVersion projectVersion = version("1.1.0.BUILD-SNAPSHOT");
this.saganUpdater.updateSagan("1.1.x", projectVersion, projectVersion);

View File

@@ -45,6 +45,11 @@
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency>
<groupId>com.jakewharton.fliptables</groupId>
<artifactId>fliptables</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -45,7 +45,7 @@ public class ReleaserApplication implements CommandLineRunner {
@Autowired SpringReleaser releaser;
@Autowired Parser parser;
@Override public void run(String... strings) throws Exception {
@Override public void run(String... strings) {
Options options = this.parser.parse(strings);
try {
this.releaser.release(options);

View File

@@ -37,11 +37,11 @@ class Task {
this.taskType = taskType;
}
void execute(Args args) {
TaskAndException execute(Args args) {
if (args.taskType != this.taskType) {
log.info("Skipping [{}] since task type is [{}] and should be [{}]]",
this.name, this.taskType, args.taskType);
return;
return TaskAndException.skipped(this);
}
try {
boolean interactive = args.interactive;
@@ -49,18 +49,28 @@ class Task {
if (interactive) {
boolean skipStep = stepSkipper.skipStep();
if (!skipStep) {
this.consumer.accept(args);
return runTask(args);
}
return TaskAndException.skipped(this);
} else {
this.consumer.accept(args);
return runTask(args);
}
} catch (Exception e) {
log.error("\n\n\nBUILD FAILED!!!\n\nException occurred for task <" +
log.error("\n\n\nBUILD FAILED!!!\n\nException occurred for project <" +
(args.project != null ? args.project.getName() : "") + "> task <" +
this.name + "> \n\nwith description <" + this.description + ">\n\n", e);
throw e;
if (this.taskType == TaskType.RELEASE) {
throw e;
}
return TaskAndException.failure(this, e);
}
}
private TaskAndException runTask(Args args) {
this.consumer.accept(args);
return TaskAndException.success(this);
}
private void printLog(boolean interactive) {
log.info("\n\n\n=== {} ===\n\n{} {}\n\n", this.header, this.description, interactive ? MSG : "");
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2013-2018 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
*
* http://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.spring;
/**
* @author Marcin Grzejszczak
*/
class TaskAndException {
final Task task;
final TaskState taskState;
final Exception exception;
private TaskAndException(Task task, TaskState taskState) {
this.task = task;
this.taskState = taskState;
this.exception = null;
}
private TaskAndException(Task task, TaskState taskState, Exception exception) {
this.task = task;
this.taskState = taskState;
this.exception = exception;
}
static TaskAndException skipped(Task task) {
return new TaskAndException(task, TaskState.SKIPPED);
}
static TaskAndException success(Task task) {
return new TaskAndException(task, TaskState.SUCCESS);
}
static TaskAndException failure(Task task, Exception exception) {
return new TaskAndException(task, TaskState.FAILURE, exception);
}
enum TaskState {
SKIPPED, SUCCESS, FAILURE
}
}

View File

@@ -1,11 +1,18 @@
package org.springframework.cloud.release.internal.spring;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.jakewharton.fliptables.FlipTableConverters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
/**
* All tasks that can be executed by the releaser
*
@@ -135,23 +142,22 @@ class Tasks {
static Task RELEASE = Tasks.task("release", "fr",
"FULL RELEASE",
"Perform a full release of this project without interruptions",
args -> DEFAULT_TASKS_PER_PROJECT.forEach(task -> task.execute(args)));
args -> new CompositeConsumer(DEFAULT_TASKS_PER_PROJECT).accept(args));
static Task POST_RELEASE = Tasks.task("postRelease", "pr",
"POST RELEASE TASKS",
"Perform post release tasks for this release without interruptions",
args -> DEFAULT_TASKS_PER_RELEASE.forEach(task -> task.execute(args)),
args -> new CompositeConsumer(DEFAULT_TASKS_PER_RELEASE).accept(args),
TaskType.POST_RELEASE);
static Task RELEASE_VERBOSE = Tasks.task("releaseVerbose", "r",
"FULL VERBOSE RELEASE",
"Perform a full release of this project in interactive mode (you'll be asked about skipping steps)",
args -> DEFAULT_TASKS_PER_PROJECT.forEach(task -> task.execute(args)));
args -> new CompositeConsumer(DEFAULT_TASKS_PER_PROJECT).accept(args));
static Task META_RELEASE = Tasks.task("metaRelease", "x",
"META RELEASE",
"Perform a meta release of projects",
args -> DEFAULT_TASKS_PER_PROJECT.forEach(task -> {
args.properties.getMetaRelease().setEnabled(true);
task.execute(args);
}));
args -> new CompositeConsumer(DEFAULT_TASKS_PER_PROJECT,
(args1 -> args.properties.getMetaRelease().setEnabled(true)))
.accept(args));
static final List<Task> COMPOSITE_TASKS = Stream.of(
RELEASE,
@@ -187,4 +193,83 @@ class Tasks {
enum TaskType {
RELEASE, POST_RELEASE
}
class CompositeConsumer implements Consumer<Args> {
private static final Logger log = LoggerFactory.getLogger(CompositeConsumer.class);
private final List<Task> tasks;
private final Consumer<Args> setup;
CompositeConsumer(List<Task> tasks) {
this.tasks = tasks;
this.setup = args -> {};
}
CompositeConsumer(List<Task> tasks, Consumer<Args> setup) {
this.tasks = tasks;
this.setup = setup;
}
@Override
public void accept(Args args) {
this.setup.accept(args);
List<Table> table = this.tasks.stream()
.map(task -> new Table(task.execute(args)))
.collect(Collectors.toList());
String string = "\n\n***** BUILD REPORT *****\n\n"
+ FlipTableConverters.fromIterable(table, Table.class)
+ "\n\n***** BUILD REPORT *****\n\n";
List<Table> brokenTasks = table.stream()
.filter(table1 -> StringUtils.hasText(table1.thrownException))
.collect(Collectors.toList());
if (!brokenTasks.isEmpty()) {
String brokenBuilds = "\n\n[BUILD UNSTABLE] One of the tasks is failing!\n\n" +
FlipTableConverters.fromIterable(brokenTasks, Table.class) + "\n\n";
log.info(string + brokenBuilds);
throw new IllegalStateException("[BUILD UNSTABLE] One of the tasks is failing! + \n\n\n" + brokenBuilds);
} else {
log.info(string);
}
}
}
class Table {
final String taskCaption;
final String taskDescription;
final String taskState;
final String thrownException;
Table(TaskAndException tae) {
this.taskCaption = tae.task.name;
this.taskDescription = tae.task.description;
this.taskState = tae.taskState.name().toLowerCase();
this.thrownException = tae.exception == null ? "" : Arrays
.stream(tae.exception.getStackTrace())
.map(s -> {
String[] strings = s.toString().split("\\.");
return strings[strings.length - 3] + "." + strings[strings.length - 2] + "." + strings[strings.length - 1];
})
.limit(15)
.collect(Collectors.joining("\n"));
}
public String getTaskCaption() {
return this.taskCaption;
}
public String getTaskDescription() {
return this.taskDescription;
}
public String getTaskState() {
return this.taskState;
}
public String getThrownException() {
return this.thrownException;
}
}

View File

@@ -40,7 +40,7 @@ public class TestDocumentationUpdater extends DocumentationUpdater {
}
@Override
String readIndexHtmlContents(File indexHtml) throws IOException {
String readIndexHtmlContents(File indexHtml) {
return response();
}

View File

@@ -526,7 +526,7 @@ public class AcceptanceTests {
return this.testPomReader.readPom(new File(dir, "pom.xml"));
}
private File emailTemplate() throws URISyntaxException {
private File emailTemplate() {
return new File("target/email.txt");
}
@@ -534,15 +534,15 @@ public class AcceptanceTests {
return new String(Files.readAllBytes(emailTemplate().toPath()));
}
private File blogTemplate() throws URISyntaxException {
private File blogTemplate() {
return new File("target/blog.md");
}
private File tweetTemplate() throws URISyntaxException {
private File tweetTemplate() {
return new File("target/tweet.txt");
}
private File releaseNotesTemplate() throws URISyntaxException {
private File releaseNotesTemplate() {
return new File("target/notes.md");
}
@@ -620,7 +620,7 @@ public class AcceptanceTests {
}
private Releaser defaultReleaser(String expectedVersion, String projectName,
ReleaserProperties properties) throws Exception {
ReleaserProperties properties) {
ProjectPomUpdater pomUpdater = new ProjectPomUpdater(properties);
ProjectBuilder projectBuilder = new ProjectBuilder(properties);
TestProjectGitHandler handler = new TestProjectGitHandler(properties,
@@ -644,7 +644,7 @@ public class AcceptanceTests {
return releaser;
}
private Releaser defaultMetaReleaser(ReleaserProperties properties) throws Exception {
private Releaser defaultMetaReleaser(ReleaserProperties properties) {
ProjectPomUpdater pomUpdater = new ProjectPomUpdater(properties);
ProjectBuilder projectBuilder = new ProjectBuilder(properties);
NonAssertingTestProjectGitHandler handler = new NonAssertingTestProjectGitHandler(properties);

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2013-2018 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
*
* http://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.spring;
import java.util.Arrays;
import org.assertj.core.api.BDDAssertions;
import org.junit.Test;
/**
* @author Marcin Grzejszczak
*/
public class CompositeConsumerTests {
@Test
public void should_throw_exception_for_a_release_task() {
CompositeConsumer compositeConsumer = new CompositeConsumer(Arrays.asList(
new Task("foo", "foo", "foo", "foo",
(args -> {})),
new Task("bar", "bar", "bar", "bar",
(args -> { throw new MyException(); }))
));
BDDAssertions.thenThrownBy(() ->
compositeConsumer.accept(new Args(TaskType.RELEASE)))
.isInstanceOf(MyException.class);
}
@Test
public void should_throw_exception_for_a_post_release_task_after_creating_a_report() {
CompositeConsumer compositeConsumer = new CompositeConsumer(Arrays.asList(
new Task("foo", "foo", "foo", "foo",
(args -> {}), TaskType.POST_RELEASE),
new Task("bar", "bar", "bar", "bar",
(args -> { throw new MyException(); }), TaskType.POST_RELEASE)
));
BDDAssertions.thenThrownBy(() ->
compositeConsumer.accept(new Args(TaskType.POST_RELEASE)))
.isInstanceOf(IllegalStateException.class);
}
}
class MyException extends RuntimeException {}

View File

@@ -50,7 +50,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_throw_exception_when_an_invalid_option_was_picked() throws Exception {
public void should_throw_exception_when_an_invalid_option_was_picked() {
Options options = nonInteractiveOpts().options();
thenThrownBy(() -> this.optionsProcessor.processOptions(options, args()))
@@ -58,7 +58,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_only_tasks_after_the_provided_one_using_full_name() throws Exception {
public void should_execute_only_tasks_after_the_provided_one_using_full_name() {
Options options = nonInteractiveOpts().startFrom("second").options();
this.optionsProcessor.processOptions(options, args());
@@ -70,7 +70,7 @@ public class OptionsProcessorTests {
@Test
public void should_execute_only_tasks_after_the_provided_one_using_short_name() throws Exception {
public void should_execute_only_tasks_after_the_provided_one_using_short_name() {
Options options = nonInteractiveOpts().startFrom("2").options();
this.optionsProcessor.processOptions(options, args());
@@ -81,7 +81,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_only_tasks_from_range_using_full_name() throws Exception {
public void should_execute_only_tasks_from_range_using_full_name() {
Options options = nonInteractiveOpts().range("second-third").options();
this.optionsProcessor.processOptions(options, args());
@@ -92,7 +92,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_only_tasks_from_range_using_short_name() throws Exception {
public void should_execute_only_tasks_from_range_using_short_name() {
Options options = nonInteractiveOpts().range("2-3").options();
this.optionsProcessor.processOptions(options, args());
@@ -103,7 +103,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_only_tasks_from_range_using_full_name_with_same_range() throws Exception {
public void should_execute_only_tasks_from_range_using_full_name_with_same_range() {
Options options = nonInteractiveOpts().range("second-second").options();
this.optionsProcessor.processOptions(options, args());
@@ -114,7 +114,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_only_tasks_from_range_using_short_name_with_same_range() throws Exception {
public void should_execute_only_tasks_from_range_using_short_name_with_same_range() {
Options options = nonInteractiveOpts().range("2-2").options();
this.optionsProcessor.processOptions(options, args());
@@ -125,7 +125,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_only_tasks_from_multi_using_full_name() throws Exception {
public void should_execute_only_tasks_from_multi_using_full_name() {
Options options = nonInteractiveOpts().taskNames(list("first", "third")).options();
this.optionsProcessor.processOptions(options, args());
@@ -136,7 +136,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_only_tasks_from_multi_using_short_name() throws Exception {
public void should_execute_only_tasks_from_multi_using_short_name() {
Options options = nonInteractiveOpts().taskNames(list("1", "3")).options();
this.optionsProcessor.processOptions(options, args());
@@ -147,7 +147,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_interactively_only_single_task() throws Exception {
public void should_execute_interactively_only_single_task() {
this.optionsProcessor = new OptionsProcessor(this.releaser, new ReleaserProperties(), this.tasks) {
@Override String chosenOption() {
return "0";
@@ -163,7 +163,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_interactively_range_of_tasks() throws Exception {
public void should_execute_interactively_range_of_tasks() {
this.optionsProcessor = new OptionsProcessor(this.releaser, new ReleaserProperties(), this.tasks) {
@Override String chosenOption() {
return "0-1";
@@ -179,7 +179,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_interactively_start_from() throws Exception {
public void should_execute_interactively_start_from() {
this.optionsProcessor = new OptionsProcessor(this.releaser, new ReleaserProperties(), this.tasks) {
@Override String chosenOption() {
return "1-";
@@ -195,7 +195,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_interactively_multi() throws Exception {
public void should_execute_interactively_multi() {
this.optionsProcessor = new OptionsProcessor(this.releaser, new ReleaserProperties(), this.tasks) {
@Override String chosenOption() {
return "0,2";
@@ -211,7 +211,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_full_release() throws Exception {
public void should_execute_full_release() {
this.optionsProcessor = new OptionsProcessor(this.releaser, new ReleaserProperties(), this.tasks) {
@Override Task releaseTask() {
return OptionsProcessorTests.this.firstTask;
@@ -231,7 +231,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_execute_full_verbose_release() throws Exception {
public void should_execute_full_verbose_release() {
this.optionsProcessor = new OptionsProcessor(this.releaser, new ReleaserProperties(), this.tasks) {
@Override Task releaseVerboseTask() {
return OptionsProcessorTests.this.firstTask;
@@ -251,7 +251,7 @@ public class OptionsProcessorTests {
}
@Test
public void should_remove_single_quotes() throws Exception {
public void should_remove_single_quotes() {
Options options = interactiveOpts().fullRelease(true)
.range("'1-2'")
.startFrom("'c'")

View File

@@ -43,7 +43,7 @@ public class TaskTests {
then(someBool.get()).isTrue();
then(this.capture.toString())
.contains("BUILD FAILED!!!")
.contains("Exception occurred for task <foo>")
.contains("Exception occurred for project <> task <foo>")
.contains("with description <descr>");
}
}