diff --git a/.github/workflows/publish-jetbrains.yml b/.github/workflows/publish-jetbrains.yml deleted file mode 100644 index 3465c4f78f1..00000000000 --- a/.github/workflows/publish-jetbrains.yml +++ /dev/null @@ -1,167 +0,0 @@ -# kilocode_change - new file -name: publish-jetbrains - -on: - push: - tags: - - "jetbrains/*" - -concurrency: - group: publish-jetbrains-${{ github.ref }} - cancel-in-progress: false - -permissions: - contents: write - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - publish: - if: github.repository == 'Kilo-Org/kilocode' - runs-on: blacksmith-8vcpu-ubuntu-2404 - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: "24" - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: "21" - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Install build tools - run: | - sudo apt-get update - sudo apt-get install -y patchelf zip - - - name: Validate version tag - id: version - run: | - tag="$GITHUB_REF_NAME" - if [[ "$tag" != jetbrains/* ]]; then - echo "Unsupported tag '$tag'. Expected jetbrains/." >&2 - exit 1 - fi - - version="${tag#jetbrains/}" - if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$ ]]; then - { - echo "version=$version" - echo "kind=rc" - echo "marketplace_channel=eap" - echo "cli_channel=rc" - } >> "$GITHUB_OUTPUT" - exit 0 - fi - - if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - { - echo "version=$version" - echo "kind=stable" - echo "marketplace_channel=default" - echo "cli_channel=latest" - } >> "$GITHUB_OUTPUT" - echo "Stable JetBrains Marketplace publishing is implemented but intentionally disabled; use an rc tag such as jetbrains/7.0.1-rc.1." >&2 - exit 1 - fi - - echo "Unsupported JetBrains plugin version '$version'. Expected x.y.z-rc.n or x.y.z." >&2 - exit 1 - - - name: Validate publishing secrets - run: | - missing=0 - for name in JETBRAINS_MARKETPLACE_TOKEN JETBRAINS_CERTIFICATE_CHAIN JETBRAINS_PRIVATE_KEY JETBRAINS_PRIVATE_KEY_PASSWORD; do - if [[ -z "${!name}" ]]; then - echo "Missing required secret: $name" >&2 - missing=1 - fi - done - exit "$missing" - env: - JETBRAINS_MARKETPLACE_TOKEN: ${{ secrets.JETBRAINS_MARKETPLACE_TOKEN }} - JETBRAINS_CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }} - JETBRAINS_PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }} - JETBRAINS_PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }} - - - name: Prepare CLI resources - working-directory: packages/kilo-jetbrains - run: bun script/build.ts --production --prepare-cli - env: - KILO_VERSION: ${{ steps.version.outputs.version }} - KILO_CHANNEL: ${{ steps.version.outputs.cli_channel }} - GH_TOKEN: ${{ github.token }} - GH_REPO: ${{ github.repository }} - - - name: Verify plugin - working-directory: packages/kilo-jetbrains - run: ./gradlew verifyPlugin -Pproduction=true -Pkilo.channel="$CHANNEL" - env: - CHANNEL: ${{ steps.version.outputs.marketplace_channel }} - - - name: Publish to JetBrains Marketplace - working-directory: packages/kilo-jetbrains - run: ./gradlew publishPlugin -Pproduction=true -Pkilo.channel="$CHANNEL" - env: - CHANNEL: ${{ steps.version.outputs.marketplace_channel }} - JETBRAINS_MARKETPLACE_TOKEN: ${{ secrets.JETBRAINS_MARKETPLACE_TOKEN }} - JETBRAINS_CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }} - JETBRAINS_PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }} - JETBRAINS_PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }} - - - name: Resolve plugin archive - id: archive - run: | - mapfile -t signed < <(compgen -G "packages/kilo-jetbrains/build/distributions/*-signed.zip") - if [[ "${#signed[@]}" -eq 1 ]]; then - echo "path=${signed[0]}" >> "$GITHUB_OUTPUT" - exit 0 - fi - if [[ "${#signed[@]}" -gt 1 ]]; then - echo "Expected exactly one signed JetBrains plugin ZIP, found ${#signed[@]}." >&2 - printf '%s\n' "${signed[@]}" >&2 - exit 1 - fi - - mapfile -t files < <(compgen -G "packages/kilo-jetbrains/build/distributions/*.zip") - if [[ "${#files[@]}" -ne 1 ]]; then - echo "Expected exactly one JetBrains plugin ZIP, found ${#files[@]}." >&2 - printf '%s\n' "${files[@]}" >&2 - exit 1 - fi - echo "path=${files[0]}" >> "$GITHUB_OUTPUT" - - - name: Upload to GitHub Release - run: | - tag="$GITHUB_REF_NAME" - title="JetBrains $VERSION" - notes="JetBrains plugin $VERSION." - if gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then - gh release upload "$tag" "$ARCHIVE" --clobber --repo "$GITHUB_REPOSITORY" - exit 0 - fi - gh release create "$tag" "$ARCHIVE" --title "$title" --notes "$notes" --prerelease --repo "$GITHUB_REPOSITORY" - env: - GH_TOKEN: ${{ github.token }} - VERSION: ${{ steps.version.outputs.version }} - ARCHIVE: ${{ steps.archive.outputs.path }} - - - name: Upload workflow artifact - if: always() - uses: actions/upload-artifact@v4 - with: - name: kilo-jetbrains-${{ steps.version.outputs.version }} - path: packages/kilo-jetbrains/build/distributions/*.zip - if-no-files-found: ignore diff --git a/packages/kilo-jetbrains/README.md b/packages/kilo-jetbrains/README.md index 8cd2eed1cc5..56fbf578a11 100644 --- a/packages/kilo-jetbrains/README.md +++ b/packages/kilo-jetbrains/README.md @@ -52,29 +52,6 @@ The built plugin archive is at `build/distributions/kilo.jetbrains-.zip --- -## Publish release candidates - -JetBrains release-candidate builds publish from tags matching `jetbrains/x.y.z-rc.n`, for example `jetbrains/7.0.1-rc.1`. The git tag is the source of truth for the Marketplace plugin version; production Gradle builds ignore manually supplied version properties and fail if `HEAD` is not tagged with `jetbrains/`. Local dev builds can use the placeholder `0.0.0-dev` version. - -The `publish-jetbrains` workflow publishes RC builds to the JetBrains Marketplace `eap` channel and uploads the same plugin ZIP to a GitHub prerelease for the tag. Stable tags like `jetbrains/x.y.z` are recognized by the workflow but intentionally rejected until default-channel publishing is enabled. - -Testers can install or update EAP builds from this custom plugin repository: - -``` -https://plugins.jetbrains.com/plugins/eap/list -``` - -Required GitHub Actions secrets: - -- `JETBRAINS_MARKETPLACE_TOKEN` -- `JETBRAINS_CERTIFICATE_CHAIN` -- `JETBRAINS_PRIVATE_KEY` -- `JETBRAINS_PRIVATE_KEY_PASSWORD` - -Before the first publish, complete `RELEASE_TODO.md`. - ---- - ## Run the plugin Use the `runIde` Gradle task (available in the Gradle tool window or via the "Run JetBrains Plugin" run configuration) to launch a sandboxed IntelliJ instance with the plugin installed. diff --git a/packages/kilo-jetbrains/RELEASE_TODO.md b/packages/kilo-jetbrains/RELEASE_TODO.md deleted file mode 100644 index d3b8430da4d..00000000000 --- a/packages/kilo-jetbrains/RELEASE_TODO.md +++ /dev/null @@ -1,44 +0,0 @@ -# JetBrains Release Todo - -## One-Time Marketplace Setup - -- Confirm `ai.kilocode.jetbrains` is the final permanent Marketplace plugin ID before the first upload. -- Build a production ZIP locally or in CI for the first Marketplace version. -- Manually upload the first plugin version in JetBrains Marketplace if the plugin has not been published before. -- Confirm the plugin is owned by the correct Kilo vendor or organization. -- Confirm the `eap` custom channel exists or is accepted on the first RC upload. -- Confirm Marketplace signing requirements before publishing RC builds. - -## One-Time GitHub Setup - -- Create a JetBrains Marketplace permanent token from Marketplace `My Tokens`. -- Add `JETBRAINS_MARKETPLACE_TOKEN` to GitHub Actions secrets or the protected environment. -- Confirm `GITHUB_TOKEN` has `contents: write` permission for creating and updating GitHub Releases from `jetbrains/*` tags. -- Optionally create a protected `jetbrains-marketplace` GitHub Environment with required reviewers. -- If using an environment, move the Marketplace and signing secrets there and set the workflow job environment. - -## One-Time Signing Certificate Setup - -- Generate or locate the JetBrains plugin signing private key and certificate chain. -- Add `JETBRAINS_CERTIFICATE_CHAIN` with the full certificate chain PEM content. -- Add `JETBRAINS_PRIVATE_KEY` with the private key PEM content. -- Add `JETBRAINS_PRIVATE_KEY_PASSWORD` with the private key password. -- Keep PEM files out of git, local logs, and workflow output. -- If GitHub secret input mangles multiline PEM values, store base64-encoded values and verify the Gradle signing task decodes them correctly. - -## Per-RC Release - -- Choose an RC version in the form `x.y.z-rc.n`. -- Push tag `jetbrains/x.y.z-rc.n`. -- Watch the `publish-jetbrains` workflow. -- Download and retain the workflow artifact if needed. -- Confirm the update appears on the JetBrains Marketplace `eap` channel. -- Confirm the GitHub Release for the `jetbrains/x.y.z-rc.n` tag exists and contains the JetBrains plugin ZIP asset. -- Share `https://plugins.jetbrains.com/plugins/eap/list` with testers. - -## Stable Release Guard - -- Stable tags like `jetbrains/x.y.z` are intentionally rejected for now. -- Before enabling stable releases, remove the workflow stable guard. -- Verify `kilo.channel=default` publishes to the default Marketplace channel. -- Update this checklist before stable releases are enabled. diff --git a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/app/KiloBackendSessionManager.kt b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/app/KiloBackendSessionManager.kt index d1998f4d64b..dd649bfd1ec 100644 --- a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/app/KiloBackendSessionManager.kt +++ b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/app/KiloBackendSessionManager.kt @@ -265,7 +265,7 @@ class KiloBackendSessionManager( time = SessionTimeDto( created = s.time.created.toDouble(), updated = s.time.updated.toDouble(), - archived = s.time.archived?.toDouble(), + archived = s.time.archived, ), summary = s.summary?.let { SessionSummaryDto( @@ -286,7 +286,7 @@ class KiloBackendSessionManager( time = SessionTimeDto( created = s.time.created.toDouble(), updated = s.time.updated.toDouble(), - archived = s.time.archived?.toDouble(), + archived = s.time.archived, ), summary = s.summary?.let { SessionSummaryDto( diff --git a/packages/kilo-jetbrains/build.gradle.kts b/packages/kilo-jetbrains/build.gradle.kts index 3ce7ec96cd4..00b4bd5ea2b 100644 --- a/packages/kilo-jetbrains/build.gradle.kts +++ b/packages/kilo-jetbrains/build.gradle.kts @@ -4,32 +4,7 @@ import org.jetbrains.intellij.platform.gradle.tasks.RunIdeTask import org.jetbrains.intellij.platform.gradle.tasks.aware.SplitModeAware.SplitModeTarget group = "ai.kilocode.jetbrains" - -fun checked(value: String): String { - if (value == "0.0.0-dev") return value - require(Regex("^[0-9]+\\.[0-9]+\\.[0-9]+(-rc\\.[0-9]+)?$").matches(value)) { - "Invalid JetBrains plugin version: $value" - } - return value -} - -fun gitTag(): String? { - val text = providers.exec { - commandLine("git", "tag", "--points-at", "HEAD") - }.standardOutput.asText.get() - return text.lineSequence().map { it.trim() }.firstOrNull { it.startsWith("jetbrains/") } -} - -val release = providers.gradleProperty("production").map { it.toBoolean() }.orElse(false).get() -val ver = if (release) checked( - gitTag()?.removePrefix("jetbrains/") - ?: error("Missing JetBrains plugin version. Publish builds must run from a jetbrains/ tag."), -) else checked(gitTag()?.removePrefix("jetbrains/") ?: "0.0.0-dev") - -val notes = providers.gradleProperty("kilo.changeNotes").orElse("Release candidate build.") -val channel = providers.gradleProperty("kilo.channel").map { it.trim() }.orElse("default") - -version = ver +version = "7.0.1" plugins { application @@ -84,39 +59,9 @@ intellijPlatform { splitMode = true splitModeTarget = SplitModeTarget.BOTH - pluginConfiguration { - id = "ai.kilocode.jetbrains" - name = "Kilo Code" - version = provider { ver } - changeNotes = notes - - ideaVersion { - untilBuild = provider { null } - } - - vendor { - name = "Kilo Code" - url = "https://kilo.ai" - } - } - - publishing { - token = providers.environmentVariable("JETBRAINS_MARKETPLACE_TOKEN") - channels = channel.map { value -> - if (value.isBlank() || value == "default") return@map listOf("default") - listOf(value) - } - } - - signing { - certificateChain = providers.environmentVariable("JETBRAINS_CERTIFICATE_CHAIN") - privateKey = providers.environmentVariable("JETBRAINS_PRIVATE_KEY") - password = providers.environmentVariable("JETBRAINS_PRIVATE_KEY_PASSWORD") - } - pluginVerification { ides { - create(IntelliJPlatformType.IntellijIdea, libs.versions.intellij.platform) + create(IntelliJPlatformType.IntellijIdeaCommunity, libs.versions.intellij.platform) } } }