diff --git a/docs/CqPackagePlugin.adoc b/docs/CqPackagePlugin.adoc index 6696070..2523e3b 100644 --- a/docs/CqPackagePlugin.adoc +++ b/docs/CqPackagePlugin.adoc @@ -117,11 +117,14 @@ This uses https://github.com/TWCable/gradle-plugin-cq-bundle/blob/master/docs/Cq It can be useful to use an existing file rather than the output of `createPackage`. (e.g., In a deployment pipeline where the artifact is pulled from a repository.) -Setting the `package` system property (i.e., `-Dpackage=XX`) will force the +Setting the `package` system or project property (i.e., `-Dpackage=XX` or `-Ppackage=XX`) will force the use of the specified file. +If more control is needed, you can prepend the package key with the name of the project (with no leading colon). +For example, `-Psub-module-a.package=XX` will set the package property for just `:sub-module-a`. + This will fail if it doesn't have a file to upload, either because `createPackage` has not been run or the `package` -system property has not been set. +property has not been set. == Task `uninstallBundles` diff --git a/src/main/groovy/com/twcable/gradle/cqpackage/UploadPackage.groovy b/src/main/groovy/com/twcable/gradle/cqpackage/UploadPackage.groovy index f49d85a..6c94a6d 100644 --- a/src/main/groovy/com/twcable/gradle/cqpackage/UploadPackage.groovy +++ b/src/main/groovy/com/twcable/gradle/cqpackage/UploadPackage.groovy @@ -27,6 +27,7 @@ import org.gradle.api.GradleException import org.gradle.api.Project import javax.annotation.Nonnull +import javax.annotation.Nullable import static com.twcable.gradle.cqpackage.PackageStatus.NO_PACKAGE import static com.twcable.gradle.cqpackage.PackageStatus.UNKNOWN @@ -160,17 +161,33 @@ in other words, there's no indication it's missing its dependency at this point return uploadStatus } + + @Nullable + private static String projectOrSystemProperty(Project project, String propName) { + def hasProperty = project.hasProperty(propName) + if (hasProperty) { + return project.property(propName) as String + } + + return System.getProperty(propName) + } + /** * Returns the CQ Package file to use. * - * If a System Property of "package" is set, that is used. Otherwise the output of + * If a System Property or Project property of "package" is set, that is used. Otherwise the output of * the 'createPackage' task is used. */ @Nonnull static File getThePackageFile(Project project) { - def packageProperty = System.getProperty('package') + def packageProperty = projectOrSystemProperty(project, 'package') ?: + projectOrSystemProperty(project, "${project.name}.package") + if (packageProperty != null) { - return new File(packageProperty) + final filename = packageProperty + final file = new File(filename).absoluteFile + if (!file.exists()) throw new FileNotFoundException(file.toString()) + return file } def file = CreatePackageTask.from(project).archivePath @@ -180,7 +197,7 @@ in other words, there's no indication it's missing its dependency at this point } // TODO Detect this situation at task-graph build time and automatically add the createPackage task - throw new IllegalStateException("The 'package' system property is not set and there is no output from the 'createPackage' task") + throw new IllegalStateException("The 'package' system/project property is not set, nor is \"${project.name}.package\", and there is no output from the \"createPackage\" task") } } diff --git a/src/test/groovy/com/twcable/gradle/cqpackage/CqPackagePluginIntSpec.groovy b/src/test/groovy/com/twcable/gradle/cqpackage/CqPackagePluginIntSpec.groovy index bf52785..debbb46 100644 --- a/src/test/groovy/com/twcable/gradle/cqpackage/CqPackagePluginIntSpec.groovy +++ b/src/test/groovy/com/twcable/gradle/cqpackage/CqPackagePluginIntSpec.groovy @@ -285,7 +285,7 @@ class CqPackagePluginIntSpec extends IntegrationSpec { !result.success def exp = result.failure.cause exp.task.name == 'uploadPackage' - exp.cause.message.contains("there is no output from the 'createPackage' task") + exp.cause.message.contains("there is no output from the \"createPackage\" task") } @@ -317,6 +317,54 @@ class CqPackagePluginIntSpec extends IntegrationSpec { } + def "upload package with package Project property"() { + def testPackageFilename = this.class.classLoader.getResource("testpackage-1.0.1.zip").file + + getHandler.addPathResponse("/crx/packmgr/list.jsp", + new JsonBuilder( + PackageServerFixture.packageList( + PackageFixture.of("twc/test:testpackage:1.0.1") + ) + ).toString() + ) + + postHandler.addFileResponse("/crx/packmgr/service/.json", successfulPackageUpload().body) + + writeSimpleBuildFile() + + when: + result = runTasks("uploadPackage", "-Ppackage=${testPackageFilename}", "-x", "removePackage") + + then: + result.success + !result.wasExecuted(':createPackage') + } + + + def "upload package with project-specific package Project property"() { + def testPackageFilename = this.class.classLoader.getResource("testpackage-1.0.1.zip").file + + getHandler.addPathResponse("/crx/packmgr/list.jsp", + new JsonBuilder( + PackageServerFixture.packageList( + PackageFixture.of("twc/test:testpackage:1.0.1") + ) + ).toString() + ) + + postHandler.addFileResponse("/crx/packmgr/service/.json", successfulPackageUpload().body) + + writeSimpleBuildFile() + + when: + result = runTasks("uploadPackage", "-P${moduleName}.package=${testPackageFilename}", "-x", "removePackage") + + then: + result.success + !result.wasExecuted(':createPackage') + } + + def "install package"() { defaultPackageListHandler()