mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
328 lines
11 KiB
YAML
328 lines
11 KiB
YAML
# kilocode_change - new file
|
|
name: publish-jetbrains-bundled
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
pr:
|
|
description: Merged JetBrains release PR number to bundle
|
|
required: true
|
|
type: string
|
|
merge_commit:
|
|
description: Merge commit SHA from the reviewed release PR
|
|
required: true
|
|
type: string
|
|
|
|
concurrency:
|
|
group: publish-jetbrains-bundled-pr-${{ inputs.pr }}
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
|
|
jobs:
|
|
validate:
|
|
if: github.repository == 'Kilo-Org/kilocode'
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
outputs:
|
|
version: ${{ steps.release.outputs.version }}
|
|
kind: ${{ steps.release.outputs.kind }}
|
|
tag: ${{ steps.release.outputs.tag }}
|
|
channel: ${{ steps.release.outputs.marketplace_channel }}
|
|
steps:
|
|
- name: Checkout trusted validation scripts
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
ref: main
|
|
|
|
- name: Setup Bun for validation
|
|
uses: ./.github/actions/setup-bun
|
|
|
|
- name: Checkout merged release PR for validation
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
path: release
|
|
persist-credentials: false
|
|
ref: ${{ inputs.merge_commit }}
|
|
|
|
- name: Validate release PR and tag
|
|
id: release
|
|
working-directory: release
|
|
run: bun ../script/jetbrains-release-validate.ts --pr "$PR_NUMBER"
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
GH_REPO: ${{ github.repository }}
|
|
PR_NUMBER: ${{ inputs.pr }}
|
|
|
|
bundle:
|
|
needs: validate
|
|
if: github.repository == 'Kilo-Org/kilocode'
|
|
runs-on: blacksmith-8vcpu-ubuntu-2404
|
|
permissions:
|
|
actions: read
|
|
contents: write
|
|
outputs:
|
|
version: ${{ needs.validate.outputs.version }}
|
|
kind: ${{ needs.validate.outputs.kind }}
|
|
steps:
|
|
- name: Checkout merged release PR metadata
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
ref: ${{ inputs.merge_commit }}
|
|
|
|
- name: Save reviewed release metadata
|
|
run: |
|
|
cp packages/kilo-jetbrains/CHANGELOG.md "$RUNNER_TEMP/jetbrains-CHANGELOG.md"
|
|
cp packages/kilo-jetbrains/gradle.properties "$RUNNER_TEMP/jetbrains-gradle.properties"
|
|
|
|
- name: Checkout release tag
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ needs.validate.outputs.tag }}
|
|
|
|
- name: Restore reviewed release metadata
|
|
run: |
|
|
cp "$RUNNER_TEMP/jetbrains-CHANGELOG.md" packages/kilo-jetbrains/CHANGELOG.md
|
|
cp "$RUNNER_TEMP/jetbrains-gradle.properties" packages/kilo-jetbrains/gradle.properties
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "24"
|
|
|
|
- name: Setup Bun
|
|
uses: ./.github/actions/setup-bun
|
|
|
|
- name: Install dependencies
|
|
run: bun install
|
|
|
|
- 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 unzip
|
|
curl --fail --location \
|
|
https://ziglang.org/download/0.14.0/zig-linux-x86_64-0.14.0.tar.xz \
|
|
--output "$RUNNER_TEMP/zig.tar.xz"
|
|
echo "473ec26806133cf4d1918caf1a410f8403a13d979726a9045b421b685031a982 $RUNNER_TEMP/zig.tar.xz" | sha256sum --check --status
|
|
tar -xJf "$RUNNER_TEMP/zig.tar.xz" -C "$RUNNER_TEMP"
|
|
echo "$RUNNER_TEMP/zig-linux-x86_64-0.14.0" >> "$GITHUB_PATH"
|
|
|
|
- name: Validate signing secrets
|
|
run: |
|
|
missing=0
|
|
for name in 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_CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }}
|
|
JETBRAINS_PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }}
|
|
JETBRAINS_PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }}
|
|
|
|
- name: Build signed bundled plugin
|
|
working-directory: packages/kilo-jetbrains
|
|
run: |
|
|
args=(
|
|
-Pproduction=true
|
|
-Pkilo.version="$VERSION"
|
|
-Pkilo.channel="$CHANNEL"
|
|
-Pkilo.cli.bundled=true
|
|
)
|
|
|
|
./gradlew clean buildPlugin "${args[@]}"
|
|
./gradlew signPlugin "${args[@]}"
|
|
./gradlew verifyPluginSignature "${args[@]}"
|
|
./gradlew verifyPlugin "${args[@]}"
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
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: Resolve bundled archive
|
|
id: archive
|
|
run: |
|
|
mapfile -t signed < <(compgen -G "packages/kilo-jetbrains/build/distributions/*-signed.zip")
|
|
if [[ "${#signed[@]}" -ne 1 ]]; then
|
|
echo "Expected exactly one signed bundled JetBrains plugin ZIP, found ${#signed[@]}." >&2
|
|
printf '%s\n' "${signed[@]}" >&2
|
|
exit 1
|
|
fi
|
|
asset="kilo-code-${VERSION}-bundled.zip"
|
|
dest="packages/kilo-jetbrains/build/release/$asset"
|
|
mkdir -p "$(dirname "$dest")"
|
|
cp "${signed[0]}" "$dest"
|
|
echo "asset=$asset" >> "$GITHUB_OUTPUT"
|
|
echo "path=$dest" >> "$GITHUB_OUTPUT"
|
|
env:
|
|
VERSION: ${{ needs.validate.outputs.version }}
|
|
|
|
- name: Upload bundled ZIP to GitHub Release
|
|
run: gh release upload "$TAG" "$ARCHIVE" --clobber --repo "$GITHUB_REPOSITORY"
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
TAG: ${{ needs.validate.outputs.tag }}
|
|
ARCHIVE: ${{ steps.archive.outputs.path }}
|
|
|
|
- name: Resolve bundled asset URL
|
|
id: asset
|
|
run: |
|
|
url="$(gh release view "$TAG" --json assets --jq '.assets[] | select(.name == env.ASSET) | .url' --repo "$GITHUB_REPOSITORY")"
|
|
if [[ -z "$url" ]]; then
|
|
echo "Could not resolve GitHub Release URL for $ASSET" >&2
|
|
exit 1
|
|
fi
|
|
echo "url=$url" >> "$GITHUB_OUTPUT"
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
TAG: ${{ needs.validate.outputs.tag }}
|
|
ASSET: ${{ steps.archive.outputs.asset }}
|
|
|
|
- name: Generate stable plugin repository XML
|
|
if: needs.validate.outputs.kind == 'stable'
|
|
run: |
|
|
mkdir -p pages/jetbrains
|
|
python3 <<'PY'
|
|
import html
|
|
import io
|
|
import os
|
|
import zipfile
|
|
import xml.etree.ElementTree as ET
|
|
|
|
archive = os.environ["ARCHIVE"]
|
|
asset = os.environ["ASSET_URL"]
|
|
version = os.environ["VERSION"]
|
|
|
|
def plugin_xml(path):
|
|
with zipfile.ZipFile(path) as zip:
|
|
for name in zip.namelist():
|
|
if name.endswith("META-INF/plugin.xml"):
|
|
return zip.read(name)
|
|
for name in zip.namelist():
|
|
if not name.endswith(".jar"):
|
|
continue
|
|
with zipfile.ZipFile(io.BytesIO(zip.read(name))) as jar:
|
|
for item in jar.namelist():
|
|
if item.endswith("META-INF/plugin.xml"):
|
|
return jar.read(item)
|
|
raise SystemExit("bundled plugin ZIP did not contain META-INF/plugin.xml")
|
|
|
|
root = ET.fromstring(plugin_xml(archive))
|
|
|
|
def text(name, default=""):
|
|
item = root.find(name)
|
|
return item.text.strip() if item is not None and item.text else default
|
|
|
|
def cdata(value):
|
|
return "<![CDATA[" + value.replace("]]>", "]]]]><![CDATA[>") + "]]>"
|
|
|
|
plugin = text("id", "ai.kilocode.jetbrains")
|
|
name = text("name", "Kilo Code")
|
|
vendor = text("vendor", "Kilo Code")
|
|
desc = text("description")
|
|
notes = text("change-notes")
|
|
idea = root.find("idea-version")
|
|
attrs = ""
|
|
if idea is not None:
|
|
since = idea.attrib.get("since-build")
|
|
until = idea.attrib.get("until-build")
|
|
if since:
|
|
attrs += f' since-build="{html.escape(since)}"'
|
|
if until:
|
|
attrs += f' until-build="{html.escape(until)}"'
|
|
|
|
xml = [
|
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
'<plugins>',
|
|
f' <plugin id="{html.escape(plugin)}" version="{html.escape(version)}" url="{html.escape(asset)}">',
|
|
f' <name>{html.escape(name)}</name>',
|
|
f' <vendor>{html.escape(vendor)}</vendor>',
|
|
f' <idea-version{attrs}/>',
|
|
]
|
|
if desc:
|
|
xml.append(f' <description>{cdata(desc)}</description>')
|
|
if notes:
|
|
xml.append(f' <change-notes>{cdata(notes)}</change-notes>')
|
|
xml.extend([' </plugin>', '</plugins>', ''])
|
|
with open("pages/jetbrains/updatePlugins.xml", "w", encoding="utf-8") as file:
|
|
file.write("\n".join(xml))
|
|
PY
|
|
env:
|
|
ARCHIVE: ${{ steps.archive.outputs.path }}
|
|
ASSET_URL: ${{ steps.asset.outputs.url }}
|
|
VERSION: ${{ needs.validate.outputs.version }}
|
|
|
|
- name: Upload stable Pages source
|
|
if: needs.validate.outputs.kind == 'stable'
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: jetbrains-pages-${{ needs.validate.outputs.version }}
|
|
path: pages
|
|
if-no-files-found: error
|
|
|
|
- name: Upload workflow artifact
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: kilo-jetbrains-bundled-${{ needs.validate.outputs.version }}
|
|
path: |
|
|
packages/kilo-jetbrains/build/release/*.zip
|
|
pages/jetbrains/updatePlugins.xml
|
|
if-no-files-found: ignore
|
|
|
|
pages:
|
|
needs: bundle
|
|
if: needs.bundle.outputs.kind == 'stable'
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
permissions:
|
|
actions: read
|
|
id-token: write
|
|
pages: write
|
|
environment:
|
|
name: github-pages
|
|
url: ${{ steps.deployment.outputs.page_url }}
|
|
steps:
|
|
- name: Download stable Pages source
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: jetbrains-pages-${{ needs.bundle.outputs.version }}
|
|
path: pages
|
|
|
|
- name: Configure Pages
|
|
uses: actions/configure-pages@v5
|
|
|
|
- name: Upload Pages artifact
|
|
uses: actions/upload-pages-artifact@v4
|
|
with:
|
|
path: pages
|
|
|
|
- name: Deploy Pages
|
|
id: deployment
|
|
uses: actions/deploy-pages@v4
|