diff --git a/buildSrc/src/main/kotlin/PklPublishing.kt b/buildSrc/src/main/kotlin/PklPublishing.kt new file mode 100644 index 00000000..60fdf79d --- /dev/null +++ b/buildSrc/src/main/kotlin/PklPublishing.kt @@ -0,0 +1,147 @@ +/* + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.nio.charset.StandardCharsets +import java.util.Base64 +import org.gradle.api.Project +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven +import org.gradle.api.publish.maven.tasks.GenerateMavenPom +import org.gradle.kotlin.dsl.* +import org.gradle.plugins.signing.SigningExtension + +/** Configures common POM metadata (licenses, developers, SCM, etc.) for all Pkl publications. */ +fun Project.configurePklPomMetadata() { + extensions.configure { + publications.withType().configureEach { + pom { + name.set(artifactId) + licenses { + license { + name.set("The Apache Software License, Version 2.0") + url.set("https://github.com/apple/pkl/blob/main/LICENSE.txt") + } + } + developers { + developer { + id.set("pkl-authors") + name.set("The Pkl Authors") + email.set("pkl-oss@group.apple.com") + } + } + scm { + connection.set("scm:git:git://github.com/apple/pkl.git") + developerConnection.set("scm:git:ssh://github.com/apple/pkl.git") + val buildInfo = extensions.getByType() + url.set("https://github.com/apple/pkl/tree/${buildInfo.commitish}") + } + issueManagement { + system.set("GitHub Issues") + url.set("https://github.com/apple/pkl/issues") + } + ciManagement { + system.set("GitHub Actions") + url.set("https://github.com/apple/pkl/actions") + } + } + } + } +} + +/** Configures POM validation task to check for unresolved versions and snapshots in releases. */ +fun Project.configurePomValidation() { + val validatePom by + tasks.registering { + if (tasks.findByName("generatePomFileForLibraryPublication") == null) { + return@registering + } + val generatePomFileForLibraryPublication by tasks.existing(GenerateMavenPom::class) + val outputFile = + layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check + + dependsOn(generatePomFileForLibraryPublication) + inputs.file(generatePomFileForLibraryPublication.get().destination) + outputs.file(outputFile) + + doLast { + outputFile.get().asFile.delete() + + val pomFile = generatePomFileForLibraryPublication.get().destination + assert(pomFile.exists()) + + val text = pomFile.readText() + + run { + val unresolvedVersion = Regex(".*[+,()\\[\\]].*") + val matches = unresolvedVersion.findAll(text).toList() + if (matches.isNotEmpty()) { + throw org.gradle.api.GradleException( + """ + Found unresolved version selector(s) in generated POM: + ${matches.joinToString("\n") { it.groupValues[0] }} + """ + .trimIndent() + ) + } + } + + val buildInfo = project.extensions.getByType() + if (buildInfo.isReleaseBuild) { + val snapshotVersion = Regex(".*-SNAPSHOT") + val matches = snapshotVersion.findAll(text).toList() + if (matches.isNotEmpty()) { + throw org.gradle.api.GradleException( + """ + Found snapshot version(s) in generated POM of Pkl release version: + ${matches.joinToString("\n") { it.groupValues[0] }} + """ + .trimIndent() + ) + } + } + + outputFile.get().asFile.writeText("OK") + } + } + + tasks.named("publish") { dependsOn(validatePom) } +} + +/** Configures signing for Pkl publications. */ +fun Project.configurePklSigning() { + // Workaround for maven publish plugin not setting up dependencies correctly. + // Taken from https://github.com/gradle/gradle/issues/26091#issuecomment-1798137734 + val dependsOnTasks = mutableListOf() + + tasks.withType().configureEach { + dependsOnTasks.add(name.replace("publish", "sign").replaceAfter("Publication", "")) + dependsOn(dependsOnTasks) + } + + extensions.configure { + // provided as env vars `ORG_GRADLE_PROJECT_signingKey` and + // `ORG_GRADLE_PROJECT_signingPassword` in CI. + val signingKey = + (findProperty("signingKey") as String?)?.let { + Base64.getDecoder().decode(it).toString(StandardCharsets.US_ASCII) + } + val signingPassword = findProperty("signingPassword") as String? + if (signingKey != null && signingPassword != null) { + useInMemoryPgpKeys(signingKey, signingPassword) + } + extensions.getByType().publications.findByName("library")?.let { sign(it) } + } +} diff --git a/buildSrc/src/main/kotlin/pklPublishLibrary.gradle.kts b/buildSrc/src/main/kotlin/pklPublishLibrary.gradle.kts index 2976fcfd..3b81d000 100644 --- a/buildSrc/src/main/kotlin/pklPublishLibrary.gradle.kts +++ b/buildSrc/src/main/kotlin/pklPublishLibrary.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,10 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import java.nio.charset.StandardCharsets -import java.util.Base64 -import org.gradle.api.publish.maven.tasks.GenerateMavenPom - plugins { `maven-publish` signing @@ -27,119 +23,14 @@ publishing { components.findByName("java")?.let { javaComponent -> create("library") { from(javaComponent) } } - withType().configureEach { - pom { - name.set(artifactId) - licenses { - license { - name.set("The Apache Software License, Version 2.0") - url.set("https://github.com/apple/pkl/blob/main/LICENSE.txt") - } - } - developers { - developer { - id.set("pkl-authors") - name.set("The Pkl Authors") - email.set("pkl-oss@group.apple.com") - } - } - scm { - connection.set("scm:git:git://github.com/apple/pkl.git") - developerConnection.set("scm:git:ssh://github.com/apple/pkl.git") - val buildInfo = project.extensions.getByType() - url.set("https://github.com/apple/pkl/tree/${buildInfo.commitish}") - } - issueManagement { - system.set("GitHub Issues") - url.set("https://github.com/apple/pkl/issues") - } - ciManagement { - system.set("GitHub Actions") - url.set("https://github.com/apple/pkl/actions") - } - } - } } } -val validatePom by - tasks.registering { - if (tasks.findByName("generatePomFileForLibraryPublication") == null) { - return@registering - } - val generatePomFileForLibraryPublication by tasks.existing(GenerateMavenPom::class) - val outputFile = - layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check +configurePklPomMetadata() - dependsOn(generatePomFileForLibraryPublication) - inputs.file(generatePomFileForLibraryPublication.get().destination) - outputs.file(outputFile) +configurePomValidation() - doLast { - outputFile.get().asFile.delete() - - val pomFile = generatePomFileForLibraryPublication.get().destination - assert(pomFile.exists()) - - val text = pomFile.readText() - - run { - val unresolvedVersion = Regex(".*[+,()\\[\\]].*") - val matches = unresolvedVersion.findAll(text).toList() - if (matches.isNotEmpty()) { - throw GradleException( - """ - Found unresolved version selector(s) in generated POM: - ${matches.joinToString("\n") { it.groupValues[0] }} - """ - .trimIndent() - ) - } - } - - val buildInfo = project.extensions.getByType() - if (buildInfo.isReleaseBuild) { - val snapshotVersion = Regex(".*-SNAPSHOT") - val matches = snapshotVersion.findAll(text).toList() - if (matches.isNotEmpty()) { - throw GradleException( - """ - Found snapshot version(s) in generated POM of Pkl release version: - ${matches.joinToString("\n") { it.groupValues[0] }} - """ - .trimIndent() - ) - } - } - - outputFile.get().asFile.writeText("OK") - } - } - -tasks.publish { dependsOn(validatePom) } - -// Workaround for maven publish plugin not setting up dependencies correctly. -// Taken from https://github.com/gradle/gradle/issues/26091#issuecomment-1798137734 -val dependsOnTasks = mutableListOf() - -tasks.withType().configureEach { - dependsOnTasks.add(name.replace("publish", "sign").replaceAfter("Publication", "")) - dependsOn(dependsOnTasks) -} - -signing { - // provided as env vars `ORG_GRADLE_PROJECT_signingKey` and `ORG_GRADLE_PROJECT_signingPassword` - // in CI. - val signingKey = - (findProperty("signingKey") as String?)?.let { - Base64.getDecoder().decode(it).toString(StandardCharsets.US_ASCII) - } - val signingPassword = findProperty("signingPassword") as String? - if (signingKey != null && signingPassword != null) { - useInMemoryPgpKeys(signingKey, signingPassword) - } - publishing.publications.findByName("library")?.let { sign(it) } -} +configurePklSigning() artifacts { project.tasks.findByName("javadocJar")?.let { archives(it) } diff --git a/pkl-bom/pkl-bom.gradle.kts b/pkl-bom/pkl-bom.gradle.kts new file mode 100644 index 00000000..09b54699 --- /dev/null +++ b/pkl-bom/pkl-bom.gradle.kts @@ -0,0 +1,60 @@ +/* + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +plugins { + pklAllProjects + `java-platform` + `maven-publish` + signing +} + +description = "Pkl BOM that includes all modules" + +dependencies { + constraints { + api(projects.pklCli) + api(projects.pklCodegenJava) + api(projects.pklCodegenKotlin) + // Use explicit coordinates for pkl-config-java to avoid ambiguity with fatJar publication + api("${project.group}:pkl-config-java:${project.version}") + api("${project.group}:pkl-config-java-all:${project.version}") + api(projects.pklConfigKotlin) + api(projects.pklCore) + api(projects.pklDoc) + api(projects.pklExecutor) + api(projects.pklFormatter) + api(projects.pklGradle) + api(projects.pklParser) + api(projects.pklTools) + } +} + +publishing { + publications { + create("library") { + from(components["javaPlatform"]) + pom { + url.set("https://github.com/apple/pkl/tree/main/pkl-bom") + description.set("Bill of Materials for managing Pkl dependency versions") + } + } + } +} + +configurePklPomMetadata() + +configurePomValidation() + +configurePklSigning() diff --git a/settings.gradle.kts b/settings.gradle.kts index a60753bc..22332f07 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,8 @@ include("bench") include("docs") +include("pkl-bom") + include("pkl-cli") include("pkl-codegen-java")