Skip to content

Commit 4aaef56

Browse files
PerishCodemrcfpsmRcfps
authored
build(desktop): stabilize Windows dev and distribution workflows (#449)
* fix(desktop): make local startup work on Windows * fix(desktop): sanitize persisted startup logs * test(desktop): add Feishu websocket smoke harness * fix(smoke): improve Feishu websocket diagnostics * build(desktop): add Windows smoke distribution flow * build(desktop): align Windows sidecar archives with zip flow * build(desktop): align Windows packaging with NSIS defaults * build(desktop): refine Windows distribution commands * build(desktop): improve Windows installer UX Switch the NSIS flow to an assisted installer so Windows install and uninstall are visible and data cleanup can be opted into without silent surprises. Restore executable resource editing and use tombstone-based app-data cleanup so shortcuts show the Nexu icon and uninstall stays fast without flashing a console window. * fix(desktop): stabilize Windows dist and runtime install (#538) * build(desktop): skip exe editing for unsigned Windows dist * fix(openclaw-runtime): stabilize Windows postinstall Keep the full install path available for debugging while making pruned installs skip Windows-native optional dependencies that break postinstall flows. * fix(desktop): align dev health check with runtime state * fix(openclaw-runtime): refresh cache on installer changes * build(desktop): add windows CI coverage * fix(desktop): avoid sidecar copy symlink loops on windows * fix(desktop): clean runtime plugin self-links on windows * build(desktop): scope windows CI to build validation * fix(desktop): restore mac dist executable discovery --------- Co-authored-by: mRcfps <1402401442@qq.com> * build(desktop): stabilize Windows startup and shell polish * fix(web): refine Windows sidebar toggle layout * fix(desktop): harden Windows packaged runtime startup * feat: streamline desktop local dev workflow (#640) * feat: add local dev supervisor workflow * feat: refine local dev workflow and desktop runtime scaffolding * docs: add dev workflow faq * fix: remove nested controller tsx watcher * refactor: share ensure guards across dev process helpers * chore: remove stale task notes * refactor: centralize local dev path resolution * refactor: move dev orchestration into scripts/dev Keep @nexu/dev-utils focused on atomic helpers so service-level controller and web flows stay easier to reason about and recover. Add lightweight session tracing so leaked dev processes can be correlated and cleaned up without heavy self-healing. * refactor: clarify scripts dev module boundaries * feat: externalize dev runtime ownership * feat: split local dev into explicit service controls * refactor: remove legacy desktop dev launchers * fix: run desktop local dev through the Vite supervisor * fix: harden local dev stack flow * chore: sync workspace lockfiles * fix: restore desktop dev auth session * chore: unify scripts dev logging * chore: stabilize launchd encapsulation and windows desktop smoke flow (#651) * chore: introduce shared desktop lifecycle contract * chore: move desktop platform lifecycle behind adapters * chore: centralize desktop platform compatibility * chore: stage patched OpenClaw runtime for local dev * chore: log staged OpenClaw runtime usage * chore: speed up windows desktop build iteration * chore: disable win executable editing for local builds * chore: ignore local build cache * fix(desktop): support windows openclaw sidecar archives * chore: unify desktop dev launch under scripts/dev (#654) * chore(ci): add windows packaging to desktop dist full * chore(ci): opt desktop dist full into node 24 actions * Revert "chore(ci): opt desktop dist full into node 24 actions" This reverts commit b19336e. * fix(desktop): harden windows packaging and installer flow * chore: remove task handoff note * chore: align desktop tests with platform runtime changes * chore: fix linux desktop test platform mocks * chore: stabilize dev check service supervision * chore: fix packaged launchd path test platform setup * fix(desktop): preserve explicit dev runtime env overrides * fix(dev): preserve openclaw supervisor pid lock * chore(ci): track scripts dev changes in desktop dev checks * chore(ci): support manual desktop workflow dispatch * fix(dev): treat active openclaw port as running * fix(dev): align desktop runtime ports with CI contract * fix(dev): wait for openclaw gateway before controller start * chore(ci): capture dev logs and read desktop pid lock * fix(dev): wait for openclaw health before reporting ready * fix(controller): debounce sync on all skill dir events * fix(dev): derive openclaw status from runtime health * fix(dev): disable bonjour in desktop CI smoke * fix(desktop): harden Windows packaging and cleanup flows * fix(dev): stabilize Windows desktop dev lifecycle * fix(dev): allow overriding desktop dev ports * fix(dev): require openclaw readiness for running status * fix(dev): expose builtin openclaw extensions in local controller * fix(desktop): stabilize windows packaging workflows * fix: restore windows dev UI and openclaw startup compatibility * fix(desktop): clear stale startup errors after runtime recovery * fix(desktop): use packaged openclaw sidecars in windows builds * chore: refresh lockfile for desktop dependency changes * fix: make nexu runtime model plugin reload state by content --------- Co-authored-by: Marc Chan <mrc@powerformer.com> Co-authored-by: mRcfps <1402401442@qq.com>
1 parent cfa5e00 commit 4aaef56

File tree

175 files changed

+13769
-1621
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

175 files changed

+13769
-1621
lines changed

.gitattributes

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
* text=auto eol=lf
2+
3+
*.bat text eol=crlf
4+
*.cmd text eol=crlf
5+
*.ps1 text eol=crlf

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
pull_request:
55
paths-ignore:
66
- "docs/**"
7+
workflow_dispatch:
78
push:
89
branches:
910
- main

.github/workflows/desktop-ci-dev.yml

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- 'openclaw-runtime/**'
1111
- 'tests/desktop/**'
1212
- 'scripts/dev-launchd.sh'
13+
- 'scripts/dev/**'
1314
- 'scripts/desktop-check-dev.sh'
1415
- 'scripts/desktop-stop-smoke.sh'
1516
- 'scripts/desktop-ci-check.mjs'
@@ -23,6 +24,7 @@ on:
2324
- 'pnpm-lock.yaml'
2425
- 'pnpm-workspace.yaml'
2526
- '.github/workflows/desktop-ci-dev.yml'
27+
workflow_dispatch:
2628
push:
2729
branches:
2830
- main
@@ -34,6 +36,7 @@ on:
3436
- 'openclaw-runtime/**'
3537
- 'tests/desktop/**'
3638
- 'scripts/dev-launchd.sh'
39+
- 'scripts/dev/**'
3740
- 'scripts/desktop-check-dev.sh'
3841
- 'scripts/desktop-stop-smoke.sh'
3942
- 'scripts/desktop-ci-check.mjs'
@@ -57,7 +60,16 @@ concurrency:
5760

5861
jobs:
5962
desktop-ci:
60-
runs-on: macos-14
63+
strategy:
64+
fail-fast: false
65+
matrix:
66+
include:
67+
- os: macos
68+
runs_on: macos-14
69+
- os: windows
70+
runs_on: windows-latest
71+
72+
runs-on: ${{ matrix.runs_on }}
6173
timeout-minutes: 45
6274

6375
steps:
@@ -101,17 +113,19 @@ jobs:
101113
run: pnpm install --frozen-lockfile
102114

103115
- name: Install tmux
116+
if: matrix.os == 'macos'
104117
shell: bash
105118
run: |
106119
set -euo pipefail
107120
brew install tmux
108121
109122
- name: Show desktop toolchain versions
110-
shell: bash
123+
shell: pwsh
111124
run: |
112-
set -euo pipefail
113125
pnpm exec electron --version
114-
tmux -V
126+
if ("${{ matrix.os }}" -eq "macos") {
127+
tmux -V
128+
}
115129
116130
- name: Build all
117131
run: pnpm build
@@ -124,19 +138,37 @@ jobs:
124138
run: bash scripts/launchd-lifecycle-e2e.sh
125139

126140
- name: Verify desktop runtime unit health
141+
if: matrix.os == 'macos'
127142
env:
128143
NEXU_DESKTOP_CHECK_CAPTURE_DIR: ${{ runner.temp }}/desktop-ci
129144
NEXU_USE_LAUNCHD: "0"
130145
run: pnpm check:dev
131146

147+
- name: Verify Windows desktop build pipeline
148+
if: matrix.os == 'windows'
149+
run: pnpm --filter @nexu/desktop build
150+
132151
- name: Capture desktop logs
133152
if: always()
153+
shell: pwsh
154+
run: |
155+
$captureDir = Join-Path $env:RUNNER_TEMP "desktop-ci"
156+
New-Item -ItemType Directory -Force -Path $captureDir | Out-Null
157+
if (Test-Path ".tmp/dev/logs") {
158+
Copy-Item ".tmp/dev/logs" (Join-Path $captureDir "repo-logs") -Recurse -Force
159+
}
160+
if (Test-Path ".tmp/desktop/electron/logs") {
161+
Copy-Item ".tmp/desktop/electron/logs" (Join-Path $captureDir "electron-logs") -Recurse -Force
162+
}
163+
164+
- name: Capture tmux log
165+
if: always() && matrix.os == 'macos'
134166
shell: bash
135167
run: |
136168
set -euo pipefail
137169
mkdir -p "$RUNNER_TEMP/desktop-ci"
138-
if [ -d .tmp/logs ]; then
139-
cp -R .tmp/logs "$RUNNER_TEMP/desktop-ci/repo-logs"
170+
if [ -d .tmp/dev/logs ]; then
171+
cp -R .tmp/dev/logs "$RUNNER_TEMP/desktop-ci/repo-logs"
140172
fi
141173
if [ -d .tmp/desktop/electron/logs ]; then
142174
cp -R .tmp/desktop/electron/logs "$RUNNER_TEMP/desktop-ci/electron-logs"
@@ -149,7 +181,7 @@ jobs:
149181
if: always()
150182
uses: actions/upload-artifact@v4
151183
with:
152-
name: desktop-ci-logs
184+
name: desktop-ci-logs-${{ matrix.os }}
153185
path: ${{ runner.temp }}/desktop-ci
154186
if-no-files-found: warn
155187
retention-days: 7

.github/workflows/desktop-ci-dist-full.yml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ on:
2626
- "scripts/postinstall.mjs"
2727
- ".github/workflows/desktop-ci-dist-full.yml"
2828
workflow_dispatch:
29+
inputs:
30+
auto_update_enabled:
31+
description: "Enable auto-update in CI build artifacts"
32+
required: false
33+
default: "false"
34+
type: choice
35+
options:
36+
- "false"
37+
- "true"
2938

3039
permissions:
3140
contents: read
@@ -168,6 +177,7 @@ jobs:
168177
NEXU_DESKTOP_TARGET_ARCH: ${{ matrix.arch }}
169178
NEXU_DESKTOP_USE_EXISTING_BUILDS: "1"
170179
NEXU_DESKTOP_USE_EXISTING_RUNTIME_INSTALL: "1"
180+
NEXU_DESKTOP_AUTO_UPDATE_ENABLED: ${{ github.event_name == 'workflow_dispatch' && inputs.auto_update_enabled || 'false' }}
171181
run: pnpm dist:mac:unsigned
172182

173183
- name: Set packaged app paths
@@ -284,3 +294,117 @@ jobs:
284294
path: ${{ runner.temp }}/desktop-ci
285295
if-no-files-found: warn
286296
retention-days: 3
297+
298+
package-windows:
299+
runs-on: windows-latest
300+
timeout-minutes: 45
301+
302+
steps:
303+
- name: Checkout
304+
uses: actions/checkout@v4
305+
306+
- name: Setup pnpm
307+
uses: pnpm/action-setup@v4
308+
with:
309+
version: 10.26.0
310+
311+
- name: Setup Node.js
312+
uses: actions/setup-node@v4
313+
with:
314+
node-version: 24
315+
cache: pnpm
316+
cache-dependency-path: pnpm-lock.yaml
317+
318+
- name: Restore npm cache for runtime installs
319+
uses: actions/cache@v4
320+
with:
321+
path: ~\AppData\Local\npm-cache
322+
key: desktop-npm-cache-${{ runner.os }}-x64-${{ hashFiles('openclaw-runtime/package-lock.json', 'apps/controller/static/runtime-plugins/openclaw-weixin/package-lock.json') }}
323+
restore-keys: |
324+
desktop-npm-cache-${{ runner.os }}-x64-
325+
desktop-npm-cache-${{ runner.os }}-
326+
327+
- name: Restore Electron build caches
328+
uses: actions/cache@v4
329+
with:
330+
path: |
331+
~\AppData\Local\electron\Cache
332+
~\AppData\Local\electron-builder\Cache
333+
apps/desktop/.cache
334+
key: desktop-electron-cache-${{ runner.os }}-x64-${{ hashFiles('pnpm-lock.yaml', 'apps/desktop/package.json') }}
335+
restore-keys: |
336+
desktop-electron-cache-${{ runner.os }}-x64-
337+
desktop-electron-cache-${{ runner.os }}-
338+
339+
- name: Install dependencies
340+
run: pnpm install --frozen-lockfile
341+
342+
- name: Show desktop toolchain versions
343+
shell: pwsh
344+
run: pnpm exec electron --version
345+
346+
- name: Build workspace artifacts
347+
run: pnpm build
348+
349+
- name: Build unsigned Windows desktop bundle
350+
env:
351+
NEXU_DESKTOP_AUTO_UPDATE_ENABLED: ${{ github.event_name == 'workflow_dispatch' && inputs.auto_update_enabled || 'false' }}
352+
run: pnpm --filter @nexu/desktop dist:win
353+
354+
- name: Verify packaged Windows artifacts
355+
shell: pwsh
356+
run: |
357+
$releaseDir = Join-Path $PWD "apps/desktop/release"
358+
$installerArtifacts = Get-ChildItem -Path $releaseDir -Filter "*.exe" -File
359+
if ($installerArtifacts.Count -eq 0) {
360+
Write-Error "No Windows installer artifact was produced"
361+
}
362+
363+
$unpackedExecutable = Join-Path $releaseDir "win-unpacked/Nexu.exe"
364+
if (-not (Test-Path $unpackedExecutable)) {
365+
Write-Error "Missing unpacked Windows app executable: $unpackedExecutable"
366+
}
367+
368+
$archiveMetadata = Join-Path $PWD "apps/desktop/.dist-runtime/openclaw/archive.json"
369+
if (-not (Test-Path $archiveMetadata)) {
370+
Write-Error "Missing OpenClaw archive metadata: $archiveMetadata"
371+
}
372+
373+
Write-Host "Built Windows artifacts:"
374+
$installerArtifacts | ForEach-Object { Write-Host " - $($_.FullName)" }
375+
Write-Host " - $unpackedExecutable"
376+
Write-Host " - $archiveMetadata"
377+
378+
- name: Upload Windows build artifacts
379+
if: success()
380+
uses: actions/upload-artifact@v4
381+
with:
382+
name: desktop-ci-dist-win-x64
383+
path: |
384+
apps/desktop/release/*.exe
385+
apps/desktop/release/win-unpacked/**
386+
if-no-files-found: error
387+
retention-days: 3
388+
389+
- name: Capture Windows build logs
390+
if: always()
391+
shell: pwsh
392+
run: |
393+
$captureDir = Join-Path $env:RUNNER_TEMP "desktop-ci-win"
394+
New-Item -ItemType Directory -Force -Path $captureDir | Out-Null
395+
396+
if (Test-Path "apps/desktop/.dist-runtime") {
397+
Copy-Item "apps/desktop/.dist-runtime" (Join-Path $captureDir "dist-runtime") -Recurse -Force
398+
}
399+
if (Test-Path ".tmp") {
400+
Copy-Item ".tmp" (Join-Path $captureDir "repo-tmp") -Recurse -Force
401+
}
402+
403+
- name: Upload Windows build logs
404+
if: always()
405+
uses: actions/upload-artifact@v4
406+
with:
407+
name: desktop-ci-logs-win-x64
408+
path: ${{ runner.temp }}/desktop-ci-win
409+
if-no-files-found: warn
410+
retention-days: 3

.github/workflows/desktop-ci-dist-lite.yml

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,27 @@ on:
1919
- "pnpm-workspace.yaml"
2020
- ".github/workflows/desktop-ci-dist-lite.yml"
2121
- ".github/workflows/desktop-ci-dist-full.yml"
22+
workflow_dispatch:
23+
push:
24+
branches:
25+
- main
26+
paths:
27+
- "apps/desktop/**"
28+
- "apps/controller/**"
29+
- "apps/web/**"
30+
- "packages/shared/**"
31+
- "openclaw-runtime/**"
32+
- "openclaw-runtime-patches/**"
33+
- "scripts/desktop-check-dist.sh"
34+
- "scripts/desktop-verify-extracted-runner.sh"
35+
- "scripts/desktop-ci-check.mjs"
36+
- "scripts/postinstall.mjs"
37+
- ".npmrc"
38+
- "package.json"
39+
- "pnpm-lock.yaml"
40+
- "pnpm-workspace.yaml"
41+
- ".github/workflows/desktop-ci-dist-lite.yml"
42+
- ".github/workflows/desktop-ci-dist-full.yml"
2243

2344
permissions:
2445
contents: read
@@ -77,61 +98,46 @@ jobs:
7798
run: pnpm install --frozen-lockfile
7899

79100
- name: Show desktop toolchain versions
80-
shell: bash
81-
run: |
82-
set -euo pipefail
83-
pnpm exec electron --version
101+
shell: pwsh
102+
run: pnpm exec electron --version
84103

85-
- name: Build unsigned macOS desktop bundle
104+
- name: Build unsigned desktop bundle
86105
env:
87106
NEXU_DESKTOP_TARGET_ARCH: arm64
88107
NEXU_DESKTOP_USE_EXISTING_RUNTIME_INSTALL: "1"
89108
run: pnpm dist:mac:unsigned
90109

91110
- name: Set packaged app paths
92-
shell: bash
111+
shell: pwsh
93112
run: |
94-
set -euo pipefail
95-
shopt -s nullglob
96-
97-
runner_home="$HOME"
98-
packaged_home="$RUNNER_TEMP/desktop-home"
99-
packaged_user_data_dir="$packaged_home/Library/Application Support/@nexu/desktop"
100-
packaged_logs_dir="$packaged_user_data_dir/logs"
101-
packaged_runtime_logs_dir="$packaged_logs_dir/runtime-units"
102-
default_user_data_dir="$runner_home/Library/Application Support/@nexu/desktop"
103-
default_logs_dir="$default_user_data_dir/logs"
104-
default_runtime_logs_dir="$default_logs_dir/runtime-units"
105-
packaged_apps=(apps/desktop/release/mac*/Nexu.app)
106-
107-
if [ "${#packaged_apps[@]}" -eq 0 ]; then
108-
echo "No packaged app bundle found under apps/desktop/release/mac*" >&2
109-
exit 1
110-
fi
111-
112-
packaged_app="${packaged_apps[0]}"
113-
packaged_executable="$packaged_app/Contents/MacOS/Nexu"
114-
115-
mkdir -p "$RUNNER_TEMP/desktop-ci" "$packaged_home" "$RUNNER_TEMP/desktop-tmp"
116-
117-
{
118-
echo "PACKAGED_HOME=$packaged_home"
119-
echo "PACKAGED_LOGS_DIR=$packaged_logs_dir"
120-
echo "PACKAGED_USER_DATA_DIR=$packaged_user_data_dir"
121-
echo "PACKAGED_RUNTIME_LOGS_DIR=$packaged_runtime_logs_dir"
122-
echo "DEFAULT_LOGS_DIR=$default_logs_dir"
123-
echo "DEFAULT_USER_DATA_DIR=$default_user_data_dir"
124-
echo "DEFAULT_RUNTIME_LOGS_DIR=$default_runtime_logs_dir"
125-
echo "PACKAGED_APP=$packaged_app"
126-
echo "PACKAGED_EXECUTABLE=$packaged_executable"
127-
} >> "$GITHUB_ENV"
113+
$captureDir = Join-Path $env:RUNNER_TEMP "desktop-ci"
114+
$packagedHome = Join-Path $env:RUNNER_TEMP "desktop-home"
115+
$tmpDir = Join-Path $env:RUNNER_TEMP "desktop-tmp"
116+
New-Item -ItemType Directory -Force -Path $captureDir, $packagedHome, $tmpDir | Out-Null
117+
118+
$packagedUserDataDir = Join-Path $packagedHome "Library/Application Support/@nexu/desktop"
119+
$packagedApp = "apps/desktop/release/mac-arm64/Nexu.app"
120+
$packagedExecutable = "$packagedApp/Contents/MacOS/Nexu"
121+
122+
$packagedLogsDir = Join-Path $packagedUserDataDir "logs"
123+
$packagedRuntimeLogsDir = Join-Path $packagedLogsDir "runtime-units"
124+
125+
@(
126+
"PACKAGED_HOME=$packagedHome",
127+
"PACKAGED_LOGS_DIR=$packagedLogsDir",
128+
"PACKAGED_USER_DATA_DIR=$packagedUserDataDir",
129+
"PACKAGED_RUNTIME_LOGS_DIR=$packagedRuntimeLogsDir",
130+
"DEFAULT_LOGS_DIR=$packagedLogsDir",
131+
"DEFAULT_USER_DATA_DIR=$packagedUserDataDir",
132+
"DEFAULT_RUNTIME_LOGS_DIR=$packagedRuntimeLogsDir",
133+
"PACKAGED_APP=$packagedApp",
134+
"PACKAGED_EXECUTABLE=$packagedExecutable"
135+
) | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
128136
129137
- name: Verify packaged desktop artifacts
130138
shell: bash
131139
run: |
132140
set -euo pipefail
133-
shopt -s nullglob
134-
135141
packaged_apps=(apps/desktop/release/mac*/Nexu.app)
136142
137143
if [ "${#packaged_apps[@]}" -eq 0 ]; then
@@ -144,8 +150,8 @@ jobs:
144150
145151
test -d "$PACKAGED_APP"
146152
test -x "$PACKAGED_EXECUTABLE"
147-
148153
- name: Verify packaged runtime unit health
154+
if: matrix.os == 'macos'
149155
env:
150156
NEXU_DESKTOP_CHECK_CAPTURE_DIR: ${{ runner.temp }}/desktop-ci
151157
NEXU_DESKTOP_CHECK_TMPDIR: ${{ runner.temp }}/desktop-tmp

0 commit comments

Comments
 (0)