Skip to content

Commit 2d7a94a

Browse files
Update signing config, fix configuration-cache compatibility (#3058)
* Do not generate (MD5) checksum for signature file * Do not configure signatory with empty key info
1 parent de69c5b commit 2d7a94a

File tree

6 files changed

+102
-101
lines changed

6 files changed

+102
-101
lines changed

build-logic/src/main/kotlin/PublicationPlugin.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,17 @@ abstract class PublicationPlugin : Plugin<Project> {
134134
// See https://docs.gradle.org/current/userguide/signing_plugin.html#sec:using_gpg_agent how to configure it
135135
// useGpgCmd()
136136

137-
val signingKeyId = System.getenv("ORG_GRADLE_PROJECT_signingKeyId")
138-
val signingKey = System.getenv("ORG_GRADLE_PROJECT_signingKey")
139-
val signingPassword = System.getenv("ORG_GRADLE_PROJECT_signingKeyPassword")
140-
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
137+
val signingKeyId = System.getenv("ORG_GRADLE_PROJECT_signingKeyId")?.takeIf { it.isNotEmpty() }
138+
val signingKey = System.getenv("ORG_GRADLE_PROJECT_signingKey")?.takeIf { it.isNotEmpty() }
139+
val signingPassword = System.getenv("ORG_GRADLE_PROJECT_signingKeyPassword")?.takeIf { it.isNotEmpty() }
140+
if (signingKeyId != null && signingKey != null && signingPassword != null) {
141+
// Avoid setting empty strings as signing keys. This avoids breaking the build when PR is opened from a fork.
142+
// Also, due to https://github.com/gradle/gradle/issues/18477 signing tasks try to prematurely access the signatory.
143+
// This also improves error messages if something's misconfigured
144+
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
145+
} else {
146+
logger.info("No signing info")
147+
}
141148

142149
// This property allows OS package maintainers to disable signing
143150
val enableSigning = providers.gradleProperty("ktlint.publication.signing.enable").orNull != "false"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import org.gradle.api.DefaultTask
2+
import org.gradle.api.model.ObjectFactory
3+
import org.gradle.api.tasks.InputFile
4+
import org.gradle.api.tasks.Internal
5+
import org.gradle.api.tasks.OutputFile
6+
import org.gradle.api.tasks.PathSensitive
7+
import org.gradle.api.tasks.PathSensitivity
8+
import org.gradle.api.tasks.TaskAction
9+
import javax.inject.Inject
10+
11+
// Implements https://github.com/brianm/really-executable-jars-maven-plugin maven plugin behaviour.
12+
// To check details how it works, see https://skife.org/java/unix/2011/06/20/really_executable_jars.html.
13+
abstract class ShadowJarExecutableTask
14+
@Inject
15+
constructor(
16+
objects: ObjectFactory,
17+
) : DefaultTask() {
18+
@InputFile
19+
val allJarFile = objects.fileProperty()
20+
21+
@PathSensitive(PathSensitivity.RELATIVE)
22+
@InputFile
23+
val windowsBatchScriptSource = objects.fileProperty()
24+
25+
@Internal
26+
val outputDirectory = objects.directoryProperty()
27+
28+
@OutputFile
29+
val selfExecutable = outputDirectory.map { it.asFile.resolve("ktlint") }
30+
31+
@OutputFile
32+
val windowsBatchScript = outputDirectory.map { it.asFile.resolve("ktlint.bat") }
33+
34+
init {
35+
description = "Creates self-executable file, that runs generated shadow jar"
36+
group = "Distribution"
37+
}
38+
39+
@TaskAction
40+
fun action() {
41+
logger.lifecycle("ktlint-cli: Base jar to build self-executable file: ${allJarFile.get()}")
42+
43+
selfExecutable.get().apply {
44+
logger.lifecycle("Creating the self-executable file: $this")
45+
46+
// writeText effective replaces the entire content if the file already exists. If appendText is used, the file keeps on growing
47+
// with each build if the clean target is not used.
48+
writeText(
49+
"""
50+
#!/bin/sh
51+
52+
# From this SO answer: https://stackoverflow.com/a/56243046
53+
54+
# First we get the major Java version as an integer, e.g. 8, 11, 16. It has special handling for the leading 1 of older java
55+
# versions, e.g. 1.8 = Java 8
56+
JV=$(java -version 2>&1 | sed -E -n 's/.* version "([^.-]*).*".*/\1/p')
57+
58+
# Suppress warning "sun.misc.Unsafe::objectFieldOffset" on Java24+ (https://github.com/pinterest/ktlint/issues/2973)
59+
X=$( [ "${"$"}JV" -ge "24" ] && echo "${"$"}X --sun-misc-unsafe-memory-access=allow" || echo "")
60+
61+
# Suppress warning "A restricted method in java.lang.System has been called" on Java 24
62+
# Error is only printed when running command "ktlint --help"
63+
X=$( [ "${"$"}JV" -ge "24" ] && echo "${"$"}X --enable-native-access=ALL-UNNAMED" || echo "")
64+
65+
exec java ${"$"}X -Xmx512m -jar "$0" "$@"
66+
67+
""".trimIndent(),
68+
)
69+
// Add the jar
70+
appendBytes(allJarFile.get().asFile.readBytes())
71+
72+
setExecutable(true, false)
73+
}
74+
logger.lifecycle("Creating the batch file for Windows OS: ${windowsBatchScript.get()}")
75+
windowsBatchScript.get().writeText(windowsBatchScriptSource.asFile.get().readText())
76+
logger.lifecycle("Finished creating output files ktlint-cli")
77+
}
78+
}

build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import java.net.URI
22

33
plugins {
44
alias(libs.plugins.kotlin.jvm) apply false
5-
alias(libs.plugins.checksum) apply false
65
alias(libs.plugins.shadow) apply false
76
alias(
87
libs

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ POM_DEVELOPER_NAME=Pinterest, Inc.
2020
org.gradle.jvmargs=-Xmx4g
2121
org.gradle.parallel=true
2222
org.gradle.caching=true
23-
org.gradle.configuration-cache=false
23+
org.gradle.configuration-cache=true
2424
org.gradle.configuration-cache.parallel=true
2525

2626
# Use V2 of the Dokka library and silence its warnings

gradle/libs.versions.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ kotlinDev = "2.2.0"
99
[plugins]
1010
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
1111
kotlin-sam-with-receiver = { id = "org.jetbrains.kotlin.plugin.sam.with.receiver", version.ref = "kotlin" }
12-
checksum = "org.gradle.crypto.checksum:1.4.0"
1312
shadow = "com.gradleup.shadow:8.3.8"
1413
kotlinx-binary-compatibiltiy-validator = "org.jetbrains.kotlinx.binary-compatibility-validator:0.18.1"
1514

ktlint-cli/build.gradle.kts

Lines changed: 12 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import org.gradle.crypto.checksum.Checksum
2-
31
plugins {
42
id("ktlint-publication-library")
53
alias(libs.plugins.shadow)
6-
alias(libs.plugins.checksum)
74
signing
85
}
96

@@ -43,116 +40,37 @@ dependencies {
4340
testRuntimeOnly(libs.junit5.platform.launcher)
4441
}
4542

46-
// Implements https://github.com/brianm/really-executable-jars-maven-plugin maven plugin behaviour.
47-
// To check details how it works, see https://skife.org/java/unix/2011/06/20/really_executable_jars.html.
48-
val shadowJarExecutable by tasks.registering(DefaultTask::class) {
49-
description = "Creates self-executable file, that runs generated shadow jar"
50-
group = "Distribution"
43+
// Output is the self-executable file, the signature file and a batch file for Windows OS.
44+
// Folder content is published as GitHub release artifacts
45+
val ktlintOutputRoot = layout.buildDirectory.dir("run")
5146

47+
val shadowJarExecutable by tasks.registering(ShadowJarExecutableTask::class) {
5248
dependsOn(tasks.shadowJar)
5349

5450
// Find the "ktlint-cli-<version>-all.jar" file
5551
val ktlintCliAllJarFile =
5652
tasks.shadowJar
5753
.get()
58-
.outputs.files.singleFile
59-
logger.lifecycle("ktlint-cli: Base jar to build self-executable file: ${ktlintCliAllJarFile.absolutePath}")
60-
inputs.files(ktlintCliAllJarFile)
61-
62-
val windowsBatchFileInputPath = layout.projectDirectory.file("src/main/scripts/ktlint.bat").asFile
63-
inputs.files(windowsBatchFileInputPath)
64-
// Output is the self-executable file, the signature file and a batch file for Windows OS
65-
val outputDirectoryPath =
66-
layout.buildDirectory
67-
.dir("run")
54+
.archiveFile
6855
.get()
69-
.asFile
70-
val selfExecutableKtlintOutputPath = outputDirectoryPath.resolve("ktlint")
71-
val selfExecutableKtlintSignatureOutputPath = outputDirectoryPath.resolve("ktlint.asc")
72-
val windowsBatchFileOutputPath = outputDirectoryPath.resolve("ktlint.bat")
73-
outputs.files(selfExecutableKtlintOutputPath)
74-
outputs.files(selfExecutableKtlintSignatureOutputPath)
75-
outputs.files(windowsBatchFileOutputPath)
76-
77-
doLast {
78-
selfExecutableKtlintOutputPath.apply {
79-
logger.lifecycle("Creating the self-executable file: $selfExecutableKtlintOutputPath")
80-
81-
// writeText effective replaces the entire content if the file already exists. If appendText is used, the file keeps on growing
82-
// with each build if the clean target is not used.
83-
writeText(
84-
"""
85-
#!/bin/sh
86-
87-
# From this SO answer: https://stackoverflow.com/a/56243046
88-
89-
# First we get the major Java version as an integer, e.g. 8, 11, 16. It has special handling for the leading 1 of older java
90-
# versions, e.g. 1.8 = Java 8
91-
JV=$(java -version 2>&1 | sed -E -n 's/.* version "([^.-]*).*".*/\1/p')
92-
93-
# Suppress warning "sun.misc.Unsafe::objectFieldOffset" on Java24+ (https://github.com/pinterest/ktlint/issues/2973)
94-
X=$( [ "${"$"}JV" -ge "24" ] && echo "${"$"}X --sun-misc-unsafe-memory-access=allow" || echo "")
56+
allJarFile.set(ktlintCliAllJarFile)
57+
windowsBatchScriptSource.set(layout.projectDirectory.file("src/main/scripts/ktlint.bat"))
58+
outputDirectory.set(ktlintOutputRoot)
9559

96-
# Suppress warning "A restricted method in java.lang.System has been called" on Java 24
97-
# Error is only printed when running command "ktlint --help"
98-
X=$( [ "${"$"}JV" -ge "24" ] && echo "${"$"}X --enable-native-access=ALL-UNNAMED" || echo "")
99-
100-
exec java ${"$"}X -Xmx512m -jar "$0" "$@"
101-
102-
""".trimIndent(),
103-
)
104-
// Add the jar
105-
appendBytes(ktlintCliAllJarFile.readBytes())
106-
107-
setExecutable(true, false)
108-
109-
if (signing.isRequired) {
110-
logger.lifecycle("Creating the signature file: $selfExecutableKtlintSignatureOutputPath")
111-
signing.sign(this)
112-
}
113-
}
114-
logger.lifecycle("Creating the batch file for Windows OS: $windowsBatchFileOutputPath")
115-
windowsBatchFileOutputPath.writeText(windowsBatchFileInputPath.readText())
116-
logger.lifecycle("Finished creating output files ktlint-cli")
117-
}
60+
finalizedBy("signShadowJarExecutable")
11861
}
11962

120-
tasks.register<Checksum>("shadowJarExecutableChecksum") {
121-
description = "Generates MD5 checksum for ktlint executable"
122-
group = "Distribution"
123-
63+
val signShadowJarExecutable by tasks.registering(Sign::class) {
12464
dependsOn(shadowJarExecutable)
12565

126-
inputFiles.setFrom(shadowJarExecutable.map { it.outputs.files })
127-
// put the checksums in the same folder with the executable itself
128-
outputDirectory.fileProvider(
129-
shadowJarExecutable
130-
.map {
131-
it
132-
.outputs
133-
.files
134-
.files
135-
.first()
136-
.parentFile
137-
},
138-
)
139-
checksumAlgorithm = Checksum.Algorithm.MD5
66+
sign(shadowJarExecutable.flatMap { it.selfExecutable }.get())
14067
}
14168

14269
tasks.withType<Test>().configureEach {
14370
dependsOn(shadowJarExecutable)
14471

14572
// TODO: Use providers directly after https://github.com/gradle/gradle/issues/12247 is fixed.
146-
val executableFilePath =
147-
providers
148-
.provider {
149-
shadowJarExecutable
150-
.get()
151-
.outputs
152-
.files
153-
.first { it.name == "ktlint" }
154-
.absolutePath
155-
}.get()
73+
val executableFilePath = shadowJarExecutable.flatMap { it.selfExecutable }.map { it.absolutePath }.get()
15674
val ktlintVersion = providers.provider { version }.get()
15775
doFirst {
15876
systemProperty(

0 commit comments

Comments
 (0)