From fb606766384953fd38812124be2aa40a98d3cd80 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Thu, 9 Mar 2017 16:32:10 +0100 Subject: [PATCH] Added docs publishing --- .../cloud/release/internal/Releaser.java | 24 ++- .../release/internal/ReleaserProperties.java | 45 +++++- .../release/internal/pom/PomUpdater.java | 11 +- .../Project.java} | 43 +++-- .../internal/ReleaserPropertiesTests.java | 28 ++++ .../internal/builder/ProjectBuilderTests.java | 88 ----------- .../internal/project/ProjectBuilderTests.java | 147 ++++++++++++++++++ .../release/spring/ReleaserConfiguration.java | 4 +- 8 files changed, 268 insertions(+), 122 deletions(-) rename spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/{builder/ProjectBuilder.java => project/Project.java} (71%) create mode 100644 spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/ReleaserPropertiesTests.java delete mode 100644 spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/builder/ProjectBuilderTests.java create mode 100644 spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/project/ProjectBuilderTests.java 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 97a96a2f..06616488 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 @@ -2,11 +2,10 @@ package org.springframework.cloud.release.internal; import java.io.File; import java.lang.invoke.MethodHandles; -import java.util.Scanner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cloud.release.internal.builder.ProjectBuilder; +import org.springframework.cloud.release.internal.project.Project; import org.springframework.cloud.release.internal.git.ProjectGitUpdater; import org.springframework.cloud.release.internal.pom.ProjectUpdater; import org.springframework.cloud.release.internal.pom.ProjectVersion; @@ -23,20 +22,19 @@ public class Releaser { private final ReleaserProperties properties; private final ProjectUpdater projectUpdater; - private final ProjectBuilder projectBuilder; + private final Project project; private final ProjectGitUpdater projectGitUpdater; public Releaser(ReleaserProperties properties, ProjectUpdater projectUpdater, - ProjectBuilder projectBuilder, ProjectGitUpdater projectGitUpdater) { + Project project, ProjectGitUpdater projectGitUpdater) { this.properties = properties; this.projectUpdater = projectUpdater; - this.projectBuilder = projectBuilder; + this.project = project; this.projectGitUpdater = projectGitUpdater; } public void release() { - String workingDir = StringUtils.hasText(this.properties.getWorkingDir()) ? - this.properties.getWorkingDir() : System.getProperty("user.dir"); + String workingDir = this.properties.getWorkingDir(); File project = new File(workingDir); log.info("\n\n\n=== UPDATING POMS ===\n\nWill run the application " + "for root folder [{}]. \n\nPress ENTER to continue {}", workingDir, MSG); @@ -49,7 +47,7 @@ public class Releaser { log.info("\n\n\n=== BUILD PROJECT ===\n\nPress ENTER to build the project {}", MSG); boolean skipBuild = skipStep(); if (!skipBuild) { - this.projectBuilder.build(); + this.project.build(); log.info("\nProject was successfully built"); } log.info("\n\n\n=== COMMITTING AND PUSHING TAGS ===\n\nPress ENTER to commit, tag and push the tag {}", MSG); @@ -57,6 +55,16 @@ public class Releaser { if (!skipCommit) { this.projectGitUpdater.commitAndTagIfApplicable(project, version); } + log.info("\n\n\n=== ARTIFACT DEPLOYMENT ===\n\nPress ENTER to deploy the artifacts {}", MSG); + boolean skipDeployment = skipStep(); + if (!skipDeployment) { + this.project.deploy(); + } + log.info("\n\n\n=== PUBLISHING DOCS ===\n\nPress ENTER to deploy the artifacts {}", MSG); + boolean skipDocs = skipStep(); + if (!skipDocs) { + this.project.publishDocs(); + } } boolean skipStep() { 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 d15c5af2..56421e0d 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 @@ -18,6 +18,7 @@ package org.springframework.cloud.release.internal; import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.StringUtils; import edu.emory.mathcs.backport.java.util.Arrays; @@ -37,6 +38,8 @@ public class ReleaserProperties { private Pom pom = new Pom(); + private Docs docs = new Docs(); + private Maven maven = new Maven(); public static class Git { @@ -102,6 +105,18 @@ public class ReleaserProperties { } } + public static class Docs { + private String ghPagesUrl = "https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/ghpages.sh"; + + public String getGhPagesUrl() { + return this.ghPagesUrl; + } + + public void setGhPagesUrl(String ghPagesUrl) { + this.ghPagesUrl = ghPagesUrl; + } + } + public static class Maven { /** @@ -115,7 +130,16 @@ public class ReleaserProperties { private String deployCommand = "./mvnw deploy -DskipTests -Pfast"; /** - * Max wait time in minutes for the build to finish + * Command to be executed to deploy a built project + */ + private String[] publishDocsCommands = { + "wget https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/ghpages.sh -O target/gh-pages.sh", + "chmod +x target/gh-pages.sh", + "./target/gh-pages.sh" + }; + + /** + * Max wait time in minutes for the process to finish */ private long waitTimeInMinutes = 20; @@ -142,10 +166,19 @@ public class ReleaserProperties { public void setDeployCommand(String deployCommand) { this.deployCommand = deployCommand; } + + public String[] getPublishDocsCommands() { + return this.publishDocsCommands; + } + + public void setPublishDocsCommands(String[] publishDocsCommands) { + this.publishDocsCommands = publishDocsCommands; + } } public String getWorkingDir() { - return this.workingDir; + return StringUtils.hasText(this.workingDir) ? + this.workingDir : System.getProperty("user.dir"); } public void setWorkingDir(String workingDir) { @@ -160,6 +193,14 @@ public class ReleaserProperties { this.git = git; } + public Docs getDocs() { + return this.docs; + } + + public void setDocs(Docs docs) { + this.docs = docs; + } + public Pom getPom() { return this.pom; } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java index ac603e95..305f149b 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java @@ -173,14 +173,6 @@ class PomUpdater { return changes; } - private boolean relativePathIsSet(Model model) { - return model.getParent() != null && StringUtils.hasText(model.getParent().getRelativePath()); - } - - private String parentName(Model model) { - return model.getParent() != null ? model.getParent().getArtifactId() : ""; - } - private String groupId(Model model) { if (StringUtils.hasText(model.getGroupId())) { return model.getGroupId(); @@ -318,8 +310,7 @@ class PropertyStorer { void setPropertyVersionIfApplicable(Project project) { String propertyName = propertyName(project); if (setPropertyVersion(propertyName, project.version)) { - log.info(" Updating property " + propertyName); - log.info(" to version " + project.version); + log.info("Updating property [" + propertyName + "] to version [" + project.version + "]"); } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/builder/ProjectBuilder.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/Project.java similarity index 71% rename from spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/builder/ProjectBuilder.java rename to spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/Project.java index 9aa6423b..1e8ebc8f 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/builder/ProjectBuilder.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/Project.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.release.internal.builder; +package org.springframework.cloud.release.internal.project; import java.io.File; import java.io.IOException; @@ -13,24 +13,23 @@ import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.release.internal.ReleaserProperties; -import org.springframework.util.StringUtils; /** * @author Marcin Grzejszczak */ -public class ProjectBuilder { +public class Project { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final ReleaserProperties properties; private final ProcessExecutor executor; - public ProjectBuilder(ReleaserProperties properties) { + public Project(ReleaserProperties properties) { this.properties = properties; this.executor = new ProcessExecutor(properties); } - ProjectBuilder(ReleaserProperties properties, ProcessExecutor executor) { + Project(ReleaserProperties properties, ProcessExecutor executor) { this.properties = properties; this.executor = executor; } @@ -38,8 +37,7 @@ public class ProjectBuilder { public void build() { try { String[] commands = this.properties.getMaven().getBuildCommand().split(" "); - long waitTimeInMinutes = this.properties.getMaven().getWaitTimeInMinutes(); - this.executor.runCommand(commands, waitTimeInMinutes); + runCommand(commands); assertNoHtmlFilesContainUnresolvedTags(); log.info("No HTML files from docs contain unresolved tags"); } catch (Exception e) { @@ -48,8 +46,7 @@ public class ProjectBuilder { } private void assertNoHtmlFilesContainUnresolvedTags() { - String workingDir = StringUtils.hasText(this.properties.getWorkingDir()) ? - this.properties.getWorkingDir() : System.getProperty("user.dir"); + String workingDir = this.properties.getWorkingDir(); try { Files.walkFileTree(new File(workingDir).toPath(), new HtmlFileWalker()); } @@ -59,7 +56,30 @@ public class ProjectBuilder { } public void deploy() { + try { + String[] commands = this.properties.getMaven().getDeployCommand().split(" "); + runCommand(commands); + log.info("The project has successfully been deployed"); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + private void runCommand(String[] commands) { + long waitTimeInMinutes = this.properties.getMaven().getWaitTimeInMinutes(); + this.executor.runCommand(commands, waitTimeInMinutes); + } + + public void publishDocs() { + try { + for (String command : this.properties.getMaven().getPublishDocsCommands()) { + String[] commands = command.split(" "); + runCommand(commands); + } + log.info("The docs got published successfully"); + } catch (Exception e) { + throw new IllegalStateException(e); + } } } @@ -74,8 +94,7 @@ class ProcessExecutor { void runCommand(String[] commands, long waitTimeInMinutes) { try { - String workingDir = StringUtils.hasText(this.properties.getWorkingDir()) ? - this.properties.getWorkingDir() : System.getProperty("user.dir"); + String workingDir = this.properties.getWorkingDir(); log.info("Will run the build via {} and wait for result for [{}] minutes", commands, waitTimeInMinutes); ProcessBuilder builder = builder(commands, workingDir); Process process = builder.start(); @@ -83,7 +102,7 @@ class ProcessExecutor { if (!finished) { log.error("The build hasn't managed to finish in [{}] minutes", waitTimeInMinutes); process.destroyForcibly(); - throw new IllegalStateException("Build waiting time of [" + waitTimeInMinutes + "] minutes exceeded"); + throw new IllegalStateException("Process waiting time of [" + waitTimeInMinutes + "] minutes exceeded"); } } catch (InterruptedException | IOException e) { diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/ReleaserPropertiesTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/ReleaserPropertiesTests.java new file mode 100644 index 00000000..efe8ea68 --- /dev/null +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/ReleaserPropertiesTests.java @@ -0,0 +1,28 @@ +package org.springframework.cloud.release.internal; + +import org.junit.Test; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * @author Marcin Grzejszczak + */ +public class ReleaserPropertiesTests { + @Test + public void should_return_provided_working_dir_when_it_was_set() throws Exception { + String workingDir = "foo"; + ReleaserProperties properties = new ReleaserProperties(); + + properties.setWorkingDir(workingDir); + + then(properties.getWorkingDir()).isEqualTo(workingDir); + } + + @Test + public void should_return_current_working_dir_when_it_was_not_previously_set() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + + then(properties.getWorkingDir()).isNotEmpty(); + } + +} \ No newline at end of file diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/builder/ProjectBuilderTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/builder/ProjectBuilderTests.java deleted file mode 100644 index a95f38dd..00000000 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/builder/ProjectBuilderTests.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.springframework.cloud.release.internal.builder; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Files; - -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; -import org.springframework.cloud.release.internal.ReleaserProperties; - -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenThrownBy; - -/** - * @author Marcin Grzejszczak - */ -public class ProjectBuilderTests { - - @Before - public void checkOs() { - Assume.assumeFalse(System.getProperty("os.name").toLowerCase().startsWith("win")); - } - - @Test - public void should_successfully_execute_a_command_when_after_running_there_is_no_html_file_with_unresolved_tag() throws Exception { - ReleaserProperties properties = new ReleaserProperties(); - properties.getMaven().setBuildCommand("ls -al"); - properties.setWorkingDir(file("/projects/builder/resolved").getPath()); - ProjectBuilder builder = new ProjectBuilder(properties, executor(properties)); - - builder.build(); - - then(asString(file("/projects/builder/resolved/resolved.log"))) - .contains("total 0") - .contains("file.txt"); - } - - @Test - public void should_throw_exception_when_after_running_there_is_an_html_file_with_unresolved_tag() throws Exception { - ReleaserProperties properties = new ReleaserProperties(); - properties.getMaven().setBuildCommand("ls -al"); - properties.setWorkingDir(file("/projects/builder/unresolved").getPath()); - ProjectBuilder builder = new ProjectBuilder(properties, executor(properties)); - - thenThrownBy(builder::build).hasMessageContaining("contains a tag that wasn't resolved properly"); - } - - @Test - public void should_throw_exception_when_command_took_too_long_to_execute() throws Exception { - ReleaserProperties properties = new ReleaserProperties(); - properties.getMaven().setBuildCommand("sleep 1"); - properties.getMaven().setWaitTimeInMinutes(0); - properties.setWorkingDir(file("/projects/builder/unresolved").getPath()); - ProjectBuilder builder = new ProjectBuilder(properties, executor(properties)); - - thenThrownBy(builder::build).hasMessageContaining("Build waiting time of [0] minutes exceeded"); - } - - private ProcessExecutor executor(ReleaserProperties properties) { - return new ProcessExecutor(properties) { - @Override ProcessBuilder builder(String[] commands, String workingDir) { - return super.builder(commands, workingDir) - .redirectOutput(file("/projects/builder/resolved/resolved.log")); - } - }; - } - - private File file(String relativePath) { - try { - File root = new File(ProjectBuilderTests.class.getResource("/").toURI()); - File file = new File(root, relativePath); - if (!file.exists()) { - file.createNewFile(); - } - return file; - } - catch (IOException | URISyntaxException e) { - throw new IllegalStateException(e); - } - } - - private String asString(File file) throws IOException { - return new String(Files.readAllBytes(file.toPath())); - } - -} \ No newline at end of file diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/project/ProjectBuilderTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/project/ProjectBuilderTests.java new file mode 100644 index 00000000..2e2f67af --- /dev/null +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/project/ProjectBuilderTests.java @@ -0,0 +1,147 @@ +package org.springframework.cloud.release.internal.project; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; + +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.springframework.cloud.release.internal.ReleaserProperties; + +import static org.assertj.core.api.BDDAssertions.then; +import static org.assertj.core.api.BDDAssertions.thenThrownBy; + +/** + * @author Marcin Grzejszczak + */ +public class ProjectBuilderTests { + + @Before + public void checkOs() { + Assume.assumeFalse(System.getProperty("os.name").toLowerCase().startsWith("win")); + } + + @Test + public void should_successfully_execute_a_command_when_after_running_there_is_no_html_file_with_unresolved_tag() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + properties.getMaven().setBuildCommand("ls -al"); + properties.setWorkingDir(file("/projects/builder/resolved").getPath()); + Project builder = new Project(properties, executor(properties)); + + builder.build(); + + then(asString(file("/projects/builder/resolved/resolved.log"))) + .contains("file.txt"); + } + + @Test + public void should_throw_exception_when_after_running_there_is_an_html_file_with_unresolved_tag() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + properties.getMaven().setBuildCommand("ls -al"); + properties.setWorkingDir(file("/projects/builder/unresolved").getPath()); + Project builder = new Project(properties, executor(properties)); + + thenThrownBy(builder::build).hasMessageContaining("contains a tag that wasn't resolved properly"); + } + + @Test + public void should_throw_exception_when_command_took_too_long_to_execute() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + properties.getMaven().setBuildCommand("sleep 1"); + properties.getMaven().setWaitTimeInMinutes(0); + properties.setWorkingDir(file("/projects/builder/unresolved").getPath()); + Project builder = new Project(properties, executor(properties)); + + thenThrownBy(builder::build).hasMessageContaining("Process waiting time of [0] minutes exceeded"); + } + + @Test + public void should_successfully_execute_a_deploy_command() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + properties.getMaven().setDeployCommand("ls -al"); + properties.setWorkingDir(file("/projects/builder/resolved").getPath()); + Project builder = new Project(properties, executor(properties)); + + builder.deploy(); + + then(asString(file("/projects/builder/resolved/resolved.log"))) + .contains("file.txt"); + } + + @Test + public void should_throw_exception_when_deploy_command_took_too_long_to_execute() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + properties.getMaven().setDeployCommand("sleep 1"); + properties.getMaven().setWaitTimeInMinutes(0); + properties.setWorkingDir(file("/projects/builder/unresolved").getPath()); + Project builder = new Project(properties, executor(properties)); + + thenThrownBy(builder::deploy).hasMessageContaining("Process waiting time of [0] minutes exceeded"); + } + + @Test + public void should_successfully_execute_a_publish_docs_command() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + properties.getMaven().setPublishDocsCommands(new String[] { "ls -al", "ls -al" }); + properties.setWorkingDir(file("/projects/builder/resolved").getPath()); + TestProcessExecutor executor = executor(properties); + Project builder = new Project(properties, executor); + + builder.publishDocs(); + + then(asString(file("/projects/builder/resolved/resolved.log"))) + .contains("file.txt"); + then(executor.counter).isEqualTo(2); + } + + @Test + public void should_throw_exception_when_publish_docs_command_took_too_long_to_execute() throws Exception { + ReleaserProperties properties = new ReleaserProperties(); + properties.getMaven().setPublishDocsCommands(new String[] { "ls -al", "ls -al" }); + properties.getMaven().setWaitTimeInMinutes(0); + properties.setWorkingDir(file("/projects/builder/unresolved").getPath()); + Project builder = new Project(properties, executor(properties)); + + thenThrownBy(builder::publishDocs).hasMessageContaining("Process waiting time of [0] minutes exceeded"); + } + + private TestProcessExecutor executor(ReleaserProperties properties) { + return new TestProcessExecutor(properties); + } + + class TestProcessExecutor extends ProcessExecutor { + + int counter = 0; + + TestProcessExecutor(ReleaserProperties properties) { + super(properties); + } + + @Override ProcessBuilder builder(String[] commands, String workingDir) { + counter++; + return super.builder(commands, workingDir) + .redirectOutput(file("/projects/builder/resolved/resolved.log")); + } + } + + private File file(String relativePath) { + try { + File root = new File(ProjectBuilderTests.class.getResource("/").toURI()); + File file = new File(root, relativePath); + if (!file.exists()) { + file.createNewFile(); + } + return file; + } + catch (IOException | URISyntaxException e) { + throw new IllegalStateException(e); + } + } + + private String asString(File file) throws IOException { + return new String(Files.readAllBytes(file.toPath())); + } + +} \ No newline at end of file diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/spring/ReleaserConfiguration.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/spring/ReleaserConfiguration.java index eec26c65..bad0efd8 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/spring/ReleaserConfiguration.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/spring/ReleaserConfiguration.java @@ -18,7 +18,7 @@ package org.springframework.cloud.release.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.builder.ProjectBuilder; +import org.springframework.cloud.release.internal.project.Project; import org.springframework.cloud.release.internal.git.ProjectGitUpdater; import org.springframework.cloud.release.internal.pom.ProjectUpdater; import org.springframework.context.annotation.Bean; @@ -30,6 +30,6 @@ class ReleaserConfiguration { @Bean Releaser releaser(ReleaserProperties properties) { return new Releaser(properties, new ProjectUpdater(properties), - new ProjectBuilder(properties), new ProjectGitUpdater()); + new Project(properties), new ProjectGitUpdater()); } }