mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-09 17:29:12 +00:00
* ci(kimi-desktop): strip Developer ID prefix from CSC_NAME electron-builder rejects the 'Developer ID Application: ' prefix in CSC_NAME; the keychain setup exports the full certificate name, so strip the prefix before passing it to electron-builder. * ci(kimi-desktop): add homepage and maintainer for linux .deb electron-builder's .deb target requires a project homepage and a package maintainer; set both so the Linux build succeeds.
170 lines
6 KiB
YAML
170 lines
6 KiB
YAML
name: desktop-build
|
|
|
|
# Builds the Kimi Desktop (Electron) installers for macOS, Windows and Linux.
|
|
# Each runner builds the matching-platform SEA backend first, then packages it
|
|
# with electron-builder.
|
|
#
|
|
# macOS is signed with a Developer ID certificate + notarized (so it opens on
|
|
# any Mac without the "app is damaged" Gatekeeper block) when `sign-macos` is
|
|
# true and the Apple secrets are configured. Windows/Linux ship unsigned in v1.
|
|
#
|
|
# Triggered two ways:
|
|
# - workflow_dispatch: manual ad-hoc builds from the Actions tab.
|
|
# - workflow_call: called by release.yml to attach installers to a release.
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
sign-macos:
|
|
description: 'Sign + notarize macOS (needs Apple secrets)'
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
retention-days:
|
|
description: 'Artifact retention in days'
|
|
required: false
|
|
type: number
|
|
default: 5
|
|
upload-artifact-prefix:
|
|
description: 'Prefix for uploaded artifact name'
|
|
required: false
|
|
type: string
|
|
default: 'kimi-desktop'
|
|
workflow_call:
|
|
inputs:
|
|
sign-macos:
|
|
description: 'Sign + notarize macOS (needs Apple secrets)'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
retention-days:
|
|
description: 'Artifact retention in days'
|
|
required: false
|
|
type: number
|
|
default: 7
|
|
upload-artifact-prefix:
|
|
description: 'Prefix for uploaded artifact name'
|
|
required: false
|
|
type: string
|
|
default: 'kimi-desktop'
|
|
secrets:
|
|
APPLE_CERTIFICATE_P12:
|
|
required: false
|
|
APPLE_CERTIFICATE_PASSWORD:
|
|
required: false
|
|
APPLE_NOTARIZATION_KEY_P8:
|
|
required: false
|
|
APPLE_NOTARIZATION_KEY_ID:
|
|
required: false
|
|
APPLE_NOTARIZATION_ISSUER_ID:
|
|
required: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
desktop:
|
|
name: Desktop installer (${{ matrix.target }})
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- os: macos-15
|
|
target: darwin-arm64
|
|
- os: macos-15-intel
|
|
target: darwin-x64
|
|
- os: windows-2025-vs2026
|
|
target: win32-x64
|
|
- os: ubuntu-24.04
|
|
target: linux-x64
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v6
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: .nvmrc
|
|
cache: 'pnpm'
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build Kimi web assets
|
|
# The SEA blob embeds apps/kimi-code/dist-web; build the web app and
|
|
# stage its assets before producing the native executable.
|
|
# KIMI_WEB_DESKTOP=1 bakes the internal-build banner into the web bundle
|
|
# (see apps/kimi-web/src/components/InternalBuildBanner.vue); only the
|
|
# desktop sets this flag, so the CLI `kimi web` stays banner-free.
|
|
env:
|
|
KIMI_WEB_DESKTOP: '1'
|
|
run: |
|
|
pnpm --filter @moonshot-ai/kimi-web run build
|
|
node apps/kimi-code/scripts/copy-web-assets.mjs
|
|
|
|
- name: Build native executable (local profile)
|
|
# The Electron app signs the SEA itself (electron-builder, inside-out),
|
|
# so the native build stays unsigned here.
|
|
run: pnpm --filter @moonshot-ai/kimi-code run build:native:sea
|
|
|
|
- name: Setup macOS keychain (Developer ID)
|
|
if: runner.os == 'macOS' && inputs.sign-macos
|
|
uses: ./.github/actions/macos-keychain-setup
|
|
with:
|
|
certificate-p12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
|
|
certificate-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
|
|
- name: Prepare CSC_NAME for electron-builder (macOS)
|
|
if: runner.os == 'macOS' && inputs.sign-macos
|
|
shell: bash
|
|
run: |
|
|
# electron-builder rejects the "Developer ID Application: " prefix in
|
|
# CSC_NAME; strip it so the certificate matches by team name + ID.
|
|
name="${APPLE_SIGNING_IDENTITY}"
|
|
name="${name#Developer ID Application: }"
|
|
echo "CSC_NAME=$name" >> "$GITHUB_ENV"
|
|
|
|
- name: Prepare notarization API key (macOS)
|
|
if: runner.os == 'macOS' && inputs.sign-macos
|
|
shell: bash
|
|
env:
|
|
APPLE_NOTARIZATION_KEY_P8: ${{ secrets.APPLE_NOTARIZATION_KEY_P8 }}
|
|
run: |
|
|
set -euo pipefail
|
|
key_path="$RUNNER_TEMP/notary-AuthKey.p8"
|
|
printf '%s' "$APPLE_NOTARIZATION_KEY_P8" | base64 -d > "$key_path"
|
|
echo "APPLE_API_KEY=$key_path" >> "$GITHUB_ENV"
|
|
|
|
- name: Build & package desktop app
|
|
shell: bash
|
|
env:
|
|
# macOS signing is driven by env: when sign-macos, electron-builder
|
|
# signs with the keychain's Developer ID and notarizes via the notary
|
|
# API key; otherwise it builds unsigned.
|
|
CSC_IDENTITY_AUTO_DISCOVERY: ${{ (runner.os == 'macOS' && inputs.sign-macos) && 'true' || 'false' }}
|
|
CSC_KEYCHAIN: ${{ env.APPLE_KEYCHAIN_PATH }}
|
|
KIMI_DESKTOP_NOTARIZE: ${{ (runner.os == 'macOS' && inputs.sign-macos) && 'true' || 'false' }}
|
|
APPLE_API_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
|
APPLE_API_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }}
|
|
run: pnpm --filter @moonshot-ai/kimi-desktop run dist
|
|
|
|
- name: Cleanup macOS keychain
|
|
if: always() && runner.os == 'macOS' && inputs.sign-macos
|
|
uses: ./.github/actions/macos-keychain-cleanup
|
|
|
|
- name: Upload installers
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: ${{ inputs.upload-artifact-prefix }}-${{ matrix.target }}
|
|
retention-days: ${{ inputs.retention-days }}
|
|
path: |
|
|
apps/kimi-desktop/dist-app/*.dmg
|
|
apps/kimi-desktop/dist-app/*.zip
|
|
apps/kimi-desktop/dist-app/*.exe
|
|
apps/kimi-desktop/dist-app/*.AppImage
|
|
apps/kimi-desktop/dist-app/*.deb
|
|
if-no-files-found: ignore
|