diff --git a/.github/workflows/publish-jetbrains-bundled.yml b/.github/workflows/publish-jetbrains-bundled.yml index 53de4637bdb..8f0134b15c7 100644 --- a/.github/workflows/publish-jetbrains-bundled.yml +++ b/.github/workflows/publish-jetbrains-bundled.yml @@ -142,6 +142,22 @@ jobs: JETBRAINS_PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }} JETBRAINS_PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }} + - name: Write signing secrets to temp files + run: | + dir="$RUNNER_TEMP/jetbrains-signing" + mkdir -m 700 -p "$dir" + chain="$dir/certificate-chain.pem" + key="$dir/private-key.pem" + umask 077 + printf '%s' "$JETBRAINS_CERTIFICATE_CHAIN" > "$chain" + printf '%s' "$JETBRAINS_PRIVATE_KEY" > "$key" + chmod 600 "$chain" "$key" + echo "JETBRAINS_CERTIFICATE_CHAIN_FILE=$chain" >> "$GITHUB_ENV" + echo "JETBRAINS_PRIVATE_KEY_FILE=$key" >> "$GITHUB_ENV" + env: + JETBRAINS_CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }} + JETBRAINS_PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }} + - name: Build signed bundled plugin working-directory: packages/kilo-jetbrains run: | @@ -152,6 +168,9 @@ jobs: -Pkilo.cli.bundled=true ) + # signPlugin and verifyPluginSignature run as separate Gradle invocations (see #12567) + # so the JETBRAINS_CERTIFICATE_CHAIN_FILE / JETBRAINS_PRIVATE_KEY_FILE env vars set in + # the previous step (rather than raw multiline secret content) must be present for both. ./gradlew clean buildPlugin "${args[@]}" ./gradlew signPlugin "${args[@]}" ./gradlew verifyPluginSignature "${args[@]}" @@ -161,10 +180,12 @@ jobs: GITHUB_TOKEN: ${{ github.token }} VERSION: ${{ needs.validate.outputs.version }} CHANNEL: ${{ needs.validate.outputs.channel }} - JETBRAINS_CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }} - JETBRAINS_PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }} JETBRAINS_PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }} + - name: Remove signing secret temp files + if: always() + run: rm -rf "$RUNNER_TEMP/jetbrains-signing" + - name: Resolve bundled archive id: archive run: | diff --git a/packages/kilo-jetbrains/build.gradle.kts b/packages/kilo-jetbrains/build.gradle.kts index c13a70c2b64..3ad08aff36b 100644 --- a/packages/kilo-jetbrains/build.gradle.kts +++ b/packages/kilo-jetbrains/build.gradle.kts @@ -207,8 +207,15 @@ intellijPlatform { } signing { - certificateChain = providers.environmentVariable("JETBRAINS_CERTIFICATE_CHAIN") - privateKey = providers.environmentVariable("JETBRAINS_PRIVATE_KEY") + // File-based inputs are preferred over raw content: certificateChain/privateKey take + // precedence over certificateChainFile/privateKeyFile in the IntelliJ Platform Gradle + // plugin, and passing multiline PEM content straight through as a certificateChain/ + // privateKey value can get mishandled as extra CLI arguments by the zip-signer CLI when + // signPlugin/verifyPluginSignature run as separate Gradle invocations. Both CI + // (.github/workflows/publish-jetbrains-bundled.yml) and local releases + // (script/build-version.sh) write the secrets to files and export the *_FILE variables. + certificateChainFile.fileProvider(providers.environmentVariable("JETBRAINS_CERTIFICATE_CHAIN_FILE").map { file(it) }) + privateKeyFile.fileProvider(providers.environmentVariable("JETBRAINS_PRIVATE_KEY_FILE").map { file(it) }) password = providers.environmentVariable("JETBRAINS_PRIVATE_KEY_PASSWORD") }