Skip to content

Commit d6803da

Browse files
committed
Fix signing when the developer ID contains non-ASCII characters.
1 parent cf0ff4f commit d6803da

File tree

5 files changed

+73
-19
lines changed

5 files changed

+73
-19
lines changed

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

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,11 @@ internal class MacSignerImpl(
9393
}
9494

9595
private fun matchCertificates(certificates: String): String {
96-
val regex = Pattern.compile("\"alis\"<blob>=\"([^\"]+)\"")
96+
// When the developer id contains non-ascii characters, the output of `security find-certificate` is
97+
// slightly different. The `alis` line first has the hex-encoded developer id, then some spaces,
98+
// and then the developer id with non-ascii characters encoded as octal.
99+
// See https://bugs.openjdk.org/browse/JDK-8308042
100+
val regex = Pattern.compile("\"alis\"<blob>=(0x[0-9A-F]+)?\\s*\"([^\"]+)\"")
97101
val m = regex.matcher(certificates)
98102
if (!m.find()) {
99103
val keychainPath = settings.keychain?.absolutePath
@@ -102,14 +106,24 @@ internal class MacSignerImpl(
102106
" in keychain [${keychainPath.orEmpty()}]"
103107
)
104108
}
105-
106-
val result = m.group(1)
107-
if (m.find())
108-
error(
109-
"Multiple matching certificates are found for '${settings.fullDeveloperID}'. " +
110-
"Please specify keychain containing unique matching certificate."
111-
)
112-
return result
109+
val hexEncoded = m.group(1)
110+
if (hexEncoded.isNullOrBlank()) {
111+
// Regular case; developer id only has ascii characters
112+
val result = m.group(2)
113+
if (m.find())
114+
error(
115+
"Multiple matching certificates are found for '${settings.fullDeveloperID}'. " +
116+
"Please specify keychain containing unique matching certificate."
117+
)
118+
return result
119+
} else {
120+
return hexEncoded
121+
.substring(2)
122+
.chunked(2)
123+
.map { it.toInt(16).toByte() }
124+
.toByteArray()
125+
.toString(Charsets.UTF_8)
126+
}
113127
}
114128
}
115129

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

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,12 @@ class DesktopApplicationTest : GradlePluginTestBase() {
375375
}
376376
}
377377

378-
@Test
379-
@Disabled
380-
// the test does not work on CI and locally unless test keychain is opened manually
381-
fun testMacSign() {
378+
private fun testMacSign(
379+
identity: String,
380+
keychainFilename: String,
381+
keychainPassword: String,
382+
javaVersion: String = "17"
383+
) {
382384
Assumptions.assumeTrue(currentOS == OS.MacOS)
383385

384386
fun security(vararg args: Any): ProcessRunResult {
@@ -403,13 +405,20 @@ class DesktopApplicationTest : GradlePluginTestBase() {
403405
}
404406
}
405407

406-
with(testProject("application/macSign")) {
407-
val keychain = file("compose.test.keychain")
408-
val password = "compose.test"
408+
val project = testProject("application/macSign").apply {
409+
modifyText("build.gradle") {
410+
it
411+
.replace("%IDENTITY%", identity)
412+
.replace("%KEYCHAIN%", keychainFilename)
413+
.replace("%JAVA_VERSION%", javaVersion)
414+
}
415+
}
416+
with(project) {
417+
val keychain = file(keychainFilename)
409418

410419
withNewDefaultKeychain(keychain) {
411420
security("default-keychain", "-s", keychain)
412-
security("unlock-keychain", "-p", password, keychain)
421+
security("unlock-keychain", "-p", keychainPassword, keychain)
413422

414423
gradle(":createDistributable").checks {
415424
check.taskSuccessful(":createDistributable")
@@ -431,6 +440,29 @@ class DesktopApplicationTest : GradlePluginTestBase() {
431440
}
432441
}
433442

443+
@Test
444+
@Disabled
445+
// the test does not work on CI and locally unless test keychain is opened manually
446+
fun testMacSign() {
447+
testMacSign(
448+
identity = "Compose Test",
449+
keychainFilename = "compose.test.keychain",
450+
keychainPassword = "compose.test"
451+
)
452+
}
453+
454+
@Test
455+
@Disabled
456+
// the test does not work on CI and locally unless test keychain is opened manually
457+
fun testMacSignWithNonAsciiDeveloperId() {
458+
testMacSign(
459+
identity = "Cömpose Test",
460+
keychainFilename = "compose.test-non-ascii.keychain",
461+
keychainPassword = "compose.test",
462+
javaVersion = "21", // https://bugs.openjdk.org/browse/JDK-8308042 fixed in JDK 21
463+
)
464+
}
465+
434466
@Test
435467
fun testOptionsWithSpaces() {
436468
with(testProject("application/optionsWithSpaces")) {

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,18 @@ compose.desktop {
1313
application {
1414
mainClass = "MainKt"
1515
nativeDistributions {
16+
javaHome = javaToolchains.launcherFor {
17+
languageVersion.set(JavaLanguageVersion.of(%JAVA_VERSION%))
18+
}.get().metadata.installationPath.asFile.absolutePath
19+
1620
packageName = "TestPackage"
1721
macOS {
1822
bundleID = "signing.test.package"
1923

2024
signing {
2125
sign.set(true)
22-
identity.set("Compose Test")
23-
keychain.set("compose.test.keychain")
26+
identity.set("%IDENTITY%")
27+
keychain.set("%KEYCHAIN%")
2428
}
2529
}
2630
}
27.2 KB
Binary file not shown.

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pluginManagement {
33
id 'org.jetbrains.kotlin.jvm' version 'KOTLIN_VERSION_PLACEHOLDER'
44
id 'org.jetbrains.kotlin.plugin.compose' version 'KOTLIN_VERSION_PLACEHOLDER'
55
id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER'
6+
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
67
}
78
repositories {
89
mavenLocal()
@@ -14,6 +15,9 @@ pluginManagement {
1415
}
1516
}
1617
}
18+
plugins {
19+
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
20+
}
1721
dependencyResolutionManagement {
1822
repositories {
1923
mavenCentral()

0 commit comments

Comments
 (0)