From b8545e4d6f394f3446bed771e09c17d2221f05ce Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov <654232+AlexeyTsvetkov@users.noreply.github.com> Date: Fri, 5 Feb 2021 09:11:03 +0300 Subject: [PATCH] Fix gradle plugin tests (#350) * Fix uninitialized lateinit var property exceptions on Linux and Windows lateinit property nonValidatedMacSigningSettings was not initialized on Linux and Windows * Revert reusing app image when creating installer Previously there was a change to reuse an app image, when creating an installer. So packaging would happen in two steps: 1. jpackage --type app-image ... 2. jpackage --type msi --app-image /path/to/app/image ... This way a user could always conveniently inspect, what goes into an installer. However, that change lead to bizzare crashes on Windows and Linux. As a workaround, this change reverts reusing an app image, when creating an installer. * Fix args filtering when invoking jpackage "app-image" args can also be used, when creating an installer w/o predefined app image (e.g. w/o `--app-image ...` argument) * Fix deb package name for tests on Linux --- .../internal/configureApplication.kt | 16 ++--- .../ValidatedMacOSNotarizationSettings.kt | 8 ++- .../application/tasks/AbstractJPackageTask.kt | 59 ++++++++++--------- .../tasks/AbstractNotarizationTask.kt | 3 +- .../compose/DesktopApplicationTest.kt | 5 +- .../org/jetbrains/compose/test/fileUtils.kt | 12 +++- 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt index aaeae42977..108074317a 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt @@ -59,19 +59,12 @@ internal fun Project.configurePackagingTasks(apps: Collection) { destinationDir.set(project.layout.buildDirectory.dir("compose/tmp/${app.name}/runtime")) } - val createDistributable = tasks.composeTask( - taskName("createDistributable", app), - args = listOf(TargetFormat.AppImage) - ) { - configurePackagingTask(app, createRuntimeImage = createRuntimeImage) - } - val packageFormats = app.nativeDistributions.targetFormats.map { targetFormat -> val packageFormat = tasks.composeTask( taskName("package", app, targetFormat.name), args = listOf(targetFormat) ) { - configurePackagingTask(app, createAppImage = createDistributable) + configurePackagingTask(app, createRuntimeImage = createRuntimeImage) } if (targetFormat.isCompatibleWith(OS.MacOS)) { @@ -104,6 +97,13 @@ internal fun Project.configurePackagingTasks(apps: Collection) { configurePackageUberJarForCurrentOS(app) } + val createDistributable = tasks.composeTask( + taskName("createDistributable", app), + args = listOf(TargetFormat.AppImage) + ) { + configurePackagingTask(app, createRuntimeImage = createRuntimeImage) + } + val runDistributable = project.tasks.composeTask( taskName("runDistributable", app), args = listOf(createDistributable) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/ValidatedMacOSNotarizationSettings.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/ValidatedMacOSNotarizationSettings.kt index 6cc35fb173..5bc1038b4a 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/ValidatedMacOSNotarizationSettings.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/validation/ValidatedMacOSNotarizationSettings.kt @@ -10,9 +10,13 @@ internal data class ValidatedMacOSNotarizationSettings( val password: String ) -internal fun MacOSNotarizationSettings.validate( +internal fun MacOSNotarizationSettings?.validate( bundleIDProvider: Provider ): ValidatedMacOSNotarizationSettings { + checkNotNull(this) { + ERR_NOTARIZATION_SETTINGS_ARE_NOT_PROVIDED + } + val bundleID = validateBundleID(bundleIDProvider) check(!appleID.orNull.isNullOrEmpty()) { ERR_APPLE_ID_IS_EMPTY @@ -28,6 +32,8 @@ internal fun MacOSNotarizationSettings.validate( } private const val ERR_PREFIX = "Notarization settings error:" +private const val ERR_NOTARIZATION_SETTINGS_ARE_NOT_PROVIDED = + "$ERR_PREFIX notarization settings are not provided" private val ERR_APPLE_ID_IS_EMPTY = """|$ERR_PREFIX appleID is null or empty. To specify: | * Use '${ComposeProperties.MAC_NOTARIZATION_APPLE_ID}' Gradle property; diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt index 55cc1438c7..9c3fe447c6 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt @@ -15,6 +15,7 @@ import org.gradle.work.InputChanges import org.jetbrains.compose.desktop.application.dsl.MacOSSigningSettings import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.internal.* +import org.jetbrains.compose.desktop.application.internal.validation.ValidatedMacOSSigningSettings import org.jetbrains.compose.desktop.application.internal.validation.validate import java.io.File import javax.inject.Inject @@ -151,26 +152,44 @@ abstract class AbstractJPackageTask @Inject constructor( @get:Optional internal val nonValidatedMacBundleID: Property = objects.nullableProperty() + @get:Optional @get:Nested - internal lateinit var nonValidatedMacSigningSettings: MacOSSigningSettings + internal var nonValidatedMacSigningSettings: MacOSSigningSettings? = null - private fun validateSigning() = - nonValidatedMacSigningSettings.validate(nonValidatedMacBundleID) + private inline fun withValidatedMacOSSigning(fn: (ValidatedMacOSSigningSettings) -> T): T? = + nonValidatedMacSigningSettings?.let { nonValidated -> + if (currentOS == OS.MacOS && nonValidated.sign.get()) { + fn(nonValidated.validate(nonValidatedMacBundleID)) + } else null + } @get:LocalState protected val signDir: Provider = project.layout.buildDirectory.dir("compose/tmp/sign") override fun makeArgs(tmpDir: File): MutableList = super.makeArgs(tmpDir).apply { - if (targetFormat == TargetFormat.AppImage) { + if (targetFormat == TargetFormat.AppImage || appImage.orNull == null) { + // Args, that can only be used, when creating an app image or an installer w/o --app-image parameter cliArg("--input", tmpDir) - check(runtimeImage.isPresent) { "runtimeImage must be set for ${TargetFormat.AppImage}" } - check(!appImage.isPresent) { "appImage must not be set for ${TargetFormat.AppImage}" } cliArg("--runtime-image", runtimeImage) cliArg("--main-jar", launcherMainJar.ioFile.name) cliArg("--main-class", launcherMainClass) - } else { - check(!runtimeImage.isPresent) { "runtimeImage must not be set for $targetFormat" } - check(appImage.isPresent) { "appImage must be set for $targetFormat" } + + when (currentOS) { + OS.Windows -> { + cliArg("--win-console", winConsole) + } + } + cliArg("--icon", iconFile) + launcherArgs.orNull?.forEach { + cliArg("--arguments", it) + } + launcherJvmArgs.orNull?.forEach { + cliArg("--java-options", it) + } + } + + if (targetFormat != TargetFormat.AppImage) { + // Args, that can only be used, when creating an installer cliArg("--app-image", appImage) cliArg("--install-dir", installationPath) cliArg("--license-file", licenseFile) @@ -201,38 +220,24 @@ abstract class AbstractJPackageTask @Inject constructor( cliArg("--dest", destinationDir) cliArg("--verbose", verbose) - cliArg("--icon", iconFile) - cliArg("--name", packageName) cliArg("--description", packageDescription) cliArg("--copyright", packageCopyright) cliArg("--app-version", packageVersion) cliArg("--vendor", packageVendor) - launcherArgs.orNull?.forEach { - cliArg("--arguments", it) - } - launcherJvmArgs.orNull?.forEach { - cliArg("--java-options", it) - } - when (currentOS) { OS.MacOS -> { cliArg("--mac-package-name", macPackageName) cliArg("--mac-package-identifier", nonValidatedMacBundleID) - if (nonValidatedMacSigningSettings.sign.get()) { - val signing = validateSigning() + withValidatedMacOSSigning { signing -> cliArg("--mac-sign", true) cliArg("--mac-signing-key-user-name", signing.identity) cliArg("--mac-signing-keychain", signing.keychain) cliArg("--mac-package-signing-prefix", signing.prefix) - } } - OS.Windows -> { - cliArg("--win-console", winConsole) - } } } @@ -241,7 +246,7 @@ abstract class AbstractJPackageTask @Inject constructor( // todo: parallel processing val fileProcessor = - if (currentOS == OS.MacOS && nonValidatedMacSigningSettings.sign.get()) { + withValidatedMacOSSigning { signing -> val tmpDirForSign = signDir.ioFile fileOperations.delete(tmpDirForSign) tmpDirForSign.mkdirs() @@ -249,9 +254,9 @@ abstract class AbstractJPackageTask @Inject constructor( MacJarSignFileCopyingProcessor( tempDir = tmpDirForSign, execOperations = execOperations, - signing = validateSigning() + signing = signing ) - } else SimpleFileCopyingProcessor + } ?: SimpleFileCopyingProcessor if (inputChanges.isIncremental) { logger.debug("Updating working dir incrementally: $workingDir") diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractNotarizationTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractNotarizationTask.kt index 13340d593f..b6c11222d8 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractNotarizationTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractNotarizationTask.kt @@ -24,7 +24,8 @@ abstract class AbstractNotarizationTask( internal val nonValidatedBundleID: Property = objects.nullableProperty() @get:Nested - internal lateinit var nonValidatedNotarizationSettings: MacOSNotarizationSettings + @get:Optional + internal var nonValidatedNotarizationSettings: MacOSNotarizationSettings? = null internal fun validateNotarization() = nonValidatedNotarizationSettings.validate(nonValidatedBundleID) diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/DesktopApplicationTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/DesktopApplicationTest.kt index 68a8160a89..69af794acd 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/DesktopApplicationTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/DesktopApplicationTest.kt @@ -57,7 +57,10 @@ class DesktopApplicationTest : GradlePluginTestBase() { OS.Windows -> "msi" OS.MacOS -> "dmg" } - file("build/compose/binaries/main/$ext/TestPackage-1.0.$ext") + val fileName = + if (currentOS == OS.Linux && ext == "deb") "testpackage_1.0-1_amd64" + else "TestPackage-1.0" + file("build/compose/binaries/main/$ext/$fileName.$ext") .checkExists() assertEquals(TaskOutcome.SUCCESS, result.task(":package${ext.capitalize()}")?.outcome) assertEquals(TaskOutcome.SUCCESS, result.task(":package")?.outcome) diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/fileUtils.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/fileUtils.kt index 315b5e7e07..cd15b7c262 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/fileUtils.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/fileUtils.kt @@ -9,5 +9,15 @@ fun File.modify(fn: (String) -> String) { } fun File.checkExists(): File = apply { - check(exists()) { "File does not exist: $absolutePath" } + check(exists()) { + buildString { + appendln("Requested file does not exist: $absolutePath") + parentFile?.listFiles()?.let { siblingFiles -> + appendln("Other files in the same directory: ${parentFile.absolutePath}") + siblingFiles.forEach { + appendln(" * ${it.name}") + } + } + } + } } \ No newline at end of file