From 412b78311d063f7a086059352939446340e3adeb Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Wed, 31 Oct 2018 10:53:05 +0100 Subject: [PATCH] Added Gradle updater to project updates --- .../cloud/release/internal/Releaser.java | 10 +++--- .../internal/gradle/GradleUpdater.java | 10 +++--- .../release/internal/pom/PomUpdater.java | 3 ++ .../internal/pom/ProjectPomUpdater.java | 9 +++++ .../internal/post/PostReleaseActions.java | 24 ++++++++----- .../internal/gradle/GradleUpdaterTests.java | 4 +-- .../internal/pom/ProjectPomUpdaterTests.java | 15 ++++++++ .../post/PostReleaseActionsTests.java | 35 +++++++++++++------ .../spring/ReleaserConfiguration.java | 4 +-- .../cloud/release/internal/spring/Tasks.java | 2 +- 10 files changed, 81 insertions(+), 35 deletions(-) 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 73b0c4e1..45e68275 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 @@ -60,16 +60,16 @@ public class Releaser { return this.projectPomUpdater.fixedVersions(); } - public void updateProjectFromScRelease(File project, Projects versions, + public void updateProjectFromBom(File project, Projects versions, ProjectVersion versionFromScRelease) { - updateProjectFromScRelease(project, versions, versionFromScRelease, ASSERT_SNAPSHOTS); + updateProjectFromBom(project, versions, versionFromScRelease, ASSERT_SNAPSHOTS); } - private void updateProjectFromScRelease(File project, Projects versions, + private void updateProjectFromBom(File project, Projects versions, ProjectVersion versionFromScRelease, boolean assertSnapshots) { this.projectPomUpdater.updateProjectFromReleaseTrain(project, versions, versionFromScRelease, assertSnapshots); - this.gradleUpdater.updateProjectFromSCRelease(project, versions, + this.gradleUpdater.updateProjectFromBom(project, versions, versionFromScRelease, assertSnapshots); ProjectVersion changedVersion = new ProjectVersion(project); log.info("\n\nProject was successfully updated to [{}]", changedVersion); @@ -105,7 +105,7 @@ public class Releaser { log.info("Original project version is [{}]", originalVersion); if ((scReleaseVersion.isRelease() || scReleaseVersion.isServiceRelease()) && originalVersion.isSnapshot()) { Projects newProjects = Projects.forRollback(projects, originalVersion); - updateProjectFromScRelease(project, newProjects, originalVersion, SKIP_SNAPSHOT_ASSERTION); + updateProjectFromBom(project, newProjects, originalVersion, SKIP_SNAPSHOT_ASSERTION); this.projectGitHandler.commitAfterBumpingVersions(project, originalVersion); log.info("\nSuccessfully reverted the commit and bumped snapshot versions"); } else { 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 ad733f1c..a7aeffa3 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 @@ -36,17 +36,17 @@ public class GradleUpdater implements ReleaserPropertiesAware { /** * For the given root folder (typically the working directory) performs the whole - * flow of updating {@code gradle.properties} with values from Spring Cloud Release project. + * flow of updating {@code gradle.properties} with values from BOM project. * Remember to pass the mapping from a property name inside {@code gradle.properties} to * the project name via {@link ReleaserProperties.Gradle#gradlePropsSubstitution} * @param projectRoot - root folder with project to update * @param projects - versions of projects used to update poms - * @param versionFromScRelease - version for the project from Spring Cloud Release + * @param versionFromBom - version for the project from Spring Cloud Release * @param assertSnapshots - should snapshots presence be asserted */ - public void updateProjectFromSCRelease(File projectRoot, Projects projects, - ProjectVersion versionFromScRelease, boolean assertSnapshots) { - processAllGradleProps(projectRoot, projects, versionFromScRelease, assertSnapshots); + public void updateProjectFromBom(File projectRoot, Projects projects, + ProjectVersion versionFromBom, boolean assertSnapshots) { + processAllGradleProps(projectRoot, projects, versionFromBom, assertSnapshots); } private void processAllGradleProps(File projectRoot, Projects projects, diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java index eefc9229..bfeccea7 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/PomUpdater.java @@ -64,6 +64,9 @@ class PomUpdater { */ boolean shouldProjectBeUpdated(File rootFolder, Versions versions) { File rootPom = rootPom(rootFolder); + if (!rootPom.exists()) { + return false; + } Model model = this.pomReader.readPom(rootPom); String artifactId = artifactId(model); if (!versions.shouldBeUpdated(artifactId)) { 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 c54066ae..9c3ccc90 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 @@ -56,6 +56,11 @@ public class ProjectPomUpdater implements ReleaserPropertiesAware { this.gitRepo = new ProjectGitHandler(properties); } + ProjectPomUpdater(ReleaserProperties properties, ProjectGitHandler gitRepo) { + this.properties = properties; + this.gitRepo = gitRepo; + } + /** * For the given root folder (typically the working directory) retrieves list of versions * for a given release version. @@ -109,6 +114,10 @@ public class ProjectPomUpdater implements ReleaserPropertiesAware { private void updatePoms(File projectRoot, Projects projects, ProjectVersion versionFromScRelease, boolean assertSnapshots) { File rootPom = new File(projectRoot, "pom.xml"); + if (!rootPom.exists()) { + log.info("No pom.xml present, skipping!"); + return; + } ModelWrapper rootPomModel = this.pomUpdater.readModel(rootPom); processAllPoms(projectRoot, new PomWalker(rootPomModel, projects, this.pomUpdater, this.properties, versionFromScRelease, assertSnapshots)); diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java index 6a484e6b..b2b73e82 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/post/PostReleaseActions.java @@ -3,7 +3,6 @@ package org.springframework.cloud.release.internal.post; import java.io.Closeable; import java.io.File; import java.io.IOException; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -18,6 +17,7 @@ import org.slf4j.LoggerFactory; import org.springframework.cloud.release.internal.ReleaserProperties; import org.springframework.cloud.release.internal.git.ProjectGitHandler; +import org.springframework.cloud.release.internal.gradle.GradleUpdater; import org.springframework.cloud.release.internal.pom.ProjectPomUpdater; import org.springframework.cloud.release.internal.pom.ProjectVersion; import org.springframework.cloud.release.internal.pom.Projects; @@ -35,14 +35,16 @@ public class PostReleaseActions implements Closeable { private final ProjectGitHandler projectGitHandler; private final ProjectPomUpdater projectPomUpdater; + private final GradleUpdater gradleUpdater; private final ProjectBuilder projectBuilder; private final ReleaserProperties properties; public PostReleaseActions(ProjectGitHandler projectGitHandler, - ProjectPomUpdater projectPomUpdater, ProjectBuilder projectBuilder, + ProjectPomUpdater projectPomUpdater, GradleUpdater gradleUpdater, ProjectBuilder projectBuilder, ReleaserProperties properties) { this.projectGitHandler = projectGitHandler; this.projectPomUpdater = projectPomUpdater; + this.gradleUpdater = gradleUpdater; this.projectBuilder = projectBuilder; this.properties = properties; } @@ -63,8 +65,7 @@ public class PostReleaseActions implements Closeable { ProjectVersion projectVersion = new ProjectVersion(file); String releaseTrainVersion = projects.releaseTrain(this.properties).version; Projects newProjects = addVersionForTestsProject(projects, projectVersion, releaseTrainVersion); - this.projectPomUpdater - .updateProjectFromReleaseTrain(file, newProjects, projectVersion, false); + updateWithVersions(file, newProjects); this.projectBuilder.build(projectVersion, file.getAbsolutePath()); } @@ -134,9 +135,7 @@ public class PostReleaseActions implements Closeable { .cloneAndGuessBranch(url, releaseTrainVersion, projectVersion); Projects newPostRelease = new Projects(postRelease); newPostRelease.add(new ProjectVersion(file)); - this.projectPomUpdater - .updateProjectFromReleaseTrain(file, newPostRelease, - new ProjectVersion(file), false); + updateWithVersions(file, newPostRelease); this.projectGitHandler .commit(file, "Updated versions after [" + releaseTrainVersion + "] " + "release train and [" + projectVersionForReleaseTrain.version + "] [" @@ -144,6 +143,14 @@ public class PostReleaseActions implements Closeable { this.projectGitHandler.pushCurrentBranch(file); } + private void updateWithVersions(File file, Projects newPostRelease) { + this.projectPomUpdater + .updateProjectFromReleaseTrain(file, newPostRelease, + new ProjectVersion(file), false); + this.gradleUpdater.updateProjectFromBom(file, newPostRelease, + new ProjectVersion(file), false); + } + private ProjectAndFuture run(String key, String url, Runnable runnable) { return new ProjectAndFuture(key, url, SERVICE.submit(runnable)); } @@ -185,8 +192,7 @@ public class PostReleaseActions implements Closeable { ProjectVersion projectVersion = new ProjectVersion(file); String releaseTrainVersion = projects.releaseTrain(this.properties).version; Projects newProjects = addVersionForTestsProject(projects, projectVersion, releaseTrainVersion); - this.projectPomUpdater - .updateProjectFromReleaseTrain(file, newProjects, projectVersion, false); + updateWithVersions(file, newProjects); this.projectBuilder.generateReleaseTrainDocs(releaseTrainVersion, file.getAbsolutePath()); } diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/gradle/GradleUpdaterTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/gradle/GradleUpdaterTests.java index 84477f53..dc13cac5 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/gradle/GradleUpdaterTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/gradle/GradleUpdaterTests.java @@ -46,7 +46,7 @@ public class GradleUpdaterTests { new ProjectVersion("spring-cloud-sleuth", "2.0.0") ); - new GradleUpdater(properties).updateProjectFromSCRelease(projectRoot, + new GradleUpdater(properties).updateProjectFromBom(projectRoot, projects, new ProjectVersion("spring-cloud-contract", "1.0.0"), true); then(asString(tmpFile("gradleproject/gradle.properties"))) @@ -69,7 +69,7 @@ public class GradleUpdaterTests { new ProjectVersion("spring-cloud-sleuth", "2.0.0") ); - thenThrownBy(() -> new GradleUpdater(properties).updateProjectFromSCRelease(projectRoot, + thenThrownBy(() -> new GradleUpdater(properties).updateProjectFromBom(projectRoot, projects, new ProjectVersion("spring-cloud-contract", "1.0.0"), true)) .hasMessageContaining("contains a SNAPSHOT version for a non snapshot release in line number"); } diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdaterTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdaterTests.java index 60ecd827..db6ebbff 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdaterTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/pom/ProjectPomUpdaterTests.java @@ -1,11 +1,15 @@ package org.springframework.cloud.release.internal.pom; +import java.io.File; import java.util.Map; import java.util.stream.Collectors; import org.assertj.core.api.BDDAssertions; import org.junit.Test; +import org.mockito.BDDMockito; + import org.springframework.cloud.release.internal.ReleaserProperties; +import org.springframework.cloud.release.internal.git.ProjectGitHandler; import static org.junit.Assert.*; @@ -54,4 +58,15 @@ public class ProjectPomUpdaterTests { .containsEntry("spring-cloud-release", "Finchley.BUILD-SNAPSHOT") .containsEntry("spring-cloud", "Finchley.BUILD-SNAPSHOT"); } + + @Test public void should_skip_any_steps_if_there_is_no_pom_xml() { + ReleaserProperties properties = new ReleaserProperties(); + ProjectGitHandler handler = BDDMockito.mock(ProjectGitHandler.class); + ProjectPomUpdater updater = new ProjectPomUpdater(properties, handler); + + updater.updateProjectFromReleaseTrain( + new File("target"), new Projects(), new ProjectVersion("foo", "1.0.0.RELEASE"), false); + + BDDMockito.then(handler).shouldHaveZeroInteractions(); + } } \ No newline at end of file diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java index 2da2d591..d0078c36 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/post/PostReleaseActionsTests.java @@ -2,9 +2,7 @@ package org.springframework.cloud.release.internal.post; import java.io.File; import java.net.URISyntaxException; -import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -17,11 +15,13 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.mockito.BDDMockito; import org.springframework.cloud.release.internal.PomUpdateAcceptanceTests; import org.springframework.cloud.release.internal.ReleaserProperties; 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.pom.ProjectPomUpdater; import org.springframework.cloud.release.internal.pom.ProjectVersion; import org.springframework.cloud.release.internal.pom.Projects; @@ -40,6 +40,7 @@ public class PostReleaseActionsTests { public TemporaryFolder tmp = new TemporaryFolder(); File temporaryFolder; TestPomReader testPomReader = new TestPomReader(); + GradleUpdater gradleUpdater = BDDMockito.mock(GradleUpdater.class); ReleaserProperties properties = new ReleaserProperties(); File cloned; LinkedMultiValueMap clonedTestProjects = new LinkedMultiValueMap<>(); @@ -77,22 +78,24 @@ public class PostReleaseActionsTests { public void should_do_nothing_when_is_not_meta_release_and_update_test_is_called() { this.properties.getMetaRelease().setEnabled(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.runUpdatedTests(currentGa()); BDDAssertions.then(cloned).isNull(); + BDDMockito.then(gradleUpdater).shouldHaveZeroInteractions(); } @Test public void should_do_nothing_when_the_switch_for_sample_check_is_off_and_update_test_is_called() { this.properties.getGit().setRunUpdatedSamples(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.runUpdatedTests(currentGa()); BDDAssertions.then(cloned).isNull(); + BDDMockito.then(gradleUpdater).shouldHaveZeroInteractions(); } @Test @@ -101,7 +104,7 @@ public class PostReleaseActionsTests { this.properties.getGit().setTestSamplesProjectUrl(tmpFile("spring-cloud-core-tests/").getAbsolutePath() + "/"); this.properties.getMaven().setBuildCommand("touch build.log"); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.runUpdatedTests(currentGa()); @@ -110,13 +113,19 @@ public class PostReleaseActionsTests { BDDAssertions.then(rootPom.getParent().getVersion()).isEqualTo("2.0.4.RELEASE"); BDDAssertions.then(sleuthParentPomVersion()).isEqualTo("2.0.4.RELEASE"); BDDAssertions.then(new File(cloned, "build.log")).exists(); + thenGradleUpdaterWasCalled(); + } + + private void thenGradleUpdaterWasCalled() { + BDDMockito.then(gradleUpdater).should().updateProjectFromBom(BDDMockito.any(File.class), + BDDMockito.any(Projects.class), BDDMockito.any(ProjectVersion.class), BDDMockito.eq(false)); } @Test public void should_do_nothing_when_is_not_meta_release_and_release_train_docs_generation_is_called() { this.properties.getMetaRelease().setEnabled(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.generateReleaseTrainDocumentation(currentGa()); @@ -127,7 +136,7 @@ public class PostReleaseActionsTests { public void should_do_nothing_when_the_switch_for_sample_check_is_off_and_release_train_docs_generation_is_called() { this.properties.getGit().setUpdateReleaseTrainDocs(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.generateReleaseTrainDocumentation(currentGa()); @@ -140,7 +149,7 @@ public class PostReleaseActionsTests { this.properties.getGit().setReleaseTrainDocsUrl(tmpFile("spring-cloud-core-tests/").getAbsolutePath() + "/"); this.properties.getMaven().setGenerateReleaseTrainDocsCommand("touch generate.log"); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.generateReleaseTrainDocumentation(currentGa()); @@ -149,28 +158,31 @@ public class PostReleaseActionsTests { BDDAssertions.then(rootPom.getParent().getVersion()).isEqualTo("2.0.4.RELEASE"); BDDAssertions.then(sleuthParentPomVersion()).isEqualTo("2.0.4.RELEASE"); BDDAssertions.then(new File(cloned, "generate.log")).exists(); + thenGradleUpdaterWasCalled(); } @Test public void should_do_nothing_when_is_not_meta_release_and_test_samples_update_is_called() { this.properties.getMetaRelease().setEnabled(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.updateAllTestSamples(currentGa()); BDDAssertions.then(cloned).isNull(); + BDDMockito.then(gradleUpdater).shouldHaveZeroInteractions(); } @Test public void should_do_nothing_when_the_switch_for_test_samples_update_check_is_off_and_test_samples_update_is_called() { this.properties.getGit().setUpdateReleaseTrainDocs(false); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.updateAllTestSamples(currentGa()); BDDAssertions.then(cloned).isNull(); + BDDMockito.then(gradleUpdater).shouldHaveZeroInteractions(); } @Test @@ -181,7 +193,7 @@ public class PostReleaseActionsTests { Collections.singletonList(tmpFile("spring-cloud-core-tests/") .getAbsolutePath() + "/")); PostReleaseActions actions = new PostReleaseActions(this.projectGitHandler, - this.updater, this.builder, this.properties); + this.updater, gradleUpdater, this.builder, this.properties); actions.updateAllTestSamples(currentGa()); @@ -198,6 +210,7 @@ public class PostReleaseActionsTests { RevCommit commit = iterator.next(); BDDAssertions.then(commit.getShortMessage()) .isEqualTo("Updated versions after [Finchley.SR1] release train and [2.0.1.RELEASE] [spring-cloud-sleuth] project release"); + thenGradleUpdaterWasCalled(); } private String sleuthParentPomVersion() { 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 707f48c0..d035b43c 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 @@ -78,8 +78,8 @@ class ReleaserConfiguration { @Bean PostReleaseActions postReleaseActions(ProjectGitHandler handler, ProjectPomUpdater pomUpdater, - ProjectBuilder projectBuilder, ReleaserProperties releaserProperties) { - return new PostReleaseActions(handler, pomUpdater, projectBuilder, releaserProperties); + GradleUpdater gradleUpdater, ProjectBuilder projectBuilder, ReleaserProperties releaserProperties) { + return new PostReleaseActions(handler, pomUpdater, gradleUpdater, projectBuilder, releaserProperties); } @Bean 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 9c2c9b5d..30c2d0a2 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 @@ -15,7 +15,7 @@ class Tasks { static Task UPDATING_POMS = task("updatePoms", "u", "UPDATING POMS", "Update poms with versions from Spring Cloud Release", - args -> args.releaser.updateProjectFromScRelease(args.project, args.projects, args.versionFromScRelease)); + args -> args.releaser.updateProjectFromBom(args.project, args.projects, args.versionFromScRelease)); static Task BUILD_PROJECT = task("build", "b", "BUILD PROJECT", "Build the project",