diff --git a/.github/scripts/configure_publishing_secrets.py b/.github/scripts/configure_publishing_secrets.py new file mode 100644 index 0000000000..9dd1ef9f98 --- /dev/null +++ b/.github/scripts/configure_publishing_secrets.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +import base64 +import os +import re +import uuid + + +def decode_secret(env_var_name: str) -> str: + raw = os.environ.get(env_var_name, "") + if not raw: + return "" + # MIME Base64: ignore non-base64 chars (newlines, carriage returns, spaces, etc.) + cleaned = re.sub(r"[^A-Za-z0-9+/=]", "", raw) + if not cleaned: + return "" + return base64.b64decode(cleaned).decode("utf-8").strip() + + +def main(): + github_env = os.environ.get("GITHUB_ENV") + if not github_env: + return + + env_updates = {} + + # 1. Maven Central Password + maven_central_password = decode_secret("NEXUS_PASS64") + if maven_central_password: + env_updates["ORG_GRADLE_PROJECT_mavenCentralPassword"] = maven_central_password + + # 2. GPG Signing Key + gpg_key = decode_secret("GPG_KEY64") + if gpg_key: + env_updates["ORG_GRADLE_PROJECT_signingInMemoryKey"] = gpg_key + env_updates["ORG_GRADLE_PROJECT_signingInMemoryKeyId"] = "0x4272C851" + + # 3. GPG Passphrase + gpg_passphrase = os.environ.get("GPG_PASSPHRASE", "") + if gpg_passphrase: + env_updates["ORG_GRADLE_PROJECT_signingInMemoryKeyPassword"] = gpg_passphrase + + with open(github_env, "a", encoding="utf-8") as f: + for key, value in env_updates.items(): + if "\n" in value or "\r" in value: + delimiter = f"EOF_{uuid.uuid4().hex}" + f.write(f"{key}<<{delimiter}\n{value}\n{delimiter}\n") + else: + f.write(f"{key}={value}\n") + + if "ORG_GRADLE_PROJECT_mavenCentralPassword" in env_updates: + print("Configured ORG_GRADLE_PROJECT_mavenCentralPassword=***") + if "ORG_GRADLE_PROJECT_signingInMemoryKey" in env_updates: + print("Configured ORG_GRADLE_PROJECT_signingInMemoryKey=***") + if "ORG_GRADLE_PROJECT_signingInMemoryKeyPassword" in env_updates: + print("Configured ORG_GRADLE_PROJECT_signingInMemoryKeyPassword=***") + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d30f3046c..a1aa253424 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -189,11 +189,6 @@ jobs: needs: final-status if: github.event.repository.fork == false && github.ref == 'refs/heads/main' runs-on: ubuntu-latest - env: - ORG_GRADLE_PROJECT_nexus_user: ${{ secrets.NEXUS_USER }} - ORG_GRADLE_PROJECT_nexus_pass64: ${{ secrets.NEXUS_PASS64 }} - ORG_GRADLE_PROJECT_gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }} - ORG_GRADLE_PROJECT_gpg_key64: ${{ secrets.GPG_KEY64 }} steps: - uses: actions/checkout@v7 with: @@ -205,4 +200,12 @@ jobs: - uses: gradle/actions/setup-gradle@v6 with: cache-read-only: true - - run: ./gradlew publishToMavenCentral --no-configuration-cache + - name: Configure publishing secrets + env: + NEXUS_PASS64: ${{ secrets.NEXUS_PASS64 }} + GPG_KEY64: ${{ secrets.GPG_KEY64 }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + run: python3 .github/scripts/configure_publishing_secrets.py + - run: ./gradlew publishToMavenCentral + env: + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.NEXUS_USER }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 81df2c0163..0391573a0a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,14 +32,17 @@ jobs: contents: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ORG_GRADLE_PROJECT_nexus_user: ${{ secrets.NEXUS_USER }} - ORG_GRADLE_PROJECT_nexus_pass64: ${{ secrets.NEXUS_PASS64 }} - ORG_GRADLE_PROJECT_gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }} - ORG_GRADLE_PROJECT_gpg_key64: ${{ secrets.GPG_KEY64 }} + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.NEXUS_USER }} steps: - uses: actions/checkout@v7 with: persist-credentials: false + - name: Configure publishing secrets + env: + NEXUS_PASS64: ${{ secrets.NEXUS_PASS64 }} + GPG_KEY64: ${{ secrets.GPG_KEY64 }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + run: python3 .github/scripts/configure_publishing_secrets.py - name: Configure git credentials for JGit run: | git config --local http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n x-access-token:${{ secrets.GITHUB_TOKEN }} | base64 -w0)" diff --git a/build-logic/src/main/kotlin/Ext.kt b/build-logic/src/main/kotlin/Ext.kt index 6ab5ed4df6..746d8f550a 100644 --- a/build-logic/src/main/kotlin/Ext.kt +++ b/build-logic/src/main/kotlin/Ext.kt @@ -1,5 +1,4 @@ import com.diffplug.spotless.changelog.gradle.ChangelogExtension -import java.util.Base64 import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.api.Project import org.gradle.kotlin.dsl.findByType @@ -18,17 +17,6 @@ fun Project.requiredProperty(name: String): String = findProperty(name)?.toString() ?: error("$path is missing the '$name' property, which is required") -// getMimeDecoder, not getDecoder: the basic decoder rejects the newlines that `base64`/`openssl -// base64` leave in a wrapped secret, whereas Groovy's String.decodeBase64 (used before the Kotlin -// DSL migration) skipped whitespace. -fun decode64(varName: String): String { - val envValue = System.getenv(varName) ?: return "" - return String(Base64.getMimeDecoder().decode(envValue), Charsets.UTF_8) -} - -// Groovy's String.toBoolean() -- what this used before the Kotlin DSL migration -- accepts "true", -// "y" and "1", ignoring case. Kotlin's toBoolean() only accepts "true", so the short forms would -// silently become no-ops. fun String.toBooleanGroovy(): Boolean = trim().lowercase() in setOf("true", "y", "1") val isCiServer: Boolean diff --git a/build-logic/src/main/kotlin/spotless.java-publish.gradle.kts b/build-logic/src/main/kotlin/spotless.java-publish.gradle.kts index fbeb66d6c9..d7e52a0b69 100644 --- a/build-logic/src/main/kotlin/spotless.java-publish.gradle.kts +++ b/build-logic/src/main/kotlin/spotless.java-publish.gradle.kts @@ -1,7 +1,6 @@ plugins { `java-library` id("com.vanniktech.maven.publish") - signing } tasks.withType().configureEach { @@ -34,20 +33,6 @@ tasks.withType().configureEach { } } -signing { - if ( - !project.providers.gradleProperty("signingInMemoryKey").isPresent && - System.getenv("ORG_GRADLE_PROJECT_gpg_key64") != null - ) { - val gpgKey = decode64("ORG_GRADLE_PROJECT_gpg_key64") - useInMemoryPgpKeys( - "0x4272C851", - gpgKey, - System.getenv("ORG_GRADLE_PROJECT_gpg_passphrase"), - ) - } -} - // find the project with the changelog (this project for plugins, root project for libs) val changelogProject = if (pluginManager.hasPlugin("spotless.changelog")) project else rootProject val changelogTasks = changelogProject.tasks diff --git a/plugin-gradle/build.gradle.kts b/plugin-gradle/build.gradle.kts index 33cb375092..65cc4481ad 100644 --- a/plugin-gradle/build.gradle.kts +++ b/plugin-gradle/build.gradle.kts @@ -1,3 +1,7 @@ +import org.gradle.api.plugins.JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME +import org.gradle.api.plugins.JavaPlugin.JAVADOC_ELEMENTS_CONFIGURATION_NAME +import org.gradle.api.plugins.JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME +import org.gradle.api.plugins.JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME import org.gradle.plugin.compatibility.compatibility plugins { @@ -15,6 +19,26 @@ plugins { version = spotlessChangelog.versionNext +val publishedElements = + listOf( + API_ELEMENTS_CONFIGURATION_NAME, + RUNTIME_ELEMENTS_CONFIGURATION_NAME, + JAVADOC_ELEMENTS_CONFIGURATION_NAME, + SOURCES_ELEMENTS_CONFIGURATION_NAME, + ) + +configurations.configureEach { + when (name) { + in publishedElements -> + outgoing { + // Main/current capability. + capability("com.diffplug.spotless:spotless-plugin-gradle:$version") + // Historical capabilities. + capability("com.diffplug.gradle.spotless:spotless-plugin-gradle:$version") + } + } +} + dependencies { if ( version.toString().endsWith("-SNAPSHOT") || @@ -79,13 +103,6 @@ gradlePlugin { ) compatibility { features { configurationCache = true } } } - create("spotlessPluginLegacy") { - id = "com.diffplug.gradle.spotless" - implementationClass = "com.diffplug.gradle.spotless.SpotlessPluginRedirect" - displayName = "Spotless formatting plugin (legacy)" - description = project.description - tags = listOf("format") - } } } diff --git a/plugin-gradle/src/main/resources/META-INF/gradle-plugins/com.diffplug.gradle.spotless.properties b/plugin-gradle/src/main/resources/META-INF/gradle-plugins/com.diffplug.gradle.spotless.properties new file mode 100644 index 0000000000..dc8436ddaa --- /dev/null +++ b/plugin-gradle/src/main/resources/META-INF/gradle-plugins/com.diffplug.gradle.spotless.properties @@ -0,0 +1 @@ +implementation-class=com.diffplug.gradle.spotless.SpotlessPluginRedirect diff --git a/settings.gradle.kts b/settings.gradle.kts index fdc141eeca..defb5aeedf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,3 @@ -import kotlin.io.encoding.Base64 - pluginManagement { includeBuild("build-logic") repositories { @@ -92,26 +90,3 @@ val excludeMaven = if (!excludeMaven) { include("plugin-maven") // maven-specific glue code } - -fun decode64(varName: String): String { - val envValue = System.getenv(varName) ?: return "" - return String(Base64.Mime.decode(envValue), Charsets.UTF_8) -} - -val projectProperties = startParameter.projectProperties.toMutableMap() - -if (!projectProperties.containsKey("mavenCentralUsername")) { - System.getenv("ORG_GRADLE_PROJECT_nexus_user")?.let { - projectProperties["mavenCentralUsername"] = it - } -} - -if (!projectProperties.containsKey("mavenCentralPassword")) { - decode64("ORG_GRADLE_PROJECT_nexus_pass64") - .takeIf { it.isNotEmpty() } - ?.let { - projectProperties["mavenCentralPassword"] = it - } -} - -startParameter.setProjectProperties(projectProperties)