Skip to content

fix(jetbrains): use file-based signing secrets for bundled publish workflow - #12570

Merged
kirillk merged 1 commit into
mainfrom
fix/jetbrains-bundled-publish-signing-file-vars
Jul 27, 2026
Merged

fix(jetbrains): use file-based signing secrets for bundled publish workflow#12570
kirillk merged 1 commit into
mainfrom
fix/jetbrains-bundled-publish-signing-file-vars

Conversation

@kirillk

@kirillk kirillk commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Root cause

#12567 (51d6603) split the JetBrains bundled publish workflow's Gradle build into separate ./gradlew invocations for buildPlugin, signPlugin, verifyPluginSignature, and verifyPlugin to fix a Gradle 9 task-dependency issue between :signPlugin and :verifyPluginSignature.

After that split, verifyPluginSignature started failing in its own invocation with:

Task :verifyPluginSignature FAILED
Invalid argument: ***
Usage: org.jetbrains.zip.signer.VerifyOptions
  -cert [String] Certificate file (.../build/tmp/verifyPluginSignature/certificate-chain.pem)
  -in [String] Path to signed plugin zip/jar file (.../build/distributions/kilo.jetbrains-7.0.11-signed.zip)

Failed run: https://github.com/Kilo-Org/kilocode/actions/runs/30278909051

The workflow was passing JETBRAINS_CERTIFICATE_CHAIN / JETBRAINS_PRIVATE_KEY (multiline PEM secrets) directly into the intellij-platform-gradle-plugin's certificateChain/privateKey Property<String> config, which the zip-signer CLI wiring can mishandle — the masked multiline content ends up split into extra CLI arguments — when verifyPluginSignature runs as its own Gradle invocation instead of sharing a task graph with signPlugin.

packages/kilo-jetbrains/script/build-version.sh (used for local releases) avoids this by writing the secrets to temp files and exporting JETBRAINS_CERTIFICATE_CHAIN_FILE / JETBRAINS_PRIVATE_KEY_FILE / JETBRAINS_PRIVATE_KEY_PASSWORD instead, but build.gradle.kts never actually wired those *_FILE variables into the signing extension — it only read the raw-content JETBRAINS_CERTIFICATE_CHAIN / JETBRAINS_PRIVATE_KEY env vars.

Fix

  • packages/kilo-jetbrains/build.gradle.kts: wire signing.certificateChainFile / signing.privateKeyFile (file-based, via fileProvider(...)) from JETBRAINS_CERTIFICATE_CHAIN_FILE / JETBRAINS_PRIVATE_KEY_FILE instead of the raw-content certificateChain / privateKey properties. This makes the local build-version.sh flow and CI consistent, and avoids ever passing multiline secret content as a CLI-facing value.
  • .github/workflows/publish-jetbrains-bundled.yml: write JETBRAINS_CERTIFICATE_CHAIN / JETBRAINS_PRIVATE_KEY to mode-600 temp files under $RUNNER_TEMP/jetbrains-signing (dir mode 700) before the Gradle build step, export the *_FILE env vars via $GITHUB_ENV so they're available to every subsequent ./gradlew invocation (signPlugin, verifyPluginSignature, verifyPlugin), and remove the temp files in an if: always() cleanup step. No secret values are printed to logs.

Validation

  • bun run script/check-workflows.ts — passes
  • git diff --check -- .github/workflows/publish-jetbrains-bundled.yml — clean
  • Verified the certificateChainFile/privateKeyFile/fileProvider(Provider<File>) API against the org.jetbrains.intellij.platform Gradle plugin (2.17.0) Signing extension source and the Gradle 9 RegularFileProperty Javadoc.
  • Could not run ./gradlew typecheck / a full Gradle build in this sandbox — the sandbox's outbound network path fails TLS certificate validation when Gradle tries to download its distribution (PKIX path building failed), unrelated to this change. Recommend running ./gradlew typecheck from packages/kilo-jetbrains/ in CI/locally before merge as a final check.

Re-dispatch after merge

gh workflow run publish-jetbrains-bundled.yml --ref main -f pr=12563 -f merge_commit=439448291efe1eb648de2481f12923511cbd63ec

Built for Kirill Kalishev by Kilo for Slack

…rkflow

Passing the JETBRAINS_CERTIFICATE_CHAIN / JETBRAINS_PRIVATE_KEY multiline
secret content directly as certificateChain/privateKey Gradle properties
gets mishandled by the zip-signer CLI when signPlugin and
verifyPluginSignature run as separate Gradle invocations (#12567), causing
verifyPluginSignature to fail with 'Invalid argument: ***' as the masked
multiline content is split into extra CLI args.

Mirror script/build-version.sh: write the certificate chain and private
key to temp files under $RUNNER_TEMP and wire
certificateChainFile/privateKeyFile (file-based) into the intellij
signing extension instead of certificateChain/privateKey (raw content).

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
@kilo-code-bot

kilo-code-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Reviewed the file-based signing secret rewiring in both the workflow (temp-file write/cleanup, permission handling, env var propagation via GITHUB_ENV) and build.gradle.kts (certificateChainFile/privateKeyFile wiring). Temp files are created with a narrow umask before writing, explicitly chmod 600'd, and removed in an if: always() step; no secret values are echoed to logs. Env var scoping looks consistent with the rest of the job.

Files Reviewed (2 files)
  • .github/workflows/publish-jetbrains-bundled.yml
  • packages/kilo-jetbrains/build.gradle.kts

Reviewed by claude-sonnet-5 · Input: 26 · Output: 8.5K · Cached: 532.7K

Review guidance: REVIEW.md from base branch main

@kirillk
kirillk merged commit d362812 into main Jul 27, 2026
29 checks passed
@kirillk
kirillk deleted the fix/jetbrains-bundled-publish-signing-file-vars branch July 27, 2026 16:20
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
…-publish-signing-file-vars

fix(jetbrains): use file-based signing secrets for bundled publish workflow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants