mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-18 13:23:33 +08:00
fix: make local desktop builds reflect current UI state
The desktop test package was able to reuse stale Tauri target output even after the frontend and sidecar were rebuilt, which made UI changes look missing after a build. The local macOS build script now clears that cache by default while retaining an opt-in incremental path. The project selector also no longer repeats the active branch because branch and worktree are now first-class launch controls beside it. Constraint: Local macOS test packages must prioritize freshness over incremental build speed Rejected: Keep branch text in the project chip | duplicated the dedicated branch selector and made the launch row harder to scan Confidence: high Scope-risk: narrow Directive: Keep branch selection behavior in RepositoryLaunchControls; DirectoryPicker should only identify the project Tested: cd desktop && bun run test -- DirectoryPicker.test.tsx Tested: cd desktop && bun run lint Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh Tested: Opened built app and confirmed sidecar /health returned ok
This commit is contained in:
parent
7ae885a114
commit
a340e41046
@ -23,6 +23,10 @@ Environment:
|
||||
SKIP_INSTALL=1 Skip `bun install` in the repo root and desktop app.
|
||||
SIGN_BUILD=1 Remove the default `--no-sign` flag and allow signed builds.
|
||||
OPEN_OUTPUT=1 Open the canonical artifact output directory in Finder after a successful build.
|
||||
PRESERVE_TAURI_TARGET=1
|
||||
Keep Tauri/Rust target cache for a faster incremental build.
|
||||
By default this script removes the macOS target cache so
|
||||
packaged WebView assets cannot be silently reused.
|
||||
|
||||
Examples:
|
||||
./desktop/scripts/build-macos-arm64.sh
|
||||
@ -62,27 +66,47 @@ if [[ "${SKIP_INSTALL:-0}" != "1" ]]; then
|
||||
fi
|
||||
|
||||
# ── 清理 + 显式预热前端 / sidecar ────────────────────────────
|
||||
# 之前遇到过"改了 src/ 代码,build 的 .app 里 sidecar 还是旧的"的诡异
|
||||
# case —— 根因是 Bun.build / Tauri bundler 某一层的缓存把旧 sidecar
|
||||
# binary 复用进了新 .app(.app 被删干净了也救不回来,因为 binary 源在
|
||||
# desktop/src-tauri/binaries/)。
|
||||
# 之前遇到过两类"改了源码,build 出来的 .app 还是旧行为"的诡异 case:
|
||||
# 1) Bun.build / Tauri bundler 某一层缓存把旧 sidecar binary 复用进新 .app
|
||||
# 2) Tauri/Rust target 缓存复用旧 claude-code-desktop,导致新 dist 没被嵌进去
|
||||
# 第二类尤其隐蔽: dist 是新的,sidecar 也是新的,但 WebView 运行的还是旧前端。
|
||||
#
|
||||
# 这里做三件事强制 fresh build:
|
||||
# 1) 硬删 sidecar 源 binary + Tauri bundle 目录 + 前端 dist
|
||||
# 默认做四件事强制 fresh build:
|
||||
# 1) 硬删 sidecar 源 binary + Tauri target/bundle 目录 + 前端 dist
|
||||
# 2) 显式跑 bun run build + bun run build:sidecars
|
||||
# 3) tauri build 用 --config 覆盖 beforeBuildCommand 为 true(no-op),
|
||||
# 避免 sidecar 被重复编译浪费 ~10s
|
||||
# 4) 复制到 canonical output 前再次清空输出目录
|
||||
# 任一步失败,整个脚本立即退出(set -e)。
|
||||
echo "[build-macos-arm64] Cleaning stale sidecar binaries and bundle output..."
|
||||
echo "[build-macos-arm64] Cleaning stale sidecar binaries, frontend output, and Tauri bundle cache..."
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/binaries/claude-sidecar-"*
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/bundle"
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/release/bundle"
|
||||
rm -rf "${DESKTOP_DIR}/dist"
|
||||
rm -f "${DESKTOP_DIR}/tsconfig.tsbuildinfo"
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/build/claude-code-desktop-"*
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/.fingerprint/claude-code-desktop-"*
|
||||
rm -f "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/deps/claude_code_desktop-"*
|
||||
rm -f "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/deps/libclaude_code_desktop-"*
|
||||
|
||||
if [[ "${PRESERVE_TAURI_TARGET:-0}" == "1" ]]; then
|
||||
echo "[build-macos-arm64] PRESERVE_TAURI_TARGET=1: keeping Rust dependency cache, clearing app-specific artifacts only..."
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/bundle"
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/release/bundle"
|
||||
rm -f "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/claude-code-desktop"
|
||||
rm -f "${DESKTOP_DIR}/src-tauri/target/release/claude-code-desktop"
|
||||
find "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/build" \
|
||||
-maxdepth 1 -name 'claude-code-desktop-*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/.fingerprint" \
|
||||
-maxdepth 1 -name 'claude-code-desktop-*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}/release/deps" \
|
||||
-maxdepth 1 \( -name 'claude_code_desktop-*' -o -name 'libclaude_code_desktop-*' \) -exec rm -f {} + 2>/dev/null || true
|
||||
else
|
||||
echo "[build-macos-arm64] Removing Tauri target cache for ${TARGET_TRIPLE} to force fresh embedded frontend assets..."
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/${TARGET_TRIPLE}"
|
||||
rm -rf "${DESKTOP_DIR}/src-tauri/target/release/bundle"
|
||||
rm -f "${DESKTOP_DIR}/src-tauri/target/release/claude-code-desktop"
|
||||
find "${DESKTOP_DIR}/src-tauri/target/release/build" \
|
||||
-maxdepth 1 -name 'claude-code-desktop-*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find "${DESKTOP_DIR}/src-tauri/target/release/.fingerprint" \
|
||||
-maxdepth 1 -name 'claude-code-desktop-*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find "${DESKTOP_DIR}/src-tauri/target/release/deps" \
|
||||
-maxdepth 1 \( -name 'claude_code_desktop-*' -o -name 'libclaude_code_desktop-*' \) -exec rm -f {} + 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "[build-macos-arm64] Rebuilding frontend (tsc + vite)..."
|
||||
(cd "${DESKTOP_DIR}" && bun run build)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import '@testing-library/jest-dom'
|
||||
|
||||
@ -15,6 +15,7 @@ vi.mock('../../api/filesystem', () => ({
|
||||
}))
|
||||
|
||||
import { DirectoryPicker } from './DirectoryPicker'
|
||||
import { sessionsApi } from '../../api/sessions'
|
||||
|
||||
describe('DirectoryPicker', () => {
|
||||
it('uses the source repository name as the fallback label for desktop worktree paths', () => {
|
||||
@ -28,4 +29,32 @@ describe('DirectoryPicker', () => {
|
||||
expect(screen.getByRole('button')).toHaveTextContent('checkout')
|
||||
expect(screen.getByRole('button')).not.toHaveTextContent('desktop-feature-rail-12345678')
|
||||
})
|
||||
|
||||
it('does not duplicate the branch in the selected project chip', async () => {
|
||||
vi.mocked(sessionsApi.getRecentProjects).mockResolvedValue({
|
||||
projects: [{
|
||||
projectPath: '/workspace/project',
|
||||
realPath: '/workspace/project',
|
||||
projectName: 'project',
|
||||
repoName: 'NanmiCoder/OpenCutSkill',
|
||||
branch: 'main',
|
||||
isGit: true,
|
||||
modifiedAt: '2026-05-07T00:00:00.000Z',
|
||||
sessionCount: 1,
|
||||
}],
|
||||
})
|
||||
|
||||
render(
|
||||
<DirectoryPicker
|
||||
value="/workspace/project"
|
||||
onChange={vi.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button'))
|
||||
|
||||
const trigger = await waitFor(() => screen.getAllByRole('button', { name: /NanmiCoder\/OpenCutSkill/ })[0])
|
||||
expect(trigger).toHaveTextContent('NanmiCoder/OpenCutSkill')
|
||||
expect(trigger).not.toHaveTextContent('main')
|
||||
})
|
||||
})
|
||||
|
||||
@ -164,15 +164,6 @@ export function DirectoryPicker({ value, onChange }: Props) {
|
||||
<span className="font-medium text-[var(--color-text-primary)]">
|
||||
{selectedProject?.repoName || selectedProject?.projectName || projectNameFromPath(value)}
|
||||
</span>
|
||||
{selectedProject?.branch && (
|
||||
<>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className="text-[var(--color-text-tertiary)]">
|
||||
<circle cx="18" cy="18" r="3" /><circle cx="6" cy="6" r="3" />
|
||||
<path d="M13 6h3a2 2 0 0 1 2 2v7" /><line x1="6" y1="9" x2="6" y2="21" />
|
||||
</svg>
|
||||
<span className="text-[var(--color-text-tertiary)]">{selectedProject.branch}</span>
|
||||
</>
|
||||
)}
|
||||
<span className="material-symbols-outlined text-[12px] text-[var(--color-text-tertiary)]">expand_more</span>
|
||||
</button>
|
||||
) : (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user