Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 9 additions & 43 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,45 +1,11 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
.kotlin

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
.claude/
.gradle/
.idea/
.intellijPlatform/
.kotlin/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
build/

.intellijPlatform/
chain.crt
private.pem
private_encrypted.pem
129 changes: 129 additions & 0 deletions docs/05-signing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# 05 · Signing Certificates for Plugin Publishing

JetBrains requires plugins to be signed before they can be published to the Marketplace. This guide explains how to generate the signing certificates and configure the build.

---

## 1. Generate a private key and certificate chain

Use `openssl` to create the key pair:

```bash
# Generate an encrypted RSA 4096-bit private key
openssl genpkey -aes-256-cbc -algorithm RSA \
-out private_encrypted.pem -pkeyopt rsa_keygen_bits:4096

# Convert to plain RSA format (needed by the signing tooling)
openssl rsa -in private_encrypted.pem -out private.pem

# Generate a self-signed certificate (valid for 365 days)
openssl req -key private.pem -new -x509 -days 365 -out chain.crt
```

This produces two files:

| File | Purpose |
|------|---------|
| `private.pem` | RSA private key used to sign the plugin ZIP |
| `chain.crt` | Certificate chain that JetBrains uses to verify the signature |

> **Important:** Never commit these files to version control. Add them to `.gitignore` if not already covered.

---

## 2. Configure Gradle for signing

Add the `signPlugin` configuration block to `build.gradle.kts`:

```kotlin
intellijPlatform {
signing {
certificateChainFile = file("signing/chain.crt")
privateKeyFile = file("signing/private.pem")
password = providers.environmentVariable("PRIVATE_KEY_PASSWORD")
}
}
```

> **Note:** The `password` property is only needed if your private key is encrypted. If you exported a plain key (`private.pem` from step 1), you can omit it.

---

## 3. Use environment variables (recommended for CI)

For automated pipelines, pass the certificate content via environment variables instead of files:

```kotlin
intellijPlatform {
signing {
certificateChain = providers.environmentVariable("CERTIFICATE_CHAIN")
privateKey = providers.environmentVariable("PRIVATE_KEY")
password = providers.environmentVariable("PRIVATE_KEY_PASSWORD")
}
}
```

Set the environment variables with the **full file contents** (including PEM headers):

```bash
export CERTIFICATE_CHAIN="$(cat signing/chain.crt)"
export PRIVATE_KEY="$(cat signing/private.pem)"
export PRIVATE_KEY_PASSWORD="your-passphrase" # only if key is encrypted
```

---

## 4. Sign the plugin

Once configured, signing happens automatically during the `signPlugin` task:

```bash
mise run build
# or directly:
./gradlew signPlugin
```

The signed ZIP is written to `build/distributions/`.

---

## 5. Publish the signed plugin

Publishing requires a Marketplace token in addition to signing:

```bash
export PUBLISH_TOKEN="<your-jetbrains-marketplace-token>"
```

```kotlin
intellijPlatform {
publishing {
token = providers.environmentVariable("PUBLISH_TOKEN")
}
}
```

Then publish:

```bash
./gradlew publishPlugin
```

> **Tip:** Generate your Marketplace token at https://plugins.jetbrains.com/author/me/tokens

---

## Summary of secrets

| Secret | Where to store | Used by |
|--------|---------------|---------|
| `private.pem` | Local `signing/` dir or CI secret | `signPlugin` |
| `chain.crt` | Local `signing/` dir or CI secret | `signPlugin` |
| Private key password | Environment variable | `signPlugin` |
| Marketplace token | Environment variable | `publishPlugin` |

---

## Previous step

← [04-testing.md](04-testing.md) — Testing
Loading