cc-haha/.github/workflows/build-desktop-dev.yml
程序员阿江(Relakkes) 47b3cc4d40 Reduce Windows installer confusion and heuristic AV exposure
Windows releases were shipping both NSIS exe and MSI bundles, which made the
release page harder to understand and increased the chance that users would
pick the wrong asset. Restricting Windows output to MSI narrows the installer
surface while the release asset naming now spells out platform, architecture,
and bundle type directly in every published filename.

Constraint: Remote desktop packaging is triggered by GitHub Actions releases, not local uploads
Constraint: Updater metadata must keep latest.json stable for existing clients
Rejected: Keep publishing both NSIS and MSI with better docs | still leaves the higher-risk installer on the release page
Rejected: Rename assets manually after upload | easy to drift from workflow output and updater metadata
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If Windows exe bundles are reintroduced later, reassess SmartScreen and AV impact before publishing them again
Tested: YAML parse for both desktop workflows; git diff --check on modified files; manual review of PowerShell changes
Not-tested: End-to-end GitHub Actions release run; PowerShell parser validation on a Windows host
2026-04-21 18:26:42 +08:00

246 lines
10 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Build Desktop (Dev)
# 开发阶段构建 — 不创建 Release只上传 Artifacts 供下载测试
on:
workflow_dispatch:
inputs:
platforms:
description: 'Build platforms'
required: true
default: 'all'
type: choice
options:
- all
- macos-arm64
- macos-x64
- windows-x64
- linux-x64
- linux-arm64
permissions:
contents: read
concurrency:
group: build-desktop-dev-${{ github.ref }}
cancel-in-progress: true
jobs:
# ── 动态生成构建矩阵 ──────────────────────────────────────
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: |
ALL='[{"platform":"macos-latest","rust_target":"aarch64-apple-darwin","tauri_args":"--target aarch64-apple-darwin","bundles":"app,dmg","label":"macOS-ARM64","artifact_name":"macos-arm64","asset_platform":"macos","asset_arch":"arm64"},{"platform":"macos-latest","rust_target":"x86_64-apple-darwin","tauri_args":"--target x86_64-apple-darwin","bundles":"app,dmg","label":"macOS-x64","artifact_name":"macos-x64","asset_platform":"macos","asset_arch":"x64"},{"platform":"windows-latest","rust_target":"x86_64-pc-windows-msvc","tauri_args":"","bundles":"msi","label":"Windows-x64","artifact_name":"windows-x64","asset_platform":"windows","asset_arch":"x64"},{"platform":"ubuntu-22.04","rust_target":"x86_64-unknown-linux-gnu","tauri_args":"","bundles":"deb","label":"Linux-x64","artifact_name":"linux-x64","asset_platform":"linux","asset_arch":"x64"},{"platform":"ubuntu-22.04-arm","rust_target":"aarch64-unknown-linux-gnu","tauri_args":"","bundles":"deb","label":"Linux-ARM64","artifact_name":"linux-arm64","asset_platform":"linux","asset_arch":"arm64"}]'
SELECTED="${{ inputs.platforms }}"
if [ "$SELECTED" = "all" ]; then
MATRIX=$(echo "$ALL" | jq -c '{include: .}')
else
MATRIX=$(echo "$ALL" | jq -c --arg sel "$SELECTED" '{include: [.[] | select(
($sel == "macos-arm64" and .label == "macOS-ARM64") or
($sel == "macos-x64" and .label == "macOS-x64") or
($sel == "windows-x64" and .label == "Windows-x64") or
($sel == "linux-x64" and .label == "Linux-x64") or
($sel == "linux-arm64" and .label == "Linux-ARM64")
)]}')
fi
echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT"
# ── 构建 ────────────────────────────────────────────────────
build:
needs: prepare
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
runs-on: ${{ matrix.platform }}
name: Build (${{ matrix.label }})
steps:
- name: Checkout
uses: actions/checkout@v4
# ── 读取版本号 ───────────────────────────────────────────
- name: Read version
id: version
shell: bash
run: |
VERSION=$(jq -r '.version' desktop/src-tauri/tauri.conf.json)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
# ── 系统依赖 (Linux) ─────────────────────────────────────
# libfuse2 是 AppImage 运行时依赖linuxdeploy 工具链本身是 AppImage 格式,
# 运行时需要 libfuse2Ubuntu 22.04 默认未安装。
- name: Install Linux dependencies
if: contains(matrix.platform, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential curl wget file \
libxdo-dev libssl-dev \
libwebkit2gtk-4.1-dev \
libayatana-appindicator3-dev \
librsvg2-dev patchelf \
libfuse2
# ── Bun ──────────────────────────────────────────────────
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
# ── Node.js ──────────────────────────────────────────────
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
# ── Rust ─────────────────────────────────────────────────
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: 'desktop/src-tauri -> target'
shared-key: ${{ matrix.rust_target }}
# ── 安装依赖 ─────────────────────────────────────────────
- name: Install root dependencies
run: bun install
- name: Install desktop dependencies
working-directory: desktop
run: bun install
- name: Install adapter dependencies
working-directory: adapters
run: bun install
# ── 构建 sidecars ────────────────────────────────────────
- name: Build sidecars
working-directory: desktop
env:
TAURI_ENV_TARGET_TRIPLE: ${{ matrix.rust_target }}
run: bun run build:sidecars
# ── 构建 Tauri (无签名、无 updater) ──────────────────────
- name: Build Tauri app
working-directory: desktop
env:
TAURI_ENV_TARGET_TRIPLE: ${{ matrix.rust_target }}
run: |
# 开发构建: 禁用 updater artifacts (不需要签名密钥)
echo '{"bundle":{"createUpdaterArtifacts":false}}' > /tmp/dev-build.json
ARGS=(bunx tauri build --bundles ${{ matrix.bundles }} --ci --config /tmp/dev-build.json)
if [ -n "${{ matrix.tauri_args }}" ]; then
ARGS+=(${{ matrix.tauri_args }})
fi
"${ARGS[@]}"
shell: bash
# ── 收集产物 ─────────────────────────────────────────────
- name: Collect artifacts
id: collect
shell: bash
run: |
BUNDLE_DIR="desktop/src-tauri/target/${{ matrix.rust_target }}/release/bundle"
FALLBACK_DIR="desktop/src-tauri/target/release/bundle"
# 优先使用带 target 的路径
if [ -d "$BUNDLE_DIR" ]; then
SEARCH_DIR="$BUNDLE_DIR"
else
SEARCH_DIR="$FALLBACK_DIR"
fi
STAGING="desktop/build-artifacts/ci-Claude-Code-Haha-v${{ steps.version.outputs.version }}-${{ matrix.artifact_name }}"
mkdir -p "$STAGING"
echo "Searching for artifacts in: $SEARCH_DIR"
if [ -d "$SEARCH_DIR" ]; then
find "$SEARCH_DIR" \
\( -type f \( \
-name "*.dmg" -o -name "*.msi" -o \
-name "*.deb" -o -name "*.AppImage" -o -name "*.zip" \
\) \) -o \
\( -type d -name "*.app" \) | while read -r f; do
base="$(basename "$f")"
bundle="artifact"
ext=""
case "$base" in
*.app)
bundle="app"
ext=".app"
;;
*.dmg)
bundle="dmg"
ext=".dmg"
;;
*.msi)
bundle="msi"
ext=".msi"
;;
*.deb)
bundle="deb"
ext=".deb"
;;
*.AppImage)
bundle="appimage"
ext=".AppImage"
;;
*.zip)
bundle="zip"
ext=".zip"
;;
*)
ext=""
;;
esac
target="Claude-Code-Haha_${{ steps.version.outputs.version }}_${{ matrix.asset_platform }}_${{ matrix.asset_arch }}_${bundle}${ext}"
echo " Copying: ${base} -> ${target}"
cp -R "$f" "$STAGING/$target"
done
fi
echo "staging_dir=$STAGING" >> "$GITHUB_OUTPUT"
echo "=== Collected artifacts ==="
ls -lh "$STAGING/" 2>/dev/null || echo "(empty)"
# ── 上传为 GitHub Artifact ───────────────────────────────
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: Claude-Code-Haha-v${{ steps.version.outputs.version }}-${{ matrix.artifact_name }}
path: ${{ steps.collect.outputs.staging_dir }}
retention-days: 7
if-no-files-found: warn
# ── 构建完成汇总 ────────────────────────────────────────────
summary:
needs: build
runs-on: ubuntu-latest
if: always()
steps:
- name: Build summary
run: |
echo "## Desktop Dev Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Platform | Status |" >> $GITHUB_STEP_SUMMARY
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
echo "Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "📦 Artifacts are available for download from the **Artifacts** section above." >> $GITHUB_STEP_SUMMARY
echo "Artifacts will be retained for **7 days**." >> $GITHUB_STEP_SUMMARY