Browse Source

Fix signing when the developer ID contains non-ASCII characters. (#5358)

pull/5246/merge
Alexander Maryanovsky 5 months ago committed by GitHub
parent
commit
406eef89d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 32
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/MacSigner.kt
  2. 55
      gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/DesktopApplicationTest.kt
  3. 8
      gradle-plugins/compose/src/test/test-projects/application/macSign/build.gradle
  4. BIN
      gradle-plugins/compose/src/test/test-projects/application/macSign/compose.test-non-ascii.keychain
  5. 4
      gradle-plugins/compose/src/test/test-projects/application/macSign/settings.gradle

32
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/MacSigner.kt

@ -93,7 +93,11 @@ internal class MacSignerImpl( @@ -93,7 +93,11 @@ internal class MacSignerImpl(
}
private fun matchCertificates(certificates: String): String {
val regex = Pattern.compile("\"alis\"<blob>=\"([^\"]+)\"")
// When the developer id contains non-ascii characters, the output of `security find-certificate` is
// slightly different. The `alis` line first has the hex-encoded developer id, then some spaces,
// and then the developer id with non-ascii characters encoded as octal.
// See https://bugs.openjdk.org/browse/JDK-8308042
val regex = Pattern.compile("\"alis\"<blob>=(0x[0-9A-F]+)?\\s*\"([^\"]+)\"")
val m = regex.matcher(certificates)
if (!m.find()) {
val keychainPath = settings.keychain?.absolutePath
@ -102,14 +106,24 @@ internal class MacSignerImpl( @@ -102,14 +106,24 @@ internal class MacSignerImpl(
" in keychain [${keychainPath.orEmpty()}]"
)
}
val result = m.group(1)
if (m.find())
error(
"Multiple matching certificates are found for '${settings.fullDeveloperID}'. " +
"Please specify keychain containing unique matching certificate."
)
return result
val hexEncoded = m.group(1)
if (hexEncoded.isNullOrBlank()) {
// Regular case; developer id only has ascii characters
val result = m.group(2)
if (m.find())
error(
"Multiple matching certificates are found for '${settings.fullDeveloperID}'. " +
"Please specify keychain containing unique matching certificate."
)
return result
} else {
return hexEncoded
.substring(2)
.chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
.toString(Charsets.UTF_8)
}
}
}

55
gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/DesktopApplicationTest.kt

@ -366,19 +366,34 @@ class DesktopApplicationTest : GradlePluginTestBase() { @@ -366,19 +366,34 @@ class DesktopApplicationTest : GradlePluginTestBase() {
}
}
private fun macSignProject(
identity: String,
keychainFilename: String,
javaVersion: String = "17"
) = testProject("application/macSign").apply {
modifyText("build.gradle") {
it
.replace("%IDENTITY%", identity)
.replace("%KEYCHAIN%", keychainFilename)
.replace("%JAVA_VERSION%", javaVersion)
}
}
@Test
fun testMacSignConfiguration() {
Assumptions.assumeTrue(currentOS == OS.MacOS)
with(testProject("application/macSign")) {
with(macSignProject(identity = "Compose Test", keychainFilename = "compose.test.keychain")) {
gradle("--dry-run", ":createDistributable")
}
}
@Test
@Disabled
// the test does not work on CI and locally unless test keychain is opened manually
fun testMacSign() {
private fun testMacSign(
identity: String,
keychainFilename: String,
keychainPassword: String,
javaVersion: String = "17"
) {
Assumptions.assumeTrue(currentOS == OS.MacOS)
fun security(vararg args: Any): ProcessRunResult {
@ -403,13 +418,12 @@ class DesktopApplicationTest : GradlePluginTestBase() { @@ -403,13 +418,12 @@ class DesktopApplicationTest : GradlePluginTestBase() {
}
}
with(testProject("application/macSign")) {
val keychain = file("compose.test.keychain")
val password = "compose.test"
with(macSignProject(identity = identity, keychainFilename = keychainFilename, javaVersion = javaVersion)) {
val keychain = file(keychainFilename)
withNewDefaultKeychain(keychain) {
security("default-keychain", "-s", keychain)
security("unlock-keychain", "-p", password, keychain)
security("unlock-keychain", "-p", keychainPassword, keychain)
gradle(":createDistributable").checks {
check.taskSuccessful(":createDistributable")
@ -431,6 +445,29 @@ class DesktopApplicationTest : GradlePluginTestBase() { @@ -431,6 +445,29 @@ class DesktopApplicationTest : GradlePluginTestBase() {
}
}
@Test
@Disabled
// the test does not work on CI and locally unless test keychain is opened manually
fun testMacSign() {
testMacSign(
identity = "Compose Test",
keychainFilename = "compose.test.keychain",
keychainPassword = "compose.test"
)
}
@Test
@Disabled
// the test does not work on CI and locally unless test keychain is opened manually
fun testMacSignWithNonAsciiDeveloperId() {
testMacSign(
identity = "Cömpose Test",
keychainFilename = "compose.test-non-ascii.keychain",
keychainPassword = "compose.test",
javaVersion = "21", // https://bugs.openjdk.org/browse/JDK-8308042 fixed in JDK 21
)
}
@Test
fun testOptionsWithSpaces() {
with(testProject("application/optionsWithSpaces")) {

8
gradle-plugins/compose/src/test/test-projects/application/macSign/build.gradle

@ -13,14 +13,18 @@ compose.desktop { @@ -13,14 +13,18 @@ compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
javaHome = javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(%JAVA_VERSION%))
}.get().metadata.installationPath.asFile.absolutePath
packageName = "TestPackage"
macOS {
bundleID = "signing.test.package"
signing {
sign.set(true)
identity.set("Compose Test")
keychain.set("compose.test.keychain")
identity.set("%IDENTITY%")
keychain.set("%KEYCHAIN%")
}
}
}

BIN
gradle-plugins/compose/src/test/test-projects/application/macSign/compose.test-non-ascii.keychain

Binary file not shown.

4
gradle-plugins/compose/src/test/test-projects/application/macSign/settings.gradle

@ -3,6 +3,7 @@ pluginManagement { @@ -3,6 +3,7 @@ pluginManagement {
id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER'
id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER'
id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER'
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}
repositories {
mavenLocal()
@ -14,6 +15,9 @@ pluginManagement { @@ -14,6 +15,9 @@ pluginManagement {
}
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}
dependencyResolutionManagement {
repositories {
mavenCentral()

Loading…
Cancel
Save