diff --git a/README.adoc b/README.adoc
index 63c7b399..867db0d9 100644
--- a/README.adoc
+++ b/README.adoc
@@ -25,6 +25,10 @@ why this tool makes it easy to automate the release / dependency update process
=== What does it do?
+==== Single project
+
+For a single project
+
- Clones the Spring Cloud Release project and picks all versions (Boot + Cloud projects)
- Modifies the project versions with values from SC-Release
* throws an exception when we bump versions to release and there's a SNAPSHOT version referenced in the POM
@@ -36,6 +40,12 @@ why this tool makes it easy to automate the release / dependency update process
- Publishes the docs (to `spring-cloud-static` for non-snapshots, to `gh-pages` for snapshots)
- Reverts back to snapshots, bumps the version by a patch (`1.0.1.RELEASE` -> `1.0.2.BUILD-SNAPSHOT`) (ONLY FOR RELEASE VERSIONS)
- Closes the milestone on Github (e.g. `v1.0.1.RELEASE`) (ONLY FOR NON-SNAPSHOT VERSIONS)
+
+IMPORTANT: Starting with version that does Sagan integration, you MUST pass the OAuth token,
+otherwise the application will fail to start
+
+After project release
+
- Generates an email template under `target/email.txt` (ONLY FOR NON-SNAPSHOT VERSIONS)
- Generates a blog template under `target/blog.md` (ONLY FOR NON-SNAPSHOT VERSIONS)
- Generates a tweet template under `target/tweet.txt` (ONLY FOR NON-SNAPSHOT VERSIONS)
@@ -44,8 +54,17 @@ why this tool makes it easy to automate the release / dependency update process
- For `GA`/ `SR` release will create an issue in Spring Guides under https://github.com/spring-guides/getting-started-guides/issues/
- For `GA`/ `SR` release will update the links under https://github.com/spring-cloud/spring-cloud-static/tree/gh-pages/current
-IMPORTANT: Starting with version that does Sagan integration, you MUST pass the OAuth token,
-otherwise the application will fail to start
+==== Meta-release
+
+- Uses the fixed versions to clone and check out each project (e.g. `spring-cloud-sleuth: 2.1.0.RELEASE`)
+- From the version analyzes the branch and checks it out. E.g.
+** for `spring-cloud-release`'s `Finchley.RELEASE` version will resolve either `Finchley.x` branch or will fallback to `master` if there's no `Finchley.x` branch.
+** for `spring-cloud-sleuth`'s `2.1.0.RELEASE` version will resolve `2.1.x` branch
+- Performs the release tasks per each project
+- Performs the post release tasks at the end of the release
+
+IMPORTANT: For the meta-releaser to work we assume that the path to the
+custom configuration file for each project is always `config/releaser.yml`.
=== What should I do first?
@@ -225,10 +244,31 @@ $ java -jar ~/repo/spring-cloud-release-tools/spring-cloud-release-tools-spring/
$ java -jar ~/repo/spring-cloud-release-tools/spring-cloud-release-tools-spring/target/spring-cloud-release-tools-spring-1.0.0.BUILD-SNAPSHOT.jar --releaser.pom.branch=vDalston.SR1 --spring.config.name=releaser --closeMilestone -i=false
----
+=== How to run meta-release (automatic-mode)
+
+All you have to do is run the jar with the releaser and pass the
+`-x=true` option to turn on meta-release and a list of fixed versions
+in the `--"releaser.fixed-versions[project-name]=project-version" format
+
+```
+$ java -jar spring-cloud-release-tools-spring/target/spring-cloud-release-tools-spring-1.0.0.BUILD-SNAPSHOT.jar --spring.config.name=releaser -x=true --"releaser.fixed-versions[spring-cloud-sleuth]=2.0.1.BUILD-SNAPSHOT"
+```
+
+IMPORTANT: For the meta release the `startFrom` or `taskNames` take into consideration
+the project names, not task names. E.g. you can start from `spring-cloud-netflix` project,
+or build only tasks with names `spring-cloud-build,spring-cloud-sleuth`.
+
=== Project options
- `releaser.fixed-versions` - A String to String mapping of manually set versions. E.g. `"spring-cloud-cli" -> "1.0.0.RELEASE"` will set
the `spring-cloud-cli.version` to `1.0.0.RELEASE` regardless of what was set in `spring-cloud-release` project. Example `--releaser.fixed-versions[spring-cloud-cli]=1.0.0.RELEASE`.
+Use these properties to provide versions for the meta release.
+
+- `releaser.meta-release.enabled` - You have to turn it on to enable a meta release. Defaults to `false`
+- `releaser.meta-release.release-train-project-name` - Name of the project that represents the BOM of the release train. Defaults to `spring-cloud-release`
+- `releaser.meta-release.git-org-url` - The URL of the Git organization. We'll append each project's name to it.
+Defaults to `https://github.com/spring-cloud`
+
- `releaser.git.fetch-versions-from-git` - If `true` then should fill the map of versions from Git. If `false` then picks fixed versions
- `releaser.git.clone-destination-dir` - Where should the Spring Cloud Release repo get cloned to. If null defaults to a temporary directory
- `releaser.git.spring-cloud-release-git-url` - URL to Spring Cloud Release Git repository. Defaults to `https://github.com/spring-cloud/spring-cloud-release`
@@ -282,6 +322,9 @@ $ java -jar target/spring-cloud-release-tools-spring-1.0.0.M1.jar --spring.confi
TIP: Notice that we're downloading the jar to a parent folder, not to `target`. That's because `target` get cleaned
during the build process
+IMPORTANT: For the meta-releaser to work we assume that the path to the
+configuration file is always `config/releaser.yml`.
+
==== Specifying A Branch
By deafult the releaser will default to using the `master` branch of `spring-cloud-release`.
diff --git a/docs/src/main/asciidoc/spring-cloud-release-tools.adoc b/docs/src/main/asciidoc/spring-cloud-release-tools.adoc
index 2472ef0e..05d524cc 100644
--- a/docs/src/main/asciidoc/spring-cloud-release-tools.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-release-tools.adoc
@@ -15,6 +15,10 @@ why this tool makes it easy to automate the release / dependency update process
=== What does it do?
+==== Single project
+
+For a single project
+
- Clones the Spring Cloud Release project and picks all versions (Boot + Cloud projects)
- Modifies the project versions with values from SC-Release
* throws an exception when we bump versions to release and there's a SNAPSHOT version referenced in the POM
@@ -26,6 +30,12 @@ why this tool makes it easy to automate the release / dependency update process
- Publishes the docs (to `spring-cloud-static` for non-snapshots, to `gh-pages` for snapshots)
- Reverts back to snapshots, bumps the version by a patch (`1.0.1.RELEASE` -> `1.0.2.BUILD-SNAPSHOT`) (ONLY FOR RELEASE VERSIONS)
- Closes the milestone on Github (e.g. `v1.0.1.RELEASE`) (ONLY FOR NON-SNAPSHOT VERSIONS)
+
+IMPORTANT: Starting with version that does Sagan integration, you MUST pass the OAuth token,
+otherwise the application will fail to start
+
+After project release
+
- Generates an email template under `target/email.txt` (ONLY FOR NON-SNAPSHOT VERSIONS)
- Generates a blog template under `target/blog.md` (ONLY FOR NON-SNAPSHOT VERSIONS)
- Generates a tweet template under `target/tweet.txt` (ONLY FOR NON-SNAPSHOT VERSIONS)
@@ -34,8 +44,17 @@ why this tool makes it easy to automate the release / dependency update process
- For `GA`/ `SR` release will create an issue in Spring Guides under https://github.com/spring-guides/getting-started-guides/issues/
- For `GA`/ `SR` release will update the links under https://github.com/spring-cloud/spring-cloud-static/tree/gh-pages/current
-IMPORTANT: Starting with version that does Sagan integration, you MUST pass the OAuth token,
-otherwise the application will fail to start
+==== Meta-release
+
+- Uses the fixed versions to clone and check out each project (e.g. `spring-cloud-sleuth: 2.1.0.RELEASE`)
+- From the version analyzes the branch and checks it out. E.g.
+** for `spring-cloud-release`'s `Finchley.RELEASE` version will resolve either `Finchley.x` branch or will fallback to `master` if there's no `Finchley.x` branch.
+** for `spring-cloud-sleuth`'s `2.1.0.RELEASE` version will resolve `2.1.x` branch
+- Performs the release tasks per each project
+- Performs the post release tasks at the end of the release
+
+IMPORTANT: For the meta-releaser to work we assume that the path to the
+custom configuration file for each project is always `config/releaser.yml`.
=== What should I do first?
@@ -215,10 +234,31 @@ $ java -jar ~/repo/spring-cloud-release-tools/spring-cloud-release-tools-spring/
$ java -jar ~/repo/spring-cloud-release-tools/spring-cloud-release-tools-spring/target/spring-cloud-release-tools-spring-1.0.0.BUILD-SNAPSHOT.jar --releaser.pom.branch=vDalston.SR1 --spring.config.name=releaser --closeMilestone -i=false
----
+=== How to run meta-release (automatic-mode)
+
+All you have to do is run the jar with the releaser and pass the
+`-x=true` option to turn on meta-release and a list of fixed versions
+in the `--"releaser.fixed-versions[project-name]=project-version" format
+
+```
+$ java -jar spring-cloud-release-tools-spring/target/spring-cloud-release-tools-spring-1.0.0.BUILD-SNAPSHOT.jar --spring.config.name=releaser -x=true --"releaser.fixed-versions[spring-cloud-sleuth]=2.0.1.BUILD-SNAPSHOT"
+```
+
+IMPORTANT: For the meta release the `startFrom` or `taskNames` take into consideration
+the project names, not task names. E.g. you can start from `spring-cloud-netflix` project,
+or build only tasks with names `spring-cloud-build,spring-cloud-sleuth`.
+
=== Project options
- `releaser.fixed-versions` - A String to String mapping of manually set versions. E.g. `"spring-cloud-cli" -> "1.0.0.RELEASE"` will set
the `spring-cloud-cli.version` to `1.0.0.RELEASE` regardless of what was set in `spring-cloud-release` project. Example `--releaser.fixed-versions[spring-cloud-cli]=1.0.0.RELEASE`.
+Use these properties to provide versions for the meta release.
+
+- `releaser.meta-release.enabled` - You have to turn it on to enable a meta release. Defaults to `false`
+- `releaser.meta-release.release-train-project-name` - Name of the project that represents the BOM of the release train. Defaults to `spring-cloud-release`
+- `releaser.meta-release.git-org-url` - The URL of the Git organization. We'll append each project's name to it.
+Defaults to `https://github.com/spring-cloud`
+
- `releaser.git.fetch-versions-from-git` - If `true` then should fill the map of versions from Git. If `false` then picks fixed versions
- `releaser.git.clone-destination-dir` - Where should the Spring Cloud Release repo get cloned to. If null defaults to a temporary directory
- `releaser.git.spring-cloud-release-git-url` - URL to Spring Cloud Release Git repository. Defaults to `https://github.com/spring-cloud/spring-cloud-release`
@@ -272,6 +312,9 @@ $ java -jar target/spring-cloud-release-tools-spring-1.0.0.M1.jar --spring.confi
TIP: Notice that we're downloading the jar to a parent folder, not to `target`. That's because `target` get cleaned
during the build process
+IMPORTANT: For the meta-releaser to work we assume that the path to the
+configuration file is always `config/releaser.yml`.
+
==== Specifying A Branch
By deafult the releaser will default to using the `master` branch of `spring-cloud-release`.
diff --git a/pom.xml b/pom.xml
index e846bede..51b1df5c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
org.springframework.cloud
spring-cloud-build
- 1.3.9.RELEASE
+ 2.0.0.RELEASE
@@ -24,7 +24,7 @@
- Edgware.BUILD-SNAPSHOT
+ Finchley.RELEASE
diff --git a/spring-cloud-release-tools-core/foo b/spring-cloud-release-tools-core/foo
new file mode 100644
index 00000000..e69de29b
diff --git a/spring-cloud-release-tools-core/pom.xml b/spring-cloud-release-tools-core/pom.xml
index 1543863c..2b1b3783 100644
--- a/spring-cloud-release-tools-core/pom.xml
+++ b/spring-cloud-release-tools-core/pom.xml
@@ -37,6 +37,7 @@
org.hibernate
hibernate-validator
+ 5.4.1.Final
org.eclipse.jgit
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 78308787..5f45afe9 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
@@ -46,6 +46,10 @@ public class Releaser {
this.documentationUpdater = documentationUpdater;
}
+ public File clonedProjectFromOrg(String projectName) {
+ return this.projectGitHandler.cloneProjectFromOrg(projectName);
+ }
+
public Projects retrieveVersionsFromSCRelease() {
return this.projectPomUpdater.retrieveVersionsFromSCRelease();
}
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 c64f8fc1..0b6be61a 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
@@ -45,8 +45,56 @@ public class ReleaserProperties {
private Sagan sagan = new Sagan();
+ /**
+ * Project name to its version - overrides all versions
+ * retrieved from a repository like Spring Cloud Release
+ */
private Map fixedVersions = new HashMap<>();
+ private MetaRelease metaRelease = new MetaRelease();
+
+ public static class MetaRelease {
+ /**
+ * Are we releasing the whole suite of apps or only one?
+ */
+ private boolean enabled = false;
+
+ /**
+ * Name of the release train project
+ */
+ private String releaseTrainProjectName = "spring-cloud-release";
+
+ /**
+ * The URL of the Git organization. We'll append each project's
+ * name to it
+ */
+ private String gitOrgUrl = "https://github.com/spring-cloud";
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getGitOrgUrl() {
+ return this.gitOrgUrl;
+ }
+
+ public void setGitOrgUrl(String gitOrgUrl) {
+ this.gitOrgUrl = gitOrgUrl;
+ }
+
+ public String getReleaseTrainProjectName() {
+ return this.releaseTrainProjectName;
+ }
+
+ public void setReleaseTrainProjectName(String releaseTrainProjectName) {
+ this.releaseTrainProjectName = releaseTrainProjectName;
+ }
+ }
+
public static class Git {
/**
@@ -388,6 +436,14 @@ public class ReleaserProperties {
this.fixedVersions = fixedVersions;
}
+ public MetaRelease getMetaRelease() {
+ return this.metaRelease;
+ }
+
+ public void setMetaRelease(MetaRelease metaRelease) {
+ this.metaRelease = metaRelease;
+ }
+
public Sagan getSagan() {
return this.sagan;
}
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserPropertiesAware.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserPropertiesAware.java
new file mode 100644
index 00000000..99b0c251
--- /dev/null
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserPropertiesAware.java
@@ -0,0 +1,9 @@
+package org.springframework.cloud.release.internal;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+public interface ReleaserPropertiesAware {
+
+ void setReleaserProperties(ReleaserProperties properties);
+}
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java
index ad78cff3..e6c4bc98 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/GitRepo.java
@@ -112,13 +112,12 @@ class GitRepo {
/**
* Checks out a branch for a project
- * @param project - a Git project
* @param branch - branch to check out
*/
- void checkout(File project, String branch) {
+ void checkout(String branch) {
try {
log.info("Checking out branch [{}] for repo [{}]", branch, this.basedir);
- checkoutBranch(project, branch);
+ checkoutBranch(this.basedir, branch);
log.info("Successfully checked out the branch [{}]", branch);
}
catch (Exception e) {
@@ -128,11 +127,10 @@ class GitRepo {
/**
* Performs a commit
- * @param project - a Git project
* @param message - commit message
*/
- void commit(File project, String message) {
- try(Git git = this.gitFactory.open(file(project))) {
+ void commit(String message) {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
git.add().addFilepattern(".").call();
git.commit().setAllowEmpty(false).setMessage(message).call();
printLog(git);
@@ -143,6 +141,16 @@ class GitRepo {
}
}
+ boolean hasBranch(String branch) {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
+ List[ refs = git.branchList().setListMode(ListBranchCommand.ListMode.ALL)
+ .call();
+ return refs.stream().anyMatch(ref -> ref.getName().contains(branch));
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
private void printLog(Git git) throws GitAPIException, IOException {
int maxCount = 5;
String currentBranch = git.getRepository().getBranch();
@@ -155,11 +163,10 @@ class GitRepo {
/**
* Creates a tag with a given name
- * @param project
* @param tagName
*/
- void tag(File project, String tagName) {
- try(Git git = this.gitFactory.open(file(project))) {
+ void tag(String tagName) {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
git.tag().setName(tagName).call();
} catch (Exception e) {
throw new IllegalStateException(e);
@@ -168,11 +175,10 @@ class GitRepo {
/**
* Pushes the commits to {@code origin} remote branch
- * @param project - Git project
* @param branch - remote branch to which the code should be pushed
*/
- void pushBranch(File project, String branch) {
- try(Git git = this.gitFactory.open(file(project))) {
+ void pushBranch(String branch) {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
String localBranch = git.getRepository().getFullBranch();
RefSpec refSpec = new RefSpec(localBranch + ":" + branch);
this.gitFactory.push(git).setPushTags().setRefSpecs(refSpec).call();
@@ -183,10 +189,9 @@ class GitRepo {
/**
* Pushes the commits od current branch
- * @param project - Git project
*/
- void pushCurrentBranch(File project) {
- try(Git git = this.gitFactory.open(file(project))) {
+ void pushCurrentBranch() {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
this.gitFactory.push(git).call();
} catch (Exception e) {
throw new IllegalStateException(e);
@@ -195,11 +200,10 @@ class GitRepo {
/**
* Pushes the commits to {@code origin} remote tag
- * @param project - Git project
* @param tagName - remote tag to which the code should be pushed
*/
- void pushTag(File project, String tagName) {
- try(Git git = this.gitFactory.open(file(project))) {
+ void pushTag(String tagName) {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
String localBranch = git.getRepository().getFullBranch();
RefSpec refSpec = new RefSpec(localBranch + ":" + "refs/tags/" + tagName);
this.gitFactory.push(git).setPushTags().setRefSpecs(refSpec).call();
@@ -208,8 +212,8 @@ class GitRepo {
}
}
- void revert(File project, String message) {
- try(Git git = this.gitFactory.open(file(project))) {
+ void revert(String message) {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
RevCommit commit = git.log().setMaxCount(1).call().iterator().next();
String shortMessage = commit.getShortMessage();
String id = commit.getId().getName();
@@ -227,8 +231,8 @@ class GitRepo {
}
}
- String currentBranch(File project) {
- try(Git git = this.gitFactory.open(file(project))) {
+ String currentBranch() {
+ try(Git git = this.gitFactory.open(file(this.basedir))) {
return git.getRepository().getBranch();
} catch (Exception e) {
throw new IllegalStateException(e);
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java
index b62f28ff..3f31810e 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/git/ProjectGitHandler.java
@@ -8,15 +8,17 @@ import java.nio.file.Files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.release.internal.ReleaserProperties;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
import org.springframework.cloud.release.internal.pom.Projects;
+import org.springframework.util.StringUtils;
/**
* Contains business logic around Git & Github operations
*
* @author Marcin Grzejszczak
*/
-public class ProjectGitHandler {
+public class ProjectGitHandler implements ReleaserPropertiesAware {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -25,7 +27,7 @@ public class ProjectGitHandler {
private static final String POST_RELEASE_MSG = "Going back to snapshots";
private static final String POST_RELEASE_BUMP_MSG = "Bumping versions to %s after release";
- private final ReleaserProperties properties;
+ private ReleaserProperties properties;
private final GithubMilestones githubMilestones;
private final GithubIssues githubIssues;
@@ -39,13 +41,13 @@ public class ProjectGitHandler {
GitRepo gitRepo = gitRepo(project);
if (version.isSnapshot()) {
log.info("Snapshot version [{}] found. Will only commit the changed poms", version);
- gitRepo.commit(project, MSG);
+ gitRepo.commit(MSG);
} else {
log.info("NON-snapshot version [{}] found. Will commit the changed poms, tag the version and push the tag", version);
- gitRepo.commit(project, String.format(PRE_RELEASE_MSG, version.version));
+ gitRepo.commit(String.format(PRE_RELEASE_MSG, version.version));
String tagName = "v" + version.version;
- gitRepo.tag(project, tagName);
- gitRepo.pushTag(project, tagName);
+ gitRepo.tag(tagName);
+ gitRepo.pushTag(tagName);
}
}
@@ -60,7 +62,7 @@ public class ProjectGitHandler {
public void commit(File project, String message) {
GitRepo gitRepo = gitRepo(project);
- gitRepo.commit(project, message);
+ gitRepo.commit(message);
}
public File cloneScReleaseProject() {
@@ -73,7 +75,36 @@ public class ProjectGitHandler {
return clonedProject;
}
- private File cloneProject(String url) {
+ /**
+ * For meta-release. Works with fixed versions only
+ * @param projectName - name of the project to clone
+ * @return location of the cloned project
+ */
+ public File cloneProjectFromOrg(String projectName) {
+ String orgUrl = this.properties.getMetaRelease().getGitOrgUrl();
+ String fullUrl = orgUrl.endsWith("/") ? orgUrl + projectName : orgUrl + "/" +
+ projectName + suffixNonHttpRepo(orgUrl);
+ File clonedProject = cloneProject(fullUrl);
+ String version = this.properties.getFixedVersions().get(projectName);
+ if (StringUtils.isEmpty(version)) {
+ throw new IllegalStateException("You haven't provided a version for project [" + projectName + "]");
+ }
+ String branchFromVersion = branchFromVersion(version);
+ boolean branchExists = gitRepo(clonedProject).hasBranch(branchFromVersion);
+ if (!branchExists) {
+ log.info("Branch [{}] does not exist. Assuming that should work with master branch", branchFromVersion);
+ return clonedProject;
+ }
+ log.info("Branch [{}] exists. Will check it out", branchFromVersion);
+ checkout(clonedProject, branchFromVersion);
+ return clonedProject;
+ }
+
+ private String suffixNonHttpRepo(String orgUrl) {
+ return orgUrl.startsWith("http") || orgUrl.startsWith("git") ? "" : "/";
+ }
+
+ File cloneProject(String url) {
try {
File destinationDir = properties.getGit().getCloneDestinationDir() != null ?
new File(properties.getGit().getCloneDestinationDir()) :
@@ -85,7 +116,28 @@ public class ProjectGitHandler {
}
public void checkout(File project, String branch) {
- gitRepo(project).checkout(project, branch);
+ gitRepo(project).checkout(branch);
+ }
+
+ // let's go with convention... If fixed version contains e.g.
+ // 2.3.4.RELEASE of Sleuth, we will first check if `2.0.x` branch
+ // exists. If not, then we will assume that `master` contains it
+ private String branchFromVersion(String version) {
+ // 2.3.4.RELEASE -> 2.3.4
+ // Camden.RELEASE -> Camden
+ String versionTillPatch = version.substring(0, version.lastIndexOf("."));
+ // 2.3.4 -> [2,3,4]
+ // Camden -> [Camden]
+ String[] splitVersion = versionTillPatch.split("\\.");
+ if (splitVersion.length == 3) {
+ // [2,3,4] -> 2.3.x
+ return splitVersion[0] + "." + splitVersion[1] + ".x";
+ } else if (splitVersion.length == 1) {
+ // [Camden] -> [Camden.x]
+ return splitVersion[0] + ".x";
+ }
+ throw new IllegalStateException("Wrong version [" + version + "]. Can't extract semver pieces of it");
+
}
public void revertChangesIfApplicable(File project, ProjectVersion version) {
@@ -94,11 +146,11 @@ public class ProjectGitHandler {
return;
}
log.info("Reverting last commit");
- gitRepo(project).revert(project, POST_RELEASE_MSG);
+ gitRepo(project).revert(POST_RELEASE_MSG);
}
public void pushCurrentBranch(File project) {
- gitRepo(project).pushCurrentBranch(project);
+ gitRepo(project).pushCurrentBranch();
}
public void closeMilestone(ProjectVersion releaseVersion) {
@@ -114,10 +166,14 @@ public class ProjectGitHandler {
}
public String currentBranch(File project) {
- return gitRepo(project).currentBranch(project);
+ return gitRepo(project).currentBranch();
}
GitRepo gitRepo(File workingDir) {
return new GitRepo(workingDir, this.properties);
}
+
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.properties = properties;
+ }
}
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/gradle/GradleUpdater.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/gradle/GradleUpdater.java
index c8a820c6..14c664ca 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/gradle/GradleUpdater.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/gradle/GradleUpdater.java
@@ -17,17 +17,18 @@ import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.release.internal.ReleaserProperties;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
import org.springframework.cloud.release.internal.pom.Projects;
/**
* @author Marcin Grzejszczak
*/
-public class GradleUpdater {
+public class GradleUpdater implements ReleaserPropertiesAware {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final ReleaserProperties properties;
+ private ReleaserProperties properties;
public GradleUpdater(ReleaserProperties properties) {
this.properties = properties;
@@ -59,6 +60,10 @@ public class GradleUpdater {
}
}
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.properties = properties;
+ }
+
private class GradlePropertiesWalker extends SimpleFileVisitor {
private static final String GRADLE_PROPERTIES = "gradle.properties";
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdater.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdater.java
index 4f2451f5..a4cbf82b 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdater.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdater.java
@@ -29,12 +29,13 @@ import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.release.internal.ReleaserProperties;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
import org.springframework.cloud.release.internal.git.ProjectGitHandler;
/**
* @author Marcin Grzejszczak
*/
-public class ProjectPomUpdater {
+public class ProjectPomUpdater implements ReleaserPropertiesAware {
private static final List IGNORED_SNAPSHOT_LINE_PATTERNS = Arrays.asList(
"^.*replace=.*$",
@@ -44,7 +45,7 @@ public class ProjectPomUpdater {
private static final Logger log = LoggerFactory.getLogger(ProjectPomUpdater.class);
- private final ReleaserProperties properties;
+ private ReleaserProperties properties;
private final ProjectGitHandler gitRepo;
private final PomUpdater pomUpdater = new PomUpdater();
@@ -103,6 +104,10 @@ public class ProjectPomUpdater {
}
}
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.properties = properties;
+ }
+
private class PomWalker extends SimpleFileVisitor {
private static final String POM_XML = "pom.xml";
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java
index 6b51710d..75fd8b75 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/Projects.java
@@ -66,6 +66,11 @@ public class Projects extends HashSet {
.orElseThrow(() -> exception(projectName));
}
+ public boolean containsProject(String projectName) {
+ return this.stream()
+ .anyMatch(projectVersion -> projectVersion.projectName.equals(projectName));
+ }
+
public List forNameStartingWith(String projectName) {
return this.stream().filter(projectVersion -> projectVersion.projectName.startsWith(projectName))
.collect(Collectors.toList());
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/SCReleasePomParser.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/SCReleasePomParser.java
index f54cf491..144445ec 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/SCReleasePomParser.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/SCReleasePomParser.java
@@ -45,7 +45,7 @@ class SCReleasePomParser {
private final File springCloudReleaseDir;
private final String bootPom;
- private final String dependenciesPom;
+ private final String dependenciesPomPath;
private final PomReader pomReader = new PomReader();
SCReleasePomParser(File springCloudReleaseDir) {
@@ -55,7 +55,7 @@ class SCReleasePomParser {
SCReleasePomParser(File springCloudReleaseDir, String bootPom, String dependenciesPom) {
this.springCloudReleaseDir = springCloudReleaseDir;
this.bootPom = bootPom;
- this.dependenciesPom = dependenciesPom;
+ this.dependenciesPomPath = dependenciesPom;
}
Versions allVersions() {
@@ -96,7 +96,7 @@ class SCReleasePomParser {
}
Versions springCloudVersions() {
- Model model = pom(this.dependenciesPom);
+ Model model = pom(this.dependenciesPomPath);
String buildArtifact = model.getParent().getArtifactId();
log.debug("[{}] artifact id is equal to [{}]", SpringCloudConstants.CLOUD_DEPENDENCIES_ARTIFACT_ID, buildArtifact);
if (!SpringCloudConstants.CLOUD_DEPENDENCIES_ARTIFACT_ID.equals(buildArtifact)) {
@@ -109,6 +109,8 @@ class SCReleasePomParser {
.filter(propertyMatchesSCPattern())
.map(toProject())
.collect(Collectors.toSet());
+ String scReleaseVersion = model.getVersion();
+ projects.add(new Project("spring-cloud-release", scReleaseVersion));
return new Versions(buildVersion, projects);
}
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java
index f13e4abd..ff909ae8 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/project/ProjectBuilder.java
@@ -18,6 +18,7 @@ import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
import org.springframework.util.StringUtils;
@@ -25,12 +26,12 @@ import org.springframework.util.StringUtils;
/**
* @author Marcin Grzejszczak
*/
-public class ProjectBuilder {
+public class ProjectBuilder implements ReleaserPropertiesAware {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String VERSION_MUSTACHE = "{{version}}";
- private final ReleaserProperties properties;
+ private ReleaserProperties properties;
private final ProcessExecutor executor;
public ProjectBuilder(ReleaserProperties properties) {
@@ -161,12 +162,17 @@ public class ProjectBuilder {
}
return commandsList.toArray(new String[commandsList.size()]);
}
+
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.properties = properties;
+ this.executor.setReleaserProperties(properties);
+ }
}
-class ProcessExecutor {
+class ProcessExecutor implements ReleaserPropertiesAware {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final ReleaserProperties properties;
+ private ReleaserProperties properties;
ProcessExecutor(ReleaserProperties properties) {
this.properties = properties;
@@ -175,7 +181,8 @@ class ProcessExecutor {
void runCommand(String[] commands, long waitTimeInMinutes) {
try {
String workingDir = this.properties.getWorkingDir();
- log.debug("Will run the build via {} and wait for result for [{}] minutes", commands, waitTimeInMinutes);
+ log.debug("Will run the build from [{}] via {} and wait for result for [{}] minutes",
+ workingDir, commands, waitTimeInMinutes);
ProcessBuilder builder = builder(commands, workingDir);
Process process = startProcess(builder);
boolean finished = process.waitFor(waitTimeInMinutes, TimeUnit.MINUTES);
@@ -202,6 +209,10 @@ class ProcessExecutor {
.directory(new File(workingDir))
.inheritIO();
}
+
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.properties = properties;
+ }
}
class HtmlFileWalker extends SimpleFileVisitor {
diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/template/TemplateGenerator.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/template/TemplateGenerator.java
index 9475f151..878d7e54 100644
--- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/template/TemplateGenerator.java
+++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/template/TemplateGenerator.java
@@ -9,13 +9,14 @@ import java.io.File;
import java.io.IOException;
import org.springframework.cloud.release.internal.ReleaserProperties;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
import org.springframework.cloud.release.internal.git.ProjectGitHandler;
import org.springframework.cloud.release.internal.pom.Projects;
/**
* @author Marcin Grzejszczak
*/
-public class TemplateGenerator {
+public class TemplateGenerator implements ReleaserPropertiesAware {
private static final String EMAIL_TEMPLATE = "email";
private static final String BLOG_TEMPLATE = "blog";
@@ -25,7 +26,7 @@ public class TemplateGenerator {
private final File blogOutput;
private final File tweetOutput;
private final File releaseNotesOutput;
- private final ReleaserProperties props;
+ private ReleaserProperties props;
private final ProjectGitHandler handler;
public TemplateGenerator(ReleaserProperties props, ProjectGitHandler handler) {
@@ -109,4 +110,8 @@ public class TemplateGenerator {
throw new IllegalStateException(e);
}
}
+
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.props = properties;
+ }
}
diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GitRepoTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GitRepoTests.java
index 0a082da0..52998b83 100644
--- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GitRepoTests.java
+++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/GitRepoTests.java
@@ -70,7 +70,7 @@ public class GitRepoTests {
@Test
public void should_check_out_a_branch_on_cloned_repo() throws IOException {
File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
- this.gitRepo.checkout(project, "vCamden.SR3");
+ new GitRepo(project).checkout("vCamden.SR3");
File pom = new File(this.tmpFolder, "pom.xml");
then(pom).exists();
@@ -80,18 +80,32 @@ public class GitRepoTests {
@Test
public void should_check_out_a_branch_on_cloned_repo2() throws IOException {
File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
- this.gitRepo.checkout(project, "Camden.x");
+ new GitRepo(project).checkout("Camden.x");
File pom = new File(this.tmpFolder, "pom.xml");
then(pom).exists();
then(Files.lines(pom.toPath()).anyMatch(s -> s.contains("Camden.BUILD-SNAPSHOT"))).isTrue();
}
+ @Test
+ public void should_return_true_if_branch_exists() throws IOException {
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
+
+ then(new GitRepo(project).hasBranch("Camden.x")).isTrue();
+ }
+
+ @Test
+ public void should_return_false_if_branch_does_not_exist() throws IOException {
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
+
+ then(new GitRepo(project).hasBranch("aksjdhkasjkajshd")).isFalse();
+ }
+
@Test
public void should_throw_an_exception_when_checking_out_nonexisting_branch() throws IOException {
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
try {
- this.gitRepo.checkout(project, "nonExistingBranch");
+ new GitRepo(project).checkout("nonExistingBranch");
fail("should throw an exception");
} catch (IllegalStateException e) {
then(e).hasMessageContaining("Ref nonExistingBranch can not be resolved");
@@ -100,10 +114,10 @@ public class GitRepoTests {
@Test
public void should_commit_changes() throws Exception {
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
createNewFile(project);
- this.gitRepo.commit(project, "some message");
+ new GitRepo(project).commit("some message");
try(Git git = openGitProject(project)) {
RevCommit revCommit = git.log().call().iterator().next();
@@ -113,11 +127,11 @@ public class GitRepoTests {
@Test
public void should_not_commit_empty_changes() throws Exception {
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
createNewFile(project);
- this.gitRepo.commit(project, "some message");
+ new GitRepo(project).commit("some message");
- this.gitRepo.commit(project, "empty commit");
+ new GitRepo(project).commit("empty commit");
try(Git git = openGitProject(project)) {
RevCommit revCommit = git.log().call().iterator().next();
@@ -127,11 +141,11 @@ public class GitRepoTests {
@Test
public void should_create_a_tag() throws Exception {
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
createNewFile(project);
- this.gitRepo.commit(project, "some message");
+ new GitRepo(project).commit("some message");
- this.gitRepo.tag(project, "v1.0.0");
+ new GitRepo(project).tag("v1.0.0");
try(Git git = openGitProject(project)) {
tagIsPresent(git, "v1.0.0");
@@ -147,12 +161,12 @@ public class GitRepoTests {
@Test
public void should_push_changes_to_master_branch() throws Exception {
File origin = clonedProject(this.tmp.newFolder(), this.springCloudReleaseProject);
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
setOriginOnProjectToTmp(origin, project);
createNewFile(project);
- this.gitRepo.commit(project, "some message");
+ new GitRepo(project).commit("some message");
- this.gitRepo.pushBranch(project, "master");
+ new GitRepo(project).pushBranch("master");
try(Git git = openGitProject(origin)) {
RevCommit revCommit = git.log().call().iterator().next();
@@ -163,12 +177,12 @@ public class GitRepoTests {
@Test
public void should_push_changes_to_current_branch() throws Exception {
File origin = clonedProject(this.tmp.newFolder(), this.springCloudReleaseProject);
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
setOriginOnProjectToTmp(origin, project);
createNewFile(project);
- this.gitRepo.commit(project, "some message");
+ new GitRepo(project).commit("some message");
- this.gitRepo.pushCurrentBranch(project);
+ new GitRepo(project).pushCurrentBranch();
try(Git git = openGitProject(origin)) {
RevCommit revCommit = git.log().call().iterator().next();
@@ -179,11 +193,11 @@ public class GitRepoTests {
@Test
public void should_return_the_branch_name() throws Exception {
File origin = clonedProject(this.tmp.newFolder(), this.springCloudReleaseProject);
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
setOriginOnProjectToTmp(origin, project);
createNewFile(project);
- String branch = this.gitRepo.currentBranch(project);
+ String branch = new GitRepo(project).currentBranch();
then(branch).isEqualTo("master");
}
@@ -191,13 +205,13 @@ public class GitRepoTests {
@Test
public void should_push_a_tag_to_new_branch_in_origin() throws Exception {
File origin = clonedProject(this.tmp.newFolder(), this.springCloudReleaseProject);
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
setOriginOnProjectToTmp(origin, project);
createNewFile(project);
- this.gitRepo.commit(project, "some message");
- this.gitRepo.tag(project, "v5.6.7.RELEASE");
+ new GitRepo(project).commit("some message");
+ new GitRepo(project).tag("v5.6.7.RELEASE");
- this.gitRepo.pushTag(project, "v5.6.7.RELEASE");
+ new GitRepo(project).pushTag("v5.6.7.RELEASE");
try(Git git = openGitProject(origin)) {
tagIsPresent(git, "v5.6.7");
@@ -225,12 +239,12 @@ public class GitRepoTests {
@Test
public void should_revert_changes() throws Exception {
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(this.tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
File foo = new File(project, "foo");
foo.createNewFile();
- this.gitRepo.commit(project, "Update SNAPSHOT to 1.0.0.RC1");
+ new GitRepo(project).commit("Update SNAPSHOT to 1.0.0.RC1");
- this.gitRepo.revert(project, "Reverting the commit");
+ new GitRepo(project).revert("Reverting the commit");
try(Git git = openGitProject(project)) {
RevCommit revCommit = git.log().call().iterator().next();
@@ -240,10 +254,10 @@ public class GitRepoTests {
@Test
public void should_not_revert_changes_when_commit_message_is_not_related_to_updating_snapshots() throws Exception {
- File project = this.gitRepo.cloneProject(this.springCloudReleaseProject.toURI());
+ File project = new GitRepo(tmpFolder).cloneProject(this.springCloudReleaseProject.toURI());
BDDAssertions.thenThrownBy(
- () -> this.gitRepo.revert(project, "some message"))
+ () -> new GitRepo(project).revert("some message"))
.hasMessageContaining("Won't revert the commit with id");
}
diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java
index 144d7854..8b289db1 100644
--- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java
+++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/git/ProjectGitHandlerTests.java
@@ -2,13 +2,16 @@ package org.springframework.cloud.release.internal.git;
import java.io.File;
+import org.assertj.core.api.BDDAssertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
+import org.springframework.cloud.release.internal.sagan.Release;
+import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
@@ -22,10 +25,15 @@ import static org.mockito.Mockito.never;
public class ProjectGitHandlerTests {
@Mock GitRepo gitRepo;
- ProjectGitHandler updater = new ProjectGitHandler(new ReleaserProperties()) {
+ ReleaserProperties properties = new ReleaserProperties();
+ ProjectGitHandler updater = new ProjectGitHandler(this.properties) {
@Override GitRepo gitRepo(File workingDir) {
return ProjectGitHandlerTests.this.gitRepo;
}
+
+ @Override File cloneProject(String url) {
+ return new File(".");
+ }
};
File file = new File("");
@@ -33,54 +41,95 @@ public class ProjectGitHandlerTests {
public void should_only_commit_without_pushing_changes_when_version_is_snapshot() {
this.updater.commitAndTagIfApplicable(this.file, projectVersion("1.0.0.BUILD-SNAPSHOT"));
- then(this.gitRepo).should().commit(any(File.class), eq("Bumping versions"));
- then(this.gitRepo).should(never()).tag(any(File.class), anyString());
+ then(this.gitRepo).should().commit(eq("Bumping versions"));
+ then(this.gitRepo).should(never()).tag(anyString());
}
@Test
public void should_commit_tag_and_push_tag_when_version_is_not_snapshot() {
this.updater.commitAndTagIfApplicable(this.file, projectVersion("1.0.0.RELEASE"));
- then(this.gitRepo).should().commit(any(File.class), eq("Update SNAPSHOT to 1.0.0.RELEASE"));
- then(this.gitRepo).should().tag(any(File.class), eq("v1.0.0.RELEASE"));
- then(this.gitRepo).should().pushTag(any(File.class), eq("v1.0.0.RELEASE"));
+ then(this.gitRepo).should().commit(eq("Update SNAPSHOT to 1.0.0.RELEASE"));
+ then(this.gitRepo).should().tag(eq("v1.0.0.RELEASE"));
+ then(this.gitRepo).should().pushTag(eq("v1.0.0.RELEASE"));
}
@Test
public void should_commit_when_snapshot_version_is_present_with_post_release_msg() {
this.updater.commitAfterBumpingVersions(this.file, projectVersion("1.0.0.BUILD-SNAPSHOT"));
- then(this.gitRepo).should().commit(any(File.class), eq("Bumping versions to 1.0.1.BUILD-SNAPSHOT after release"));
- then(this.gitRepo).should(never()).tag(any(File.class), anyString());
+ then(this.gitRepo).should().commit(eq("Bumping versions to 1.0.1.BUILD-SNAPSHOT after release"));
+ then(this.gitRepo).should(never()).tag(anyString());
}
@Test
public void should_not_commit_when_non_snapshot_version_is_present() {
this.updater.commitAfterBumpingVersions(this.file, projectVersion("1.0.0.RELEASE"));
- then(this.gitRepo).should(never()).commit(any(File.class), eq("Bumping versions after release"));
- then(this.gitRepo).should(never()).tag(any(File.class), anyString());
+ then(this.gitRepo).should(never()).commit(eq("Bumping versions after release"));
+ then(this.gitRepo).should(never()).tag(anyString());
}
@Test
public void should_not_revert_changes_for_snapshots() {
this.updater.revertChangesIfApplicable(this.file, projectVersion("1.0.0.BUILD-SNAPSHOT"));
- then(this.gitRepo).should(never()).revert(any(File.class), anyString());
+ then(this.gitRepo).should(never()).revert(anyString());
}
@Test
public void should_revert_changes_when_version_is_not_snapshot() {
this.updater.revertChangesIfApplicable(this.file, projectVersion("1.0.0.RELEASE"));
- then(this.gitRepo).should().revert(any(File.class), eq("Going back to snapshots"));
+ then(this.gitRepo).should().revert(eq("Going back to snapshots"));
}
@Test
public void should_push_current_branch() {
this.updater.pushCurrentBranch(this.file);
- then(this.gitRepo).should().pushCurrentBranch(any(File.class));
+ then(this.gitRepo).should().pushCurrentBranch();
+ }
+
+ @Test
+ public void should_throw_exception_when_no_fixed_version_passed_for_the_project() {
+ BDDAssertions.thenThrownBy(() -> this.updater
+ .cloneProjectFromOrg("spring-cloud-sleuth"))
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessageContaining("You haven't provided a version");
+ }
+
+ @Test
+ public void should_not_check_out_a_branch_if_it_does_not_exist_when_cloning_from_org() {
+ this.properties.getFixedVersions().put("spring-cloud-sleuth", "2.3.4.RELEASE");
+ given(this.gitRepo.hasBranch(anyString())).willReturn(true);
+ given(this.gitRepo.hasBranch("2.3.x")).willReturn(false);
+
+ this.updater.cloneProjectFromOrg("spring-cloud-sleuth");
+
+ then(this.gitRepo).should(never()).checkout(anyString());
+ }
+
+ @Test
+ public void should_check_out_a_branch_if_it_exists_when_cloning_from_org() {
+ this.properties.getFixedVersions().put("spring-cloud-sleuth", "2.3.4.RELEASE");
+ given(this.gitRepo.hasBranch(anyString())).willReturn(false);
+ given(this.gitRepo.hasBranch("2.3.x")).willReturn(true);
+
+ this.updater.cloneProjectFromOrg("spring-cloud-sleuth");
+
+ then(this.gitRepo).should().checkout("2.3.x");
+ }
+
+ @Test
+ public void should_check_out_a_branch_if_it_exists_when_cloning_from_org_and_its_a_release_train_version() {
+ this.properties.getFixedVersions().put("spring-cloud-release", "Finchley.SR6");
+ given(this.gitRepo.hasBranch(anyString())).willReturn(false);
+ given(this.gitRepo.hasBranch("Finchley.x")).willReturn(true);
+
+ this.updater.cloneProjectFromOrg("spring-cloud-release");
+
+ then(this.gitRepo).should().checkout("Finchley.x");
}
private ProjectVersion projectVersion(String version) {
diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java
index 93ee42fc..9507594b 100644
--- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java
+++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectsTests.java
@@ -35,6 +35,15 @@ public class ProjectsTests {
then(projects.forName("spring-cloud-starter-build").version).isEqualTo("1.0.0");
}
+ @Test
+ public void should_return_true_when_a_project_by_name_exists() {
+ Set projectVersions = new HashSet<>();
+ projectVersions.add(new ProjectVersion("spring-cloud-starter-build", "1.0.0"));
+ Projects projects = new Projects(projectVersions);
+
+ then(projects.containsProject("spring-cloud-starter-build")).isTrue();
+ }
+
@Test
public void should_find_projects_starting_with_name() {
Set projectVersions = new HashSet<>();
diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/PropertyStorerTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/PropertyStorerTests.java
index 3475ddb7..f111d01a 100644
--- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/PropertyStorerTests.java
+++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/PropertyStorerTests.java
@@ -2,14 +2,12 @@ package org.springframework.cloud.release.internal.pom;
import org.apache.maven.plugin.logging.Log;
import org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.BDDMockito.then;
@@ -30,15 +28,8 @@ public class PropertyStorerTests {
}
private String containsWarnMsgAboutEmptyVersion() {
- return BDDMockito.argThat(new TypeSafeMatcher() {
- @Override protected boolean matchesSafely(String item) {
- return item.contains("is empty. Will not set it");
- }
-
- @Override public void describeTo(Description description) {
-
- }
- });
+ return BDDMockito.argThat(
+ argument -> argument.contains("is empty. Will not set it"));
}
}
\ No newline at end of file
diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/SCReleasePomParserTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/SCReleasePomParserTests.java
index fed65f0f..33c14868 100644
--- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/SCReleasePomParserTests.java
+++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/SCReleasePomParserTests.java
@@ -50,6 +50,15 @@ public class SCReleasePomParserTests {
.hasMessageContaining("The pom doesn't have a [spring-boot-starter-parent] artifact id");
}
+ @Test
+ public void should_populate_sc_release_version() {
+ SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject);
+
+ String scReleaseVersion = parser.allVersions().versionForProject("spring-cloud-release");
+
+ then(scReleaseVersion).isEqualTo("Dalston.BUILD-SNAPSHOT");
+ }
+
@Test
public void should_populate_boot_version() {
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject);
diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java
index a1e5f219..6b0f1bac 100644
--- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java
+++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java
@@ -8,10 +8,11 @@ import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
import static org.mockito.BDDMockito.then;
@@ -103,23 +104,17 @@ public class SaganUpdaterTest {
"http://cloud.spring.io/foo/1.1.x/", "SNAPSHOT")));
}
- private TypeSafeMatcher]> withReleaseUpdate(final String version,
+ private ArgumentMatcher> withReleaseUpdate(final String version,
final String refDocUrl, final String releaseStatus) {
- return new TypeSafeMatcher>() {
- @Override protected boolean matchesSafely(List items) {
- ReleaseUpdate item = items.get(0);
+ return argument -> {
+ ReleaseUpdate item = argument.get(0);
return "foo".equals(item.artifactId) &&
releaseStatus.equals(item.releaseStatus) &&
version.equals(item.version) &&
refDocUrl.equals(item.apiDocUrl) &&
refDocUrl.equals(item.refDocUrl) &&
item.current;
- }
-
- @Override public void describeTo(Description description) {
-
- }
- };
+ };
}
}
\ No newline at end of file
diff --git a/spring-cloud-release-tools-spring/pom.xml b/spring-cloud-release-tools-spring/pom.xml
index f81b4da9..83776369 100644
--- a/spring-cloud-release-tools-spring/pom.xml
+++ b/spring-cloud-release-tools-spring/pom.xml
@@ -36,6 +36,10 @@
5.0.3
true
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
org.springframework.boot
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/ReleaserApplication.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/ReleaserApplication.java
index 2ca026bc..9210705d 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/ReleaserApplication.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/ReleaserApplication.java
@@ -18,6 +18,7 @@ package org.springframework.cloud.release.internal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.release.internal.options.Options;
import org.springframework.cloud.release.internal.options.Parser;
@@ -28,7 +29,7 @@ public class ReleaserApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(ReleaserApplication.class);
- application.setWebEnvironment(false);
+ application.setWebApplicationType(WebApplicationType.NONE);
application.run(args);
}
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/Options.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/Options.java
index f352eefb..80fe614c 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/Options.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/Options.java
@@ -7,14 +7,17 @@ import java.util.List;
* @author Marcin Grzejszczak
*/
public class Options {
- public Boolean fullRelease = true;
- public Boolean interactive = true;
- public List taskNames = new ArrayList<>();
+ public Boolean metaRelease;
+ public Boolean fullRelease;
+ public Boolean interactive;
+ public List taskNames;
public String startFrom = "";
public String range = "";
- Options(Boolean fullRelease, Boolean interactive, List taskNames, String startFrom,
+ Options(Boolean metaRelease, Boolean fullRelease,
+ Boolean interactive, List taskNames, String startFrom,
String range) {
+ this.metaRelease = metaRelease;
this.fullRelease = fullRelease;
this.interactive = interactive;
this.taskNames = taskNames;
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/OptionsBuilder.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/OptionsBuilder.java
index 0c018fc6..bece7b68 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/OptionsBuilder.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/options/OptionsBuilder.java
@@ -4,12 +4,18 @@ import java.util.ArrayList;
import java.util.List;
public class OptionsBuilder {
+ private Boolean metaRelease = false;
private Boolean fullRelease = false;
private Boolean interactive = true;
private List taskNames = new ArrayList<>();
private String startFrom = "";
private String range = "";
+ public OptionsBuilder metaRelease(Boolean metaRelease) {
+ this.metaRelease = metaRelease;
+ return this;
+ }
+
public OptionsBuilder fullRelease(Boolean fullRelease) {
this.fullRelease = fullRelease;
return this;
@@ -36,7 +42,8 @@ public class OptionsBuilder {
}
public Options options() {
- return new Options(this.fullRelease, this.interactive, this.taskNames, this.startFrom,
+ return new Options(this.metaRelease, this.fullRelease,
+ this.interactive, this.taskNames, this.startFrom,
this.range);
}
}
\ No newline at end of file
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java
index 3e3b4274..443ce489 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Args.java
@@ -2,6 +2,7 @@ package org.springframework.cloud.release.internal.spring;
import java.io.File;
+import org.apache.commons.validator.Arg;
import org.springframework.cloud.release.internal.Releaser;
import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
@@ -18,10 +19,11 @@ class Args {
final ProjectVersion versionFromScRelease;
final ReleaserProperties properties;
final boolean interactive;
+ final TaskType taskType;
Args(Releaser releaser, File project, Projects projects, ProjectVersion originalVersion,
ProjectVersion versionFromScRelease, ReleaserProperties properties,
- boolean interactive) {
+ boolean interactive, TaskType taskType) {
this.releaser = releaser;
this.project = project;
this.projects = projects;
@@ -29,5 +31,33 @@ class Args {
this.versionFromScRelease = versionFromScRelease;
this.properties = properties;
this.interactive = interactive;
+ this.taskType = taskType;
+ }
+
+ // Used by meta-release task
+ Args(Releaser releaser, Projects projects,
+ ProjectVersion versionFromScRelease,
+ ReleaserProperties properties,
+ boolean interactive) {
+ this.releaser = releaser;
+ this.project = null;
+ this.projects = projects;
+ this.originalVersion = null;
+ this.versionFromScRelease = versionFromScRelease;
+ this.properties = properties;
+ this.interactive = interactive;
+ this.taskType = TaskType.POST_RELEASE;
+ }
+
+ // Used for tests
+ Args(TaskType taskType) {
+ this.releaser = null;
+ this.project = null;
+ this.projects = null;
+ this.originalVersion = null;
+ this.versionFromScRelease = null;
+ this.properties = null;
+ this.interactive = false;
+ this.taskType = taskType;
}
}
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsParser.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsParser.java
index 01b88cdb..2dc02590 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsParser.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsParser.java
@@ -23,15 +23,19 @@ class OptionsParser implements Parser {
OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();
try {
+ ArgumentAcceptingOptionSpec metaReleaseOpt = parser
+ .acceptsAll(Arrays.asList("x", "meta-release"),
+ "Do you want to do the meta release?")
+ .withRequiredArg().ofType(Boolean.class).defaultsTo(false);
ArgumentAcceptingOptionSpec fullReleaseOpt = parser
.acceptsAll(Arrays.asList("f", "full-release"),
- "Do you want to do the full release")
+ "Do you want to do the full release of a single project?")
.withOptionalArg().ofType(Boolean.class).defaultsTo(false);
ArgumentAcceptingOptionSpec interactiveOpt = parser
.acceptsAll(Arrays.asList("i", "interactive"),
- "Do you want to set the properties from the command line")
+ "Do you want to set the properties from the command line of a single project?")
.withRequiredArg().ofType(Boolean.class).defaultsTo(true);
- Tasks.ALL_TASKS.forEach(task ->
+ Tasks.NON_COMPOSITE_TASKS.forEach(task ->
parser.acceptsAll(Arrays.asList(task.shortName, task.name),
task.description)
.withOptionalArg());
@@ -49,14 +53,16 @@ class OptionsParser implements Parser {
printHelpMessage(parser);
System.exit(0);
}
+ Boolean metaRelease = options.valueOf(metaReleaseOpt);
Boolean interactive = options.valueOf(interactiveOpt);
Boolean fullRelease = options.has(fullReleaseOpt);
- List taskNames = Tasks.ALL_TASKS.stream()
+ List taskNames = Tasks.NON_COMPOSITE_TASKS.stream()
.filter(task -> options.has(task.name)).map(task -> task.name)
.collect(Collectors.toList());
String startFrom = options.valueOf(startFromOpt);
String range = options.valueOf(rangeOpt);
return new OptionsBuilder()
+ .metaRelease(metaRelease)
.fullRelease(fullRelease)
.interactive(interactive)
.taskNames(taskNames)
@@ -94,7 +100,7 @@ class OptionsParser implements Parser {
}
private String intro() {
- return "\nHere you can find the list of tasks in order\n\n[" + Tasks.tasksInOrder() + "]\n\n";
+ return "\nHere you can find the list of tasks in order\n\n[" + Tasks.allTasksInOrder() + "]\n\n";
}
private String examples() {
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsProcessor.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsProcessor.java
index d32e72a7..48ab06d3 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsProcessor.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/OptionsProcessor.java
@@ -23,7 +23,7 @@ class OptionsProcessor {
private final List allTasks;
OptionsProcessor(Releaser releaser, ReleaserProperties properties) {
- this(releaser, properties, Tasks.ALL_TASKS);
+ this(releaser, properties, Tasks.ALL_TASKS_PER_PROJECT);
}
OptionsProcessor(Releaser releaser, ReleaserProperties properties, List allTasks) {
@@ -33,26 +33,60 @@ class OptionsProcessor {
}
void processOptions(Options options, Args defaultArgs) {
+ processOptions(options, defaultArgs, this.allTasks);
+ }
+
+ void processOptions(Options options, Args defaultArgs, List tasks) {
Args args = args(defaultArgs, options.interactive);
+ if (args.taskType == TaskType.POST_RELEASE) {
+ String chosenOption = chosenOption();
+ int pickedInteger = Integer.parseInt(chosenOption);
+ boolean pickedOptionIsComposite = pickedInteger <= 1;
+ boolean pickedOptionIsFromPostRelease = pickedInteger >= Tasks.ALL_TASKS_PER_PROJECT.size()
+ - Tasks.DEFAULT_TASKS_PER_RELEASE.size();
+ if (options.fullRelease || pickedOptionIsComposite) {
+ postReleaseTask().execute(args);
+ } else if (pickedOptionIsFromPostRelease) {
+ processNonComposite(options, tasks, args);
+ } else {
+ log.info("Picked option [{}] doesn't allow post release steps", pickedInteger);
+ }
+ return;
+ }
if (options.fullRelease && !options.interactive) {
log.info("Executing a full release in non-interactive mode");
releaseTask().execute(args);
} else if (options.fullRelease && options.interactive) {
log.info("Executing a full release in interactive mode");
releaseVerboseTask().execute(args);
- } else if (StringUtils.hasText(options.startFrom)) {
- startFrom(options, args);
+ } else {
+ processNonComposite(options, tasks, args);
+ }
+ }
+
+ private void processNonComposite(Options options, List tasks, Args args) {
+ if (StringUtils.hasText(options.startFrom)) {
+ startFrom(tasks, options, args);
} else if (StringUtils.hasText(options.range)) {
- range(options.range, args);
+ range(tasks, options.range, args);
} else if (!options.taskNames.isEmpty()) {
- tasks(options.taskNames, args);
+ tasks(tasks, options.taskNames, args);
} else if (options.interactive) {
- interactiveOnly(args);
+ interactiveOnly(tasks, args);
} else {
throw new IllegalStateException("You haven't picked any recognizable option");
}
}
+ void postReleaseOptions(Options options, Args defaultArgs) {
+ Args args = args(defaultArgs, options.interactive);
+ processOptions(options, args);
+ }
+
+ Task postReleaseTask() {
+ return Tasks.POST_RELEASE;
+ }
+
Task releaseTask() {
return Tasks.RELEASE;
}
@@ -61,16 +95,18 @@ class OptionsProcessor {
return Tasks.RELEASE_VERBOSE;
}
- private void interactiveOnly(Args defaultArgs) {
- log.info(buildOptionsText().toString());
- executeTaskFromOption(defaultArgs);
+ private void interactiveOnly(List tasks, Args defaultArgs) {
+ if (defaultArgs.taskType != TaskType.POST_RELEASE) {
+ log.info(buildOptionsText().toString());
+ }
+ executeTaskFromOption(tasks, defaultArgs);
}
- private void tasks(List taskNames, Args defaultArgs) {
- Tasks.forNames(this.allTasks, taskNames).forEach(task -> task.execute(defaultArgs));
+ private void tasks(List tasks, List taskNames, Args defaultArgs) {
+ Tasks.forNames(tasks, taskNames).forEach(task -> task.execute(defaultArgs));
}
- private void range(String range, Args defaultArgs) {
+ private void range(List tasks, String range, Args defaultArgs) {
String[] splitRange = range.split("-");
String start = splitRange[0];
String stop = "";
@@ -79,7 +115,7 @@ class OptionsProcessor {
}
boolean started = false;
boolean sameRange = start.equals(stop);
- for (Task task : this.allTasks) {
+ for (Task task : tasks) {
if (start.equals(task.name) || start.equals(task.shortName)) {
started = true;
task.execute(defaultArgs);
@@ -95,9 +131,9 @@ class OptionsProcessor {
}
}
- private void startFrom(Options options, Args defaultArgs) {
+ private void startFrom(List tasks, Options options, Args defaultArgs) {
boolean started = false;
- for (Task task : this.allTasks) {
+ for (Task task : tasks) {
if (options.startFrom.equals(task.name) || options.startFrom.equals(task.shortName)) {
started = true;
task.execute(defaultArgs);
@@ -120,25 +156,25 @@ class OptionsProcessor {
return msg;
}
- void executeTaskFromOption(Args defaultArgs) {
+ void executeTaskFromOption(List tasks, Args defaultArgs) {
String input = chosenOption();
switch (input.toLowerCase()) {
case "q":
System.exit(0);
default:
if (input.contains("-")) {
- rangeInteractive(defaultArgs, input);
+ rangeInteractive(tasks, defaultArgs, input);
} else if (input.contains(",")) {
- tasksInteractive(defaultArgs, input);
+ tasksInteractive(tasks, defaultArgs, input);
} else {
- singleTask(defaultArgs, input);
+ singleTask(tasks, defaultArgs, input);
}
}
}
- private void singleTask(Args defaultArgs, String input) {
+ private void singleTask(List tasks, Args defaultArgs, String input) {
int chosenOption = Integer.parseInt(input);
- Task task = this.allTasks.get(chosenOption);
+ Task task = tasks.get(chosenOption);
boolean interactive = false;
if (task == Tasks.RELEASE_VERBOSE) {
interactive = true;
@@ -147,31 +183,32 @@ class OptionsProcessor {
task.execute(args(defaultArgs, interactive));
}
- private void tasksInteractive(Args defaultArgs, String input) {
- List tasks = Arrays.asList(input.split(","));
+ private void tasksInteractive(List tasks, Args defaultArgs, String input) {
+ List tasksFromInput = Arrays.asList(input.split(","));
List taskNames = new ArrayList<>();
- for (String task : tasks) {
+ for (String task : tasksFromInput) {
Integer taskIndex = Integer.valueOf(task);
- taskNames.add(this.allTasks.get(taskIndex).name);
+ taskNames.add(tasks.get(taskIndex).name);
}
- tasks(taskNames, defaultArgs);
+ tasks(tasks, taskNames, defaultArgs);
}
- private void rangeInteractive(Args defaultArgs, String input) {
+ private void rangeInteractive(List tasks, Args defaultArgs, String input) {
String[] range = input.split("-");
Integer start = Integer.valueOf(range[0]);
Integer stop = null;
if (range.length == 2) {
stop = Integer.valueOf(range[1]);
}
- String firstName = this.allTasks.get(start).name;
- String second = stop != null ? this.allTasks.get(stop).name : "";
- range(firstName + "-" + second, defaultArgs);
+ String firstName = tasks.get(start).name;
+ String second = stop != null ? tasks.get(stop).name : "";
+ range(tasks, firstName + "-" + second, defaultArgs);
}
private Args args(Args defaultArgs, boolean interactive) {
return new Args(this.releaser, defaultArgs.project, defaultArgs.projects,
- defaultArgs.originalVersion, defaultArgs.versionFromScRelease, this.properties, interactive);
+ defaultArgs.originalVersion, defaultArgs.versionFromScRelease,
+ this.properties, interactive, defaultArgs.taskType);
}
String chosenOption() {
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java
index fa890904..badd4e95 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserConfiguration.java
@@ -15,18 +15,21 @@
*/
package org.springframework.cloud.release.internal.spring;
+import org.springframework.beans.factory.annotation.Autowired;
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.docs.DocumentationUpdater;
import org.springframework.cloud.release.internal.gradle.GradleUpdater;
import org.springframework.cloud.release.internal.options.Parser;
+import org.springframework.cloud.release.internal.sagan.Release;
import org.springframework.cloud.release.internal.sagan.SaganClient;
import org.springframework.cloud.release.internal.sagan.SaganUpdater;
import org.springframework.cloud.release.internal.template.TemplateGenerator;
import org.springframework.cloud.release.internal.project.ProjectBuilder;
import org.springframework.cloud.release.internal.git.ProjectGitHandler;
import org.springframework.cloud.release.internal.pom.ProjectPomUpdater;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -34,14 +37,37 @@ import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties(ReleaserProperties.class)
class ReleaserConfiguration {
- @Bean SpringReleaser releaser(ReleaserProperties properties, SaganClient saganClient) {
- ProjectPomUpdater pomUpdater = new ProjectPomUpdater(properties);
- ProjectGitHandler handler = new ProjectGitHandler(properties);
- SaganUpdater saganUpdater = new SaganUpdater(saganClient);
- return new SpringReleaser(new Releaser(pomUpdater, new ProjectBuilder(properties),
- handler, new TemplateGenerator(properties, handler),
- new GradleUpdater(properties), saganUpdater,
- new DocumentationUpdater(handler)), properties);
+ @Autowired ReleaserProperties properties;
+
+ @Bean SpringReleaser springReleaser(Releaser releaser,
+ ReleaserPropertiesUpdater updater) {
+ return new SpringReleaser(releaser, this.properties, updater);
+ }
+
+ @Bean ProjectBuilder projectBuilder() { return new ProjectBuilder(this.properties); }
+
+ @Bean ProjectPomUpdater pomUpdater() { return new ProjectPomUpdater(this.properties); }
+
+ @Bean ProjectGitHandler projectGitHandler() { return new ProjectGitHandler(this.properties); }
+
+ @Bean TemplateGenerator templateGenerator(ProjectGitHandler handler) { return new TemplateGenerator(this.properties, handler); }
+
+ @Bean GradleUpdater gradleUpdater() { return new GradleUpdater(this.properties); }
+
+ @Bean SaganUpdater saganUpdater(SaganClient saganClient) { return new SaganUpdater(saganClient); }
+
+ @Bean DocumentationUpdater documentationUpdater(ProjectGitHandler handler) { return new DocumentationUpdater(handler); }
+
+ @Bean Releaser releaser(ProjectPomUpdater projectPomUpdater, ProjectBuilder projectBuilder,
+ ProjectGitHandler projectGitHandler, TemplateGenerator templateGenerator,
+ GradleUpdater gradleUpdater, SaganUpdater saganUpdater,
+ DocumentationUpdater documentationUpdater) {
+ return new Releaser(projectPomUpdater, projectBuilder, projectGitHandler,
+ templateGenerator, gradleUpdater, saganUpdater, documentationUpdater);
+ }
+
+ @Bean ReleaserPropertiesUpdater releaserPropertiesUpdater(ApplicationContext context) {
+ return new ReleaserPropertiesUpdater(context);
}
@Bean Parser optionsParser() {
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdater.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdater.java
new file mode 100644
index 00000000..72caca8a
--- /dev/null
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdater.java
@@ -0,0 +1,24 @@
+package org.springframework.cloud.release.internal.spring;
+
+import java.util.Map;
+
+import org.springframework.cloud.release.internal.ReleaserProperties;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+class ReleaserPropertiesUpdater {
+ private final ApplicationContext context;
+
+ public ReleaserPropertiesUpdater(ApplicationContext context) {
+ this.context = context;
+ }
+
+ public void updateProperties(ReleaserProperties properties) {
+ Map beans = this.context
+ .getBeansOfType(ReleaserPropertiesAware.class);
+ beans.values().forEach(aware -> aware.setReleaserProperties(properties));
+ }
+}
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java
index 0b6e4861..77081c8a 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/SpringReleaser.java
@@ -1,20 +1,23 @@
package org.springframework.cloud.release.internal.spring;
import java.io.File;
-import java.lang.invoke.MethodHandles;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.BeanUtils;
import org.springframework.cloud.release.internal.Releaser;
import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.cloud.release.internal.options.Options;
import org.springframework.cloud.release.internal.options.OptionsBuilder;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
import org.springframework.cloud.release.internal.pom.Projects;
-import org.springframework.cloud.release.internal.sagan.Project;
+import org.springframework.util.StringUtils;
/**
* Releaser that gets input from console
@@ -22,24 +25,28 @@ import org.springframework.cloud.release.internal.sagan.Project;
* @author Marcin Grzejszczak
*/
public class SpringReleaser {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private static final Logger log = LoggerFactory.getLogger(SpringReleaser.class);
private final Releaser releaser;
private final ReleaserProperties properties;
private final OptionsProcessor optionsProcessor;
+ private final ReleaserPropertiesUpdater updater;
+ private final ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
- @Autowired
- public SpringReleaser(Releaser releaser, ReleaserProperties properties) {
+ public SpringReleaser(Releaser releaser, ReleaserProperties properties,
+ ReleaserPropertiesUpdater updater) {
this.releaser = releaser;
this.properties = properties;
+ this.updater = updater;
this.optionsProcessor = new OptionsProcessor(releaser, properties);
}
SpringReleaser(Releaser releaser, ReleaserProperties properties,
- OptionsProcessor optionsProcessor) {
+ OptionsProcessor optionsProcessor, ReleaserPropertiesUpdater updater) {
this.releaser = releaser;
this.properties = properties;
this.optionsProcessor = optionsProcessor;
+ this.updater = updater;
}
/**
@@ -50,17 +57,108 @@ public class SpringReleaser {
}
public void release(Options options) {
+ ProjectsAndVersion projectsAndVersion = null;
+ // if meta release, first clone, then continue as usual
+ if (options.metaRelease) {
+ log.info("Meta Release picked. Will iterate over all projects and perform release of each one");
+ this.properties.getGit().setFetchVersionsFromGit(false);
+ metaReleaseProjects(options).forEach(project -> {
+ processProjectForMetaRelease(options, project);
+ });
+ } else {
+ log.info("Single project release picked. Will release only the current project");
+ File projectFolder = projectFolder();
+ projectsAndVersion = processProject(options, projectFolder, TaskType.RELEASE);
+ }
+ this.optionsProcessor.postReleaseOptions(options, postReleaseOptionsAgs(options, projectsAndVersion));
+ }
+
+ private void processProjectForMetaRelease(Options options, String project) {
+ File clonedProjectFromOrg = this.releaser.clonedProjectFromOrg(project);
+ ReleaserProperties copy = clonePropertiesForProject();
+ updatePropertiesIfCustomConfigPresent(copy, clonedProjectFromOrg);
+ log.info("Successfully cloned the project [{}] to [{}]", project, clonedProjectFromOrg);
+ try {
+ processProject(options, clonedProjectFromOrg, TaskType.RELEASE);
+ } catch (Exception e) {
+ log.error("\n\n\nBUILD FAILED!!!\n\nException occurred for project <" +
+ project + "> \n\n");
+ throw e;
+ }
+ }
+
+ private ReleaserProperties clonePropertiesForProject() {
+ ReleaserProperties copy = new ReleaserProperties();
+ BeanUtils.copyProperties(this.properties, copy);
+ return copy;
+ }
+
+ private void updatePropertiesIfCustomConfigPresent(ReleaserProperties copy,
+ File clonedProjectFromOrg) {
+ File releaserConfig = new File(clonedProjectFromOrg, "config/releaser.yml");
+ if (releaserConfig.exists()) {
+ try {
+ ReleaserProperties releaserProperties = this.objectMapper
+ .readValue(releaserConfig, ReleaserProperties.class);
+ log.info("config/releaser.yml found. Will update the current properties");
+ copy.setMaven(releaserProperties.getMaven());
+ copy.setGradle(releaserProperties.getGradle());
+ }
+ catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ log.info("Updating working directory to [{}]", clonedProjectFromOrg.getAbsolutePath());
+ copy.setWorkingDir(clonedProjectFromOrg.getAbsolutePath());
+ this.updater.updateProperties(copy);
+ }
+
+ private List metaReleaseProjects(Options options) {
+ List projects = new ArrayList<>(this.properties.getFixedVersions().keySet());
+ if (StringUtils.hasText(options.startFrom)) {
+ int projectIndex = projects.indexOf(options.startFrom);
+ if (projectIndex < 0) throw new IllegalStateException("Project [" + options.startFrom + "] not found");
+ projects = projects.subList(projectIndex, projects.size());
+ options.startFrom = "";
+ } else if (!options.taskNames.isEmpty()) {
+ projects = projects.stream()
+ .filter(project -> options.taskNames.contains(project))
+ .collect(Collectors.toList());
+ options.taskNames = new ArrayList<>();
+ }
+ log.info("\n\n\nFor meta-release, will release the projects {}\n\n\n", projects);
+ return projects;
+ }
+
+ private File projectFolder() {
String workingDir = this.properties.getWorkingDir();
- File project = new File(workingDir);
- ProjectVersion originalVersion = new ProjectVersion(project);
+ return new File(workingDir);
+ }
+
+ Args postReleaseOptionsAgs(Options options, ProjectsAndVersion projectsAndVersion) {
+ Projects projects = projectsAndVersion == null ?
+ projectsToUpdateForFixedVersions() : projectsAndVersion.projectVersions;
+ ProjectVersion version = projects.containsProject(this.properties.getMetaRelease().getReleaseTrainProjectName()) ?
+ projects.forName(this.properties.getMetaRelease().getReleaseTrainProjectName()) : versionFromBranch();
+ return new Args(this.releaser, projects, version,
+ this.properties, options.interactive);
+ }
+
+ private ProjectVersion versionFromBranch() {
+ String branch = this.properties.getPom().getBranch();
+ return new ProjectVersion(projectFolder().getName(), branch.startsWith("v") ? branch.substring(1) : branch);
+ }
+
+ private ProjectsAndVersion projects(File project) {
ProjectVersion versionFromScRelease;
Projects projectsToUpdate;
- if (this.properties.getGit().isFetchVersionsFromGit()) {
+ if (this.properties.getGit().isFetchVersionsFromGit() && !this.properties.getMetaRelease().isEnabled()) {
printVersionRetrieval();
projectsToUpdate = this.releaser.retrieveVersionsFromSCRelease();
versionFromScRelease = projectsToUpdate.forFile(project);
assertNoSnapshotsForANonSnapshotProject(projectsToUpdate, versionFromScRelease);
} else {
+ ProjectVersion originalVersion = new ProjectVersion(project);
String fixedVersionForProject = this.properties.getFixedVersions().get(originalVersion.projectName);
versionFromScRelease = new ProjectVersion(originalVersion.projectName, fixedVersionForProject == null ?
originalVersion.version : fixedVersionForProject);
@@ -70,9 +168,35 @@ public class SpringReleaser {
projectsToUpdate.add(versionFromScRelease);
printSettingVersionFromFixedVersions(projectsToUpdate);
}
- final Args defaultArgs = new Args(this.releaser, project, projectsToUpdate,
- originalVersion, versionFromScRelease, this.properties, options.interactive);
+ return new ProjectsAndVersion(projectsToUpdate, versionFromScRelease);
+ }
+
+ class ProjectsAndVersion {
+ final Projects projectVersions;
+ final ProjectVersion versionFromScRelease;
+
+ ProjectsAndVersion(Projects projectVersions, ProjectVersion versionFromScRelease) {
+ this.projectVersions = projectVersions;
+ this.versionFromScRelease = versionFromScRelease;
+ }
+ }
+
+ private ProjectsAndVersion processProject(Options options, File project, TaskType taskType) {
+ ProjectsAndVersion projectsAndVersion = projects(project);
+ ProjectVersion originalVersion = new ProjectVersion(project);
+ final Args defaultArgs = new Args(this.releaser, project, projectsAndVersion.projectVersions,
+ originalVersion, projectsAndVersion.versionFromScRelease, this.properties,
+ options.interactive, taskType);
this.optionsProcessor.processOptions(options, defaultArgs);
+ return projectsAndVersion;
+ }
+
+ private Projects projectsToUpdateForFixedVersions() {
+ Projects projectsToUpdate = this.properties.getFixedVersions().entrySet().stream()
+ .map(entry -> new ProjectVersion(entry.getKey(), entry.getValue()))
+ .distinct().collect(Collectors.toCollection(Projects::new));
+ printSettingVersionFromFixedVersions(projectsToUpdate);
+ return projectsToUpdate;
}
private void printVersionRetrieval() {
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Task.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Task.java
index 7eb28036..a7dc5809 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Task.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Task.java
@@ -18,17 +18,30 @@ class Task {
final String shortName;
final String header;
final String description;
+ final TaskType taskType;
private final Consumer consumer;
- Task(String name, String shortName, String header, String description, Consumer consumer) {
+ Task(String name, String shortName, String header, String description,
+ Consumer consumer) {
+ this(name, shortName, header, description, consumer, TaskType.RELEASE);
+ }
+
+ Task(String name, String shortName, String header, String description,
+ Consumer consumer, TaskType taskType) {
this.name = name;
this.shortName = shortName;
this.header = header;
this.description = description;
this.consumer = consumer;
+ this.taskType = taskType;
}
void 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;
+ }
try {
boolean interactive = args.interactive;
printLog(interactive);
@@ -48,7 +61,7 @@ class Task {
}
private void printLog(boolean interactive) {
- log.info("\n\n\n=== {} ===\n\n{} {}\n\n", header, description, interactive ? MSG : "");
+ log.info("\n\n\n=== {} ===\n\n{} {}\n\n", header, description, interactive ? MSG : "");
}
boolean skipStep() {
@@ -67,5 +80,4 @@ class Task {
String chosenOption() {
return System.console().readLine();
}
-
}
diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java
index 08c608d7..efcc06e5 100644
--- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java
+++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java
@@ -1,5 +1,6 @@
package org.springframework.cloud.release.internal.spring;
+import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -51,13 +52,13 @@ class Tasks {
args.releaser.createBlog(args.versionFromScRelease, args.projects);
args.releaser.createTweet(args.versionFromScRelease);
args.releaser.createReleaseNotes(args.versionFromScRelease, args.projects);
- });
+ },TaskType.POST_RELEASE);
static Task UPDATE_GUIDES = task("updateGuides", "ug",
"UPDATE GUIDES",
"Updating Spring Guides",
args -> {
args.releaser.updateSpringGuides(args.versionFromScRelease, args.projects);
- });
+ },TaskType.POST_RELEASE);
static Task UPDATE_SAGAN = task("updateSagan", "g",
"UPDATE SAGAN",
"Updating Sagan with release info",
@@ -69,9 +70,9 @@ class Tasks {
"Updating documentation repository",
args -> {
args.releaser.updateDocumentationRepository(args.properties, args.versionFromScRelease);
- });
+ },TaskType.POST_RELEASE);
- static final List DEFAULT_TASKS = Stream.of(
+ static final List DEFAULT_TASKS_PER_PROJECT = Stream.of(
Tasks.UPDATING_POMS,
Tasks.BUILD_PROJECT,
Tasks.COMMIT,
@@ -80,32 +81,61 @@ class Tasks {
Tasks.SNAPSHOTS,
Tasks.PUSH,
Tasks.CLOSE_MILESTONE,
+ Tasks.UPDATE_SAGAN
+ ).collect(Collectors.toList());
+
+ static final List DEFAULT_TASKS_PER_RELEASE = Stream.of(
Tasks.CREATE_TEMPLATES,
- Tasks.UPDATE_SAGAN,
Tasks.UPDATE_GUIDES,
Tasks.UPDATE_DOCUMENTATION
).collect(Collectors.toList());
- static Task RELEASE = Tasks.task("release", "r",
+ static final List NON_COMPOSITE_TASKS = new ArrayList() {
+ {
+ addAll(DEFAULT_TASKS_PER_PROJECT);
+ addAll(DEFAULT_TASKS_PER_RELEASE);
+ }
+ };
+
+ static Task RELEASE = Tasks.task("release", "fr",
"FULL RELEASE",
"Perform a full release of this project without interruptions",
- args -> DEFAULT_TASKS.forEach(task -> task.execute(args)));
+ args -> DEFAULT_TASKS_PER_PROJECT.forEach(task -> task.execute(args)));
+ static Task POST_RELEASE = Tasks.task("post-release", "pr",
+ "POST RELEASE TASKS",
+ "Perform post release tasks for this release without interruptions",
+ args -> DEFAULT_TASKS_PER_RELEASE.forEach(task -> task.execute(args)),
+ TaskType.POST_RELEASE);
static Task RELEASE_VERBOSE = Tasks.task("release-verbose", "r",
"FULL VERBOSE RELEASE",
"Perform a full release of this project in interactive mode (you'll be asked about skipping steps)",
- args -> DEFAULT_TASKS.forEach(task -> task.execute(args)));
+ args -> DEFAULT_TASKS_PER_PROJECT.forEach(task -> task.execute(args)));
+ static Task META_RELEASE = Tasks.task("meta-release", "x",
+ "META RELEASE",
+ "Perform a meta release of projects",
+ args -> DEFAULT_TASKS_PER_PROJECT.forEach(task -> {
+ args.properties.getMetaRelease().setEnabled(true);
+ task.execute(args);
+ }));
static final List COMPOSITE_TASKS = Stream.of(
RELEASE,
- RELEASE_VERBOSE
+ RELEASE_VERBOSE,
+ META_RELEASE
).collect(Collectors.toList());
- static final List ALL_TASKS = Stream.of(
- COMPOSITE_TASKS, DEFAULT_TASKS
+ static final List ALL_TASKS_PER_PROJECT = Stream.of(
+ COMPOSITE_TASKS, DEFAULT_TASKS_PER_PROJECT, DEFAULT_TASKS_PER_RELEASE
).flatMap(List::stream).collect(Collectors.toList());
- static Task task(String name, String shortName, String header, String description, Consumer function) {
- return new Task(name, shortName, header, description, function);
+ static Task task(String name, String shortName, String header, String description,
+ Consumer function) {
+ return task(name, shortName, header, description, function, TaskType.RELEASE);
+ }
+
+ static Task task(String name, String shortName, String header, String description,
+ Consumer function, TaskType taskType) {
+ return new Task(name, shortName, header, description, function, taskType);
}
static List forNames(List tasks, List names) {
@@ -114,7 +144,11 @@ class Tasks {
.collect(Collectors.toList());
}
- static String tasksInOrder() {
- return DEFAULT_TASKS.stream().map(task -> task.name).collect(Collectors.joining(","));
+ static String allTasksInOrder() {
+ return ALL_TASKS_PER_PROJECT.stream().map(task -> task.name).collect(Collectors.joining(","));
}
}
+
+enum TaskType {
+ RELEASE, POST_RELEASE
+}
\ No newline at end of file
diff --git a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java
index 8fdc2184..7a81162b 100644
--- a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java
+++ b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/AcceptanceTests.java
@@ -7,8 +7,12 @@ import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import org.apache.maven.model.Model;
import org.assertj.core.api.BDDAssertions;
@@ -20,12 +24,15 @@ import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
+import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.cloud.release.internal.Releaser;
import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.cloud.release.internal.docs.DocumentationUpdater;
import org.springframework.cloud.release.internal.git.GitTestUtils;
import org.springframework.cloud.release.internal.git.ProjectGitHandler;
import org.springframework.cloud.release.internal.gradle.GradleUpdater;
+import org.springframework.cloud.release.internal.options.Options;
+import org.springframework.cloud.release.internal.options.OptionsBuilder;
import org.springframework.cloud.release.internal.pom.ProjectPomUpdater;
import org.springframework.cloud.release.internal.pom.ProjectVersion;
import org.springframework.cloud.release.internal.pom.Projects;
@@ -37,6 +44,7 @@ import org.springframework.cloud.release.internal.sagan.Release;
import org.springframework.cloud.release.internal.sagan.SaganClient;
import org.springframework.cloud.release.internal.sagan.SaganUpdater;
import org.springframework.cloud.release.internal.template.TemplateGenerator;
+import org.springframework.context.ApplicationContext;
import org.springframework.util.FileSystemUtils;
/**
@@ -45,13 +53,20 @@ import org.springframework.util.FileSystemUtils;
public class AcceptanceTests {
@Rule public TemporaryFolder tmp = new TemporaryFolder();
+ @Rule public OutputCapture capture = new OutputCapture();
TestPomReader testPomReader = new TestPomReader();
File springCloudConsulProject;
File temporaryFolder;
File documentationFolder;
TestProjectGitHandler gitHandler;
+ NonAssertingTestProjectGitHandler nonAssertingGitHandler;
SaganClient saganClient = Mockito.mock(SaganClient.class);
ReleaserProperties releaserProperties;
+ TemplateGenerator templateGenerator;
+ SaganUpdater saganUpdater;
+ DocumentationUpdater documentationUpdater;
+ ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class);
+ ReleaserPropertiesUpdater updater = new ReleaserPropertiesUpdater(this.applicationContext);
@Before
public void setup() throws Exception {
@@ -105,6 +120,7 @@ public class AcceptanceTests {
SpringReleaser releaser = templateOnlyReleaser(project, "spring-cloud-consul",
"vCamden.SR5", "1.1.2.RELEASE");
this.releaserProperties.getGit().setFetchVersionsFromGit(false);
+ this.releaserProperties.getFixedVersions().put("spring-cloud-release", "Finchley.RELEASE");
this.releaserProperties.getFixedVersions().put("spring-cloud-consul", "2.3.4.RELEASE");
File temporaryDestination = tmp.newFolder();
this.releaserProperties.getGit().setCloneDestinationDir(temporaryDestination.getAbsolutePath());
@@ -164,6 +180,80 @@ public class AcceptanceTests {
.contains("Camden.SR5");
}
+ @Test
+ public void should_perform_a_meta_release_of_sc_release_and_consul() throws Exception {
+ // simulates an org
+ Map versions = new HashMap<>();
+ versions.put("spring-cloud-release", "Camden.BUILD-SNAPSHOT");
+ versions.put("spring-cloud-consul", "1.1.2.BUILD-SNAPSHOT");
+ SpringReleaser releaser = metaReleaser(versions);
+
+ releaser.release(new OptionsBuilder().metaRelease(true).options());
+
+ then(this.nonAssertingGitHandler.clonedProjects).hasSize(2);
+ this.nonAssertingGitHandler.clonedProjects
+ .forEach(project -> {
+ then(Arrays.asList("spring-cloud-starter-build",
+ "spring-cloud-consul")).contains(pom(project).getArtifactId());
+ then(capture.toString()).contains("executed_build", "executed_deploy", "executed_docs");
+ });
+ BDDMockito.then(saganUpdater).should(BDDMockito.atLeastOnce()).updateSagan(BDDMockito.anyString(),
+ BDDMockito.any(ProjectVersion.class), BDDMockito.any(ProjectVersion.class));
+ BDDMockito.then(documentationUpdater).should()
+ .updateDocsRepo(BDDMockito.any(ProjectVersion.class), BDDMockito.anyString());
+ }
+
+ @Test
+ public void should_perform_a_meta_release_of_consul_only_when_run_from_got_passed() throws Exception {
+ // simulates an org
+ Map versions = new HashMap<>();
+ versions.put("spring-cloud-release", "Camden.BUILD-SNAPSHOT");
+ versions.put("spring-cloud-build", "1.1.2.BUILD-SNAPSHOT");
+ versions.put("spring-cloud-consul", "1.1.2.BUILD-SNAPSHOT");
+ SpringReleaser releaser = metaReleaser(versions);
+
+ releaser.release(new OptionsBuilder().metaRelease(true)
+ .startFrom("spring-cloud-consul")
+ .options());
+
+ then(this.nonAssertingGitHandler.clonedProjects).hasSize(1);
+ this.nonAssertingGitHandler.clonedProjects
+ .forEach(project -> {
+ then(pom(project).getArtifactId()).isEqualTo("spring-cloud-consul");
+ then(capture.toString()).contains("executed_build", "executed_deploy", "executed_docs");
+ });
+ BDDMockito.then(saganUpdater).should(BDDMockito.atLeastOnce()).updateSagan(BDDMockito.anyString(),
+ BDDMockito.any(ProjectVersion.class), BDDMockito.any(ProjectVersion.class));
+ BDDMockito.then(documentationUpdater).should()
+ .updateDocsRepo(BDDMockito.any(ProjectVersion.class), BDDMockito.anyString());
+ }
+
+ @Test
+ public void should_perform_a_meta_release_of_build_and_consul_only_when_task_names_got_passed() throws Exception {
+ // simulates an org
+ Map versions = new HashMap<>();
+ versions.put("spring-cloud-release", "Camden.BUILD-SNAPSHOT");
+ versions.put("spring-cloud-build", "1.1.2.BUILD-SNAPSHOT");
+ versions.put("spring-cloud-consul", "1.1.2.BUILD-SNAPSHOT");
+ SpringReleaser releaser = metaReleaser(versions);
+
+ releaser.release(new OptionsBuilder().metaRelease(true)
+ .taskNames(Arrays.asList("spring-cloud-build", "spring-cloud-consul"))
+ .options());
+
+ then(this.nonAssertingGitHandler.clonedProjects).hasSize(2);
+ this.nonAssertingGitHandler.clonedProjects
+ .forEach(project -> {
+ then(Arrays.asList("spring-cloud-build",
+ "spring-cloud-consul")).contains(pom(project).getArtifactId());
+ then(capture.toString()).contains("executed_build", "executed_deploy", "executed_docs");
+ });
+ BDDMockito.then(saganUpdater).should(BDDMockito.atLeastOnce()).updateSagan(BDDMockito.anyString(),
+ BDDMockito.any(ProjectVersion.class), BDDMockito.any(ProjectVersion.class));
+ BDDMockito.then(documentationUpdater).should()
+ .updateDocsRepo(BDDMockito.any(ProjectVersion.class), BDDMockito.anyString());
+ }
+
// issue #74
@Test
public void should_perform_a_release_of_sc_build() throws Exception {
@@ -366,6 +456,11 @@ public class AcceptanceTests {
return releaserWithFullDeployment(expectedVersion, projectName, properties);
}
+ private SpringReleaser metaReleaser(Map versions) throws Exception {
+ ReleaserProperties properties = metaReleaserProperties(versions);
+ return metaReleaserWithFullDeployment(properties);
+ }
+
private SpringReleaser releaserWithFullDeployment(String expectedVersion,
String projectName, ReleaserProperties properties) throws Exception {
Releaser releaser = defaultReleaser(expectedVersion, projectName, properties);
@@ -373,7 +468,26 @@ public class AcceptanceTests {
@Override String chosenOption() {
return "0";
}
- });
+
+ @Override void postReleaseOptions(Options options, Args defaultArgs) {
+ options.interactive = false;
+ super.postReleaseOptions(options, defaultArgs);
+ }
+ }, updater);
+ }
+
+ private SpringReleaser metaReleaserWithFullDeployment(ReleaserProperties properties) throws Exception {
+ Releaser releaser = defaultMetaReleaser(properties);
+ return new SpringReleaser(releaser, properties, new OptionsProcessor(releaser, properties) {
+ @Override String chosenOption() {
+ return "0";
+ }
+
+ @Override void postReleaseOptions(Options options, Args defaultArgs) {
+ options.interactive = false;
+ super.postReleaseOptions(options, defaultArgs);
+ }
+ }, updater);
}
private SpringReleaser releaserWithSnapshotScRelease(File projectFile, String projectName,
@@ -387,9 +501,14 @@ public class AcceptanceTests {
Releaser releaser = defaultReleaser(expectedVersion, projectName, properties);
return new SpringReleaser(releaser, properties, new OptionsProcessor(releaser, properties) {
@Override String chosenOption() {
- return "10";
+ return "12";
}
- });
+
+ @Override void postReleaseOptions(Options options, Args defaultArgs) {
+ options.interactive = true;
+ super.postReleaseOptions(options, defaultArgs);
+ }
+ }, updater);
}
private Releaser defaultReleaser(String expectedVersion, String projectName,
@@ -415,15 +534,52 @@ public class AcceptanceTests {
return releaser;
}
+ private Releaser defaultMetaReleaser(ReleaserProperties properties) throws Exception {
+ ProjectPomUpdater pomUpdater = new ProjectPomUpdater(properties);
+ ProjectBuilder projectBuilder = new ProjectBuilder(properties);
+ NonAssertingTestProjectGitHandler handler = new NonAssertingTestProjectGitHandler(properties);
+ TemplateGenerator templateGenerator = Mockito.spy(new TemplateGenerator(properties, handler));
+ GradleUpdater gradleUpdater = new GradleUpdater(properties);
+ SaganUpdater saganUpdater = Mockito.spy(new SaganUpdater(this.saganClient));
+ DocumentationUpdater documentationUpdater = Mockito.spy(new DocumentationUpdater(handler) {
+ @Override public File updateDocsRepo(ProjectVersion currentProject,
+ String springCloudReleaseBranch) {
+ File file = super.updateDocsRepo(currentProject, springCloudReleaseBranch);
+ documentationFolder = file;
+ return file;
+ }
+ });
+ Releaser releaser = Mockito.spy(new Releaser(pomUpdater, projectBuilder, handler,
+ templateGenerator, gradleUpdater, saganUpdater, documentationUpdater));
+ this.nonAssertingGitHandler = handler;
+ this.templateGenerator = templateGenerator;
+ this.saganUpdater = saganUpdater;
+ this.documentationUpdater = documentationUpdater;
+ return releaser;
+ }
+
private ReleaserProperties releaserProperties(File project, String branch) throws URISyntaxException {
ReleaserProperties releaserProperties = new ReleaserProperties();
releaserProperties.getGit().setSpringCloudReleaseGitUrl(file("/projects/spring-cloud-release/").toURI().getPath());
releaserProperties.getGit().setDocumentationUrl(file("/projects/spring-cloud-static-angel/").toURI().getPath());
- releaserProperties.getPom().setBranch(branch);
- releaserProperties.setWorkingDir(project.getPath());
releaserProperties.getMaven().setBuildCommand("echo build");
releaserProperties.getMaven().setDeployCommand("echo deploy");
releaserProperties.getMaven().setPublishDocsCommands(new String[] { "echo docs"} );
+ releaserProperties.setWorkingDir(project.getPath());
+ releaserProperties.getPom().setBranch(branch);
+ this.releaserProperties = releaserProperties;
+ return releaserProperties;
+ }
+
+ private ReleaserProperties metaReleaserProperties(Map versions) throws URISyntaxException {
+ ReleaserProperties releaserProperties = new ReleaserProperties();
+ releaserProperties.getGit().setDocumentationUrl(file("/projects/spring-cloud-static-angel/").toURI().getPath());
+ releaserProperties.getMaven().setBuildCommand("echo executed_build");
+ releaserProperties.getMaven().setDeployCommand("echo executed_deploy");
+ releaserProperties.getMaven().setPublishDocsCommands(new String[] { "echo executed_docs"} );
+ releaserProperties.getMetaRelease().setGitOrgUrl("file://" + this.temporaryFolder.getAbsolutePath());
+ releaserProperties.getMetaRelease().setEnabled(true);
+ releaserProperties.setFixedVersions(versions);
this.releaserProperties = releaserProperties;
return releaserProperties;
}
@@ -466,6 +622,48 @@ public class AcceptanceTests {
}
}
+ class NonAssertingTestProjectGitHandler extends ProjectGitHandler {
+
+ boolean closedMilestones = false;
+ boolean issueCreatedInSpringGuides = false;
+ List clonedProjects = new ArrayList<>();
+
+ public NonAssertingTestProjectGitHandler(ReleaserProperties properties) {
+ super(properties);
+ }
+
+ @Override public void closeMilestone(ProjectVersion releaseVersion) {
+ this.closedMilestones = true;
+ }
+
+ @Override public void createIssueInSpringGuides(Projects projects,
+ ProjectVersion version) {
+ this.issueCreatedInSpringGuides = true;
+ }
+
+ @Override public String milestoneUrl(ProjectVersion releaseVersion) {
+ return "http://foo.bar.com/" + releaseVersion.toString();
+ }
+
+ @Override public File cloneScReleaseProject() {
+ File file = super.cloneScReleaseProject();
+ this.clonedProjects.add(file);
+ return file;
+ }
+
+ @Override public File cloneDocumentationProject() {
+ File file = super.cloneDocumentationProject();
+ this.clonedProjects.add(file);
+ return file;
+ }
+
+ @Override public File cloneProjectFromOrg(String projectName) {
+ File file = super.cloneProjectFromOrg(projectName);
+ this.clonedProjects.add(file);
+ return file;
+ }
+ }
+
private File tmpFile(String relativePath) {
return new File(this.temporaryFolder, relativePath);
}
diff --git a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/OptionsProcessorTests.java b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/OptionsProcessorTests.java
index 39875baf..9c0046bf 100644
--- a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/OptionsProcessorTests.java
+++ b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/OptionsProcessorTests.java
@@ -210,6 +210,10 @@ public class OptionsProcessorTests {
@Override Task releaseTask() {
return firstTask;
}
+
+ @Override String chosenOption() {
+ return "0";
+ }
};
Options options = nonInteractiveOpts().fullRelease(true).options();
@@ -226,6 +230,10 @@ public class OptionsProcessorTests {
@Override Task releaseVerboseTask() {
return firstTask;
}
+
+ @Override String chosenOption() {
+ return "0";
+ }
};
Options options = interactiveOpts().fullRelease(true).options();
@@ -245,7 +253,7 @@ public class OptionsProcessorTests {
}
private Args args() {
- return new Args(null, null, null, null, null, null, false);
+ return new Args(null, null, null, null, null, null, false, TaskType.RELEASE);
}
private List list(String... list) {
diff --git a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesIntegrationTests.java b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesIntegrationTests.java
new file mode 100644
index 00000000..b8195534
--- /dev/null
+++ b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesIntegrationTests.java
@@ -0,0 +1,67 @@
+package org.springframework.cloud.release.internal.spring;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.assertj.core.api.BDDAssertions;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.BDDMockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+import org.springframework.cloud.release.internal.ReleaserApplication;
+import org.springframework.cloud.release.internal.ReleaserProperties;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+@RunWith(SpringRunner.class)
+@Import(ReleaserPropertiesIntegrationTests.Config.class)
+public class ReleaserPropertiesIntegrationTests {
+
+ @Autowired List propertiesAware;
+ @Autowired ApplicationContext context;
+
+ @Test public void should_update_properties() {
+ ReleaserProperties properties = new ReleaserProperties();
+ properties.getPom().setBranch("fooooo");
+
+ new ReleaserPropertiesUpdater(this.context).updateProperties(properties);
+
+ BDDAssertions.then(this.propertiesAware).hasSize(2);
+ this.propertiesAware.forEach(aware ->
+ BDDAssertions.then(((ReleaserPropertiesHaving) aware)
+ .properties.getPom().getBranch()).isEqualTo("fooooo"));
+ }
+
+ @Configuration
+ static class Config {
+ @Bean ReleaserPropertiesAware aware1() {
+ return new ReleaserPropertiesHaving();
+ }
+ @Bean ReleaserPropertiesAware aware2() {
+ return new ReleaserPropertiesHaving();
+ }
+ }
+
+ static class ReleaserPropertiesHaving implements ReleaserPropertiesAware {
+
+ ReleaserProperties properties;
+
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.properties = properties;
+ }
+
+ ReleaserProperties getProps() {
+ return this.properties;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdaterTests.java b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdaterTests.java
new file mode 100644
index 00000000..9cde5dd2
--- /dev/null
+++ b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/ReleaserPropertiesUpdaterTests.java
@@ -0,0 +1,48 @@
+package org.springframework.cloud.release.internal.spring;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.assertj.core.api.BDDAssertions;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.BDDMockito;
+import org.springframework.cloud.release.internal.ReleaserProperties;
+import org.springframework.cloud.release.internal.ReleaserPropertiesAware;
+import org.springframework.context.ApplicationContext;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+public class ReleaserPropertiesUpdaterTests {
+
+ ApplicationContext context = BDDMockito.mock(ApplicationContext.class);
+
+ @Test public void should_update_properties() {
+ Aware aware = new Aware();
+ BDDMockito.given(this.context.getBeansOfType(BDDMockito.any(Class.class)))
+ .willReturn(beansOfType(aware));
+ ReleaserPropertiesUpdater updater = new ReleaserPropertiesUpdater(this.context);
+
+ updater.updateProperties(new ReleaserProperties());
+
+ BDDAssertions.then(aware.properties).isNotNull();
+ }
+
+ private Map beansOfType(Aware aware) {
+ Map map = new HashMap<>();
+ map.put("foo", aware);
+ return map;
+ }
+
+ class Aware implements ReleaserPropertiesAware {
+
+ ReleaserProperties properties;
+
+ @Override public void setReleaserProperties(ReleaserProperties properties) {
+ this.properties = properties;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/TaskTests.java b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/TaskTests.java
index cf3bbe33..974ef26f 100644
--- a/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/TaskTests.java
+++ b/spring-cloud-release-tools-spring/src/test/java/org/springframework/cloud/release/internal/spring/TaskTests.java
@@ -10,7 +10,6 @@ import org.springframework.boot.test.rule.OutputCapture;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.BDDAssertions.thenThrownBy;
-import static org.junit.Assert.*;
/**
* @author Marcin Grzejszczak
@@ -27,21 +26,19 @@ public class TaskTests {
}
});
- task.execute(Mockito.mock(Args.class));
+ task.execute(new Args(TaskType.RELEASE));
then(someBool.get()).isTrue();
}
@Test public void should_fail_with_nice_text_on_exception() {
final AtomicBoolean someBool = new AtomicBoolean();
- Task task = new Task("foo", "bar", "baz", "descr", new Consumer() {
- @Override public void accept(Args args) {
- someBool.set(true);
- throw new RuntimeException("foooooooo");
- }
+ Task task = new Task("foo", "bar", "baz", "descr", args -> {
+ someBool.set(true);
+ throw new RuntimeException("foooooooo");
});
- thenThrownBy(() -> task.execute(Mockito.mock(Args.class)))
+ thenThrownBy(() -> task.execute(new Args(TaskType.RELEASE)))
.isInstanceOf(RuntimeException.class);
then(someBool.get()).isTrue();
then(this.capture.toString())