Skip to content

Commit 64fb0fb

Browse files
PerishCodemrcfpsmRcfps
authored
chore: align windows desktop delivery with mainline (#949)
* 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 * chore: extract openclaw runtime boundary helpers * chore: consolidate openclaw runtime integration boundary * chore: route windows packaging through scripts/pkg Move the root Windows packaging entrypoints onto scripts/pkg and add shared packaging/platform helper packages so the packaging path is easier to reuse and evolve. * fix: restore Windows packaged startup path Pass the managed Windows controller the Electron runner and add targeted packaging/startup diagnostics so fresh packaged builds use the correct OpenClaw launch contract. Remove the stale root Windows dist wrapper so future validation follows the real desktop packaging entrypoints. * fix: enforce exe-relative Windows runtime packaging Require packaged Windows builds to resolve OpenClaw from the current exe resources, fail fast when the packaged runtime is incomplete, and stop reusing stale Windows dist artifacts during validation. Keep the sidecar unpacked for Windows builds so portable validation can move through fast 7z-based transfers instead of unreliable copy/install paths. * fix: speed up windows custom installer extraction * fix: add windows nightly update redirect flow * fix: converge windows packaging on dist:win * fix: guard windows nightly cache purge secrets * fix: skip windows nightly purge when secrets are missing * fix: align qqbot runtime mapping and controller tests * chore: align windows beta and release CI with dist-win * chore: migrate openclaw runtime helpers back to root * chore: narrow windows branch scope to desktop delivery * chore: stabilize desktop workflow version metadata * chore: vendor windows packaging 7zip * test: align launchd runner stamp expectations * chore: format desktop package version script * chore: install nsis in desktop dist full CI * chore: accept unarchived windows sidecar in dist CI * fix: stabilize packaged openclaw mdns hostname * fix: disable openclaw mdns discovery in CI * fix: move openclaw CI discovery config to top level * fix: harden desktop packaged update flows * fix: disable openclaw bonjour in CI --------- Co-authored-by: Marc Chan <mrc@powerformer.com> Co-authored-by: mRcfps <1402401442@qq.com>
1 parent 140831c commit 64fb0fb

Some content is hidden

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

42 files changed

+4852
-1697
lines changed

.github/workflows/desktop-beta.yml

Lines changed: 162 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,169 @@ jobs:
2929
secrets: inherit
3030

3131
package-windows:
32-
name: Windows (placeholder)
32+
needs: build
3333
runs-on: windows-latest
34+
env:
35+
CHANNEL: beta
3436
steps:
35-
- name: Reserve Windows lane
37+
- name: Checkout
38+
uses: actions/checkout@v4
39+
40+
- name: Setup pnpm
41+
uses: pnpm/action-setup@v4
42+
with:
43+
version: 10.26.0
44+
45+
- name: Setup Node.js
46+
uses: actions/setup-node@v4
47+
with:
48+
node-version: 24
49+
cache: pnpm
50+
cache-dependency-path: pnpm-lock.yaml
51+
52+
- name: Install packaging tools
53+
shell: pwsh
54+
run: |
55+
choco install nsis awscli -y --no-progress
56+
57+
- name: Install dependencies
58+
shell: pwsh
59+
run: pnpm install --frozen-lockfile
60+
61+
- name: Resolve build metadata
62+
id: meta
63+
shell: pwsh
64+
run: |
65+
$baseVersion = (node apps/desktop/scripts/desktop-package-version.mjs get).Trim()
66+
$buildDate = Get-Date -Format 'yyyyMMdd'
67+
$shortSha = "${env:GITHUB_SHA}".Substring(0, 7)
68+
$desktopVersion = "$baseVersion-$env:CHANNEL.$buildDate"
69+
node apps/desktop/scripts/desktop-package-version.mjs set "$desktopVersion" | Out-Null
70+
"desktop_version=$desktopVersion" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
71+
"build_date=$buildDate" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
72+
"short_sha=$shortSha" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
73+
74+
- name: Build Windows installer
75+
shell: pwsh
76+
env:
77+
NEXU_CLOUD_URL: https://nexu.io
78+
NEXU_LINK_URL: https://link.nexu.io
79+
NEXU_DESKTOP_UPDATE_CHANNEL: beta
80+
NEXU_DESKTOP_BUILD_SOURCE: beta
81+
NEXU_DESKTOP_BUILD_BRANCH: ${{ github.ref_name }}
82+
NEXU_DESKTOP_BUILD_COMMIT: ${{ github.sha }}
83+
NEXU_UPDATE_FEED_URL: https://desktop-releases.nexu.io/beta/win32/x64/latest-win.json
84+
VITE_POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
85+
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
86+
run: |
87+
$env:NEXU_DESKTOP_BUILD_TIME = (Get-Date).ToUniversalTime().ToString('o')
88+
pnpm --filter @nexu/desktop dist:win
89+
90+
- name: Prepare Windows release artifacts
91+
id: artifacts
92+
shell: pwsh
93+
env:
94+
VERSION: ${{ steps.meta.outputs.desktop_version }}
95+
SHORT_SHA: ${{ steps.meta.outputs.short_sha }}
96+
CHANNEL: beta
97+
BASE_URL: https://desktop-releases.nexu.io/beta/win32/x64
98+
run: |
99+
$artifactVersion = "$env:VERSION.$env:SHORT_SHA"
100+
$releaseDir = "apps/desktop/release"
101+
$channelArtifacts = "apps/desktop/channel-artifacts-win"
102+
New-Item -ItemType Directory -Force -Path $channelArtifacts | Out-Null
103+
Get-ChildItem -Path $channelArtifacts -File -ErrorAction SilentlyContinue | Remove-Item -Force
104+
105+
$sourceInstaller = Join-Path $releaseDir "nexu-setup-$env:VERSION-x64.exe"
106+
if (-not (Test-Path $sourceInstaller)) {
107+
throw "Missing Windows installer: $sourceInstaller"
108+
}
109+
110+
$versionedInstaller = "nexu-setup-$artifactVersion-win-x64.exe"
111+
$latestInstaller = "nexu-latest-$env:CHANNEL-win-x64.exe"
112+
$checksumFile = "desktop-win-x64-sha256.txt"
113+
$manifestFile = "latest-win.json"
114+
115+
Copy-Item $sourceInstaller (Join-Path $channelArtifacts $versionedInstaller)
116+
Copy-Item $sourceInstaller (Join-Path $channelArtifacts $latestInstaller)
117+
118+
$hash = (Get-FileHash -Algorithm SHA256 (Join-Path $channelArtifacts $versionedInstaller)).Hash.ToLowerInvariant()
119+
"$hash $versionedInstaller" | Out-File -FilePath (Join-Path $channelArtifacts $checksumFile) -Encoding ascii
120+
121+
$env:INSTALLER_FILE = (Join-Path $channelArtifacts $latestInstaller)
122+
$env:MANIFEST_OUTPUT = (Join-Path $channelArtifacts $manifestFile)
123+
node apps/desktop/scripts/generate-win-update-manifest.mjs
124+
125+
"versioned_installer=$versionedInstaller" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
126+
"latest_installer=$latestInstaller" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
127+
"checksum_file=$checksumFile" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
128+
"manifest_file=$manifestFile" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
129+
130+
- name: Upload Windows workflow artifact
131+
uses: actions/upload-artifact@v4
132+
with:
133+
name: desktop-beta-win-x64-${{ steps.meta.outputs.build_date }}-${{ steps.meta.outputs.short_sha }}
134+
path: |
135+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.versioned_installer }}
136+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.latest_installer }}
137+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.checksum_file }}
138+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.manifest_file }}
139+
retention-days: 7
140+
if-no-files-found: error
141+
142+
- name: Publish Windows prerelease assets
143+
uses: softprops/action-gh-release@v2
144+
with:
145+
tag_name: desktop-beta
146+
target_commitish: ${{ github.sha }}
147+
name: Nexu Desktop Beta
148+
prerelease: true
149+
draft: false
150+
overwrite_files: true
151+
fail_on_unmatched_files: true
152+
files: |
153+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.versioned_installer }}
154+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.latest_installer }}
155+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.checksum_file }}
156+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.manifest_file }}
157+
158+
- name: Upload Windows artifacts to Cloudflare R2
159+
env:
160+
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
161+
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
162+
AWS_ENDPOINT_URL: https://${{ secrets.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com
163+
AWS_REGION: auto
164+
shell: pwsh
165+
run: |
166+
$prefix = "beta/win32/x64"
167+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.versioned_installer }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.versioned_installer }}" --no-progress
168+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.latest_installer }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.latest_installer }}" --no-progress
169+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.checksum_file }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.checksum_file }}" --no-progress
170+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.manifest_file }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.manifest_file }}" --no-progress
171+
172+
- name: Purge Windows latest CDN artifacts
173+
env:
174+
CLOUDFLARE_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }}
175+
CLOUDFLARE_PURGE_API_TOKEN: ${{ secrets.CLOUDFLARE_PURGE_API_TOKEN }}
176+
shell: pwsh
177+
run: |
178+
if ([string]::IsNullOrWhiteSpace($env:CLOUDFLARE_ZONE_ID) -or [string]::IsNullOrWhiteSpace($env:CLOUDFLARE_PURGE_API_TOKEN)) {
179+
Write-Host "Skipping Cloudflare purge because required secrets are missing"
180+
exit 0
181+
}
182+
183+
$baseUrl = "https://desktop-releases.nexu.io/beta/win32/x64"
184+
$files = @(
185+
"$baseUrl/${{ steps.artifacts.outputs.latest_installer }}",
186+
"$baseUrl/${{ steps.artifacts.outputs.manifest_file }}"
187+
) | ConvertTo-Json
188+
$payload = @{ files = ($files | ConvertFrom-Json) } | ConvertTo-Json -Depth 5
189+
Invoke-RestMethod -Method Post -Uri "https://api.cloudflare.com/client/v4/zones/$env:CLOUDFLARE_ZONE_ID/purge_cache" -Headers @{ Authorization = "Bearer $env:CLOUDFLARE_PURGE_API_TOKEN" } -ContentType "application/json" -Body $payload | Out-Null
190+
191+
- name: Publish Windows download links
36192
shell: pwsh
37193
run: |
38-
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "## Windows placeholder"
39-
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Channel: beta"
40-
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Status: reserved only; no Windows artifacts are published by this workflow yet"
194+
$baseUrl = "https://desktop-releases.nexu.io/beta/win32/x64"
195+
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "## Windows Beta Downloads"
196+
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Installer: $baseUrl/${{ steps.artifacts.outputs.latest_installer }}"
197+
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Manifest: $baseUrl/${{ steps.artifacts.outputs.manifest_file }}"

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,11 @@ jobs:
339339
- name: Install dependencies
340340
run: pnpm install --frozen-lockfile
341341

342+
- name: Install Windows packaging tools
343+
shell: pwsh
344+
run: |
345+
choco install nsis -y --no-progress
346+
342347
- name: Show desktop toolchain versions
343348
shell: pwsh
344349
run: pnpm exec electron --version
@@ -365,15 +370,26 @@ jobs:
365370
Write-Error "Missing unpacked Windows app executable: $unpackedExecutable"
366371
}
367372
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"
373+
$openclawRuntimeRoot = Join-Path $PWD "apps/desktop/.dist-runtime/openclaw"
374+
$archiveMetadata = Join-Path $openclawRuntimeRoot "archive.json"
375+
$unarchivedPackageJson = Join-Path $openclawRuntimeRoot "package.json"
376+
$unarchivedNodeModules = Join-Path $openclawRuntimeRoot "node_modules"
377+
if (-not (Test-Path $openclawRuntimeRoot)) {
378+
Write-Error "Missing OpenClaw runtime root: $openclawRuntimeRoot"
379+
}
380+
if (-not (Test-Path $archiveMetadata) -and ((-not (Test-Path $unarchivedPackageJson)) -or (-not (Test-Path $unarchivedNodeModules)))) {
381+
Write-Error "Missing OpenClaw runtime payload metadata under: $openclawRuntimeRoot"
371382
}
372383
373384
Write-Host "Built Windows artifacts:"
374385
$installerArtifacts | ForEach-Object { Write-Host " - $($_.FullName)" }
375386
Write-Host " - $unpackedExecutable"
376-
Write-Host " - $archiveMetadata"
387+
if (Test-Path $archiveMetadata) {
388+
Write-Host " - $archiveMetadata"
389+
} else {
390+
Write-Host " - $unarchivedPackageJson"
391+
Write-Host " - $unarchivedNodeModules"
392+
}
377393
378394
- name: Upload Windows build artifacts
379395
if: success()

.github/workflows/desktop-nightly.yml

Lines changed: 161 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,171 @@ jobs:
3030
secrets: inherit
3131

3232
package-windows:
33-
name: Windows (placeholder)
3433
runs-on: windows-latest
34+
env:
35+
CHANNEL: nightly
36+
UPDATE_FEED_ROOT: https://desktop-releases.nexu.io/nightly
3537
steps:
36-
- name: Reserve Windows lane
38+
- name: Checkout
39+
uses: actions/checkout@v4
40+
41+
- name: Setup pnpm
42+
uses: pnpm/action-setup@v4
43+
with:
44+
version: 10.26.0
45+
46+
- name: Setup Node.js
47+
uses: actions/setup-node@v4
48+
with:
49+
node-version: 24
50+
cache: pnpm
51+
cache-dependency-path: pnpm-lock.yaml
52+
53+
- name: Install packaging tools
54+
shell: pwsh
55+
run: |
56+
choco install nsis awscli -y --no-progress
57+
58+
- name: Install dependencies
59+
shell: pwsh
60+
run: pnpm install --frozen-lockfile
61+
62+
- name: Resolve build metadata
63+
id: meta
64+
shell: pwsh
65+
run: |
66+
$baseVersion = (node apps/desktop/scripts/desktop-package-version.mjs get).Trim()
67+
$buildDate = Get-Date -Format 'yyyyMMdd'
68+
$shortSha = "${env:GITHUB_SHA}".Substring(0, 7)
69+
$desktopVersion = "$baseVersion-$env:CHANNEL.$buildDate"
70+
node apps/desktop/scripts/desktop-package-version.mjs set "$desktopVersion" | Out-Null
71+
"desktop_version=$desktopVersion" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
72+
"build_date=$buildDate" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
73+
"short_sha=$shortSha" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
74+
75+
- name: Build Windows installer
76+
shell: pwsh
77+
env:
78+
NEXU_CLOUD_URL: https://nexu.powerformer.net
79+
NEXU_LINK_URL: https://nexu-link.powerformer.net
80+
NEXU_DESKTOP_BUILD_SOURCE: nightly
81+
NEXU_DESKTOP_BUILD_BRANCH: ${{ github.ref_name }}
82+
NEXU_DESKTOP_BUILD_COMMIT: ${{ github.sha }}
83+
NEXU_UPDATE_FEED_URL: https://desktop-releases.nexu.io/nightly/win32/x64/latest-win.json
84+
VITE_POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
85+
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
86+
run: |
87+
$env:NEXU_DESKTOP_BUILD_TIME = (Get-Date).ToUniversalTime().ToString('o')
88+
pnpm --filter @nexu/desktop dist:win
89+
90+
- name: Prepare Windows release artifacts
91+
id: artifacts
92+
shell: pwsh
93+
env:
94+
VERSION: ${{ steps.meta.outputs.desktop_version }}
95+
SHORT_SHA: ${{ steps.meta.outputs.short_sha }}
96+
CHANNEL: nightly
97+
BASE_URL: https://desktop-releases.nexu.io/nightly/win32/x64
98+
run: |
99+
$artifactVersion = "$env:VERSION.$env:SHORT_SHA"
100+
$releaseDir = "apps/desktop/release"
101+
$channelArtifacts = "apps/desktop/channel-artifacts-win"
102+
New-Item -ItemType Directory -Force -Path $channelArtifacts | Out-Null
103+
Get-ChildItem -Path $channelArtifacts -File -ErrorAction SilentlyContinue | Remove-Item -Force
104+
105+
$sourceInstaller = Join-Path $releaseDir "nexu-setup-$env:VERSION-x64.exe"
106+
if (-not (Test-Path $sourceInstaller)) {
107+
throw "Missing Windows installer: $sourceInstaller"
108+
}
109+
110+
$versionedInstaller = "nexu-setup-$artifactVersion-win-x64.exe"
111+
$latestInstaller = "nexu-latest-$env:CHANNEL-win-x64.exe"
112+
$checksumFile = "desktop-win-x64-sha256.txt"
113+
$manifestFile = "latest-win.json"
114+
115+
Copy-Item $sourceInstaller (Join-Path $channelArtifacts $versionedInstaller)
116+
Copy-Item $sourceInstaller (Join-Path $channelArtifacts $latestInstaller)
117+
118+
$hash = (Get-FileHash -Algorithm SHA256 (Join-Path $channelArtifacts $versionedInstaller)).Hash.ToLowerInvariant()
119+
"$hash $versionedInstaller" | Out-File -FilePath (Join-Path $channelArtifacts $checksumFile) -Encoding ascii
120+
121+
$env:INSTALLER_FILE = (Join-Path $channelArtifacts $latestInstaller)
122+
$env:MANIFEST_OUTPUT = (Join-Path $channelArtifacts $manifestFile)
123+
node apps/desktop/scripts/generate-win-update-manifest.mjs
124+
125+
"versioned_installer=$versionedInstaller" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
126+
"latest_installer=$latestInstaller" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
127+
"checksum_file=$checksumFile" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
128+
"manifest_file=$manifestFile" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
129+
130+
- name: Upload Windows workflow artifact
131+
uses: actions/upload-artifact@v4
132+
with:
133+
name: desktop-nightly-win-x64-${{ steps.meta.outputs.build_date }}-${{ steps.meta.outputs.short_sha }}
134+
path: |
135+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.versioned_installer }}
136+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.latest_installer }}
137+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.checksum_file }}
138+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.manifest_file }}
139+
retention-days: 7
140+
if-no-files-found: error
141+
142+
- name: Publish Windows prerelease assets
143+
uses: softprops/action-gh-release@v2
144+
with:
145+
tag_name: desktop-nightly
146+
target_commitish: ${{ github.sha }}
147+
name: Nexu Desktop Nightly
148+
prerelease: true
149+
draft: false
150+
overwrite_files: true
151+
fail_on_unmatched_files: true
152+
files: |
153+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.versioned_installer }}
154+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.latest_installer }}
155+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.checksum_file }}
156+
apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.manifest_file }}
157+
158+
- name: Upload Windows artifacts to Cloudflare R2
159+
env:
160+
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
161+
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
162+
AWS_ENDPOINT_URL: https://${{ secrets.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com
163+
AWS_REGION: auto
164+
shell: pwsh
165+
run: |
166+
$prefix = "nightly/win32/x64"
167+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.versioned_installer }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.versioned_installer }}" --no-progress
168+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.latest_installer }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.latest_installer }}" --no-progress
169+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.checksum_file }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.checksum_file }}" --no-progress
170+
aws s3 cp "apps/desktop/channel-artifacts-win/${{ steps.artifacts.outputs.manifest_file }}" "s3://nexu-desktop-releases/$prefix/${{ steps.artifacts.outputs.manifest_file }}" --no-progress
171+
172+
- name: Purge Windows latest CDN artifacts
173+
env:
174+
CLOUDFLARE_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }}
175+
CLOUDFLARE_PURGE_API_TOKEN: ${{ secrets.CLOUDFLARE_PURGE_API_TOKEN }}
176+
shell: pwsh
177+
run: |
178+
if ([string]::IsNullOrWhiteSpace($env:CLOUDFLARE_ZONE_ID) -or [string]::IsNullOrWhiteSpace($env:CLOUDFLARE_PURGE_API_TOKEN)) {
179+
Write-Host "Skipping Cloudflare purge because required secrets are missing"
180+
exit 0
181+
}
182+
183+
$baseUrl = "https://desktop-releases.nexu.io/nightly/win32/x64"
184+
$files = @(
185+
"$baseUrl/${{ steps.artifacts.outputs.latest_installer }}",
186+
"$baseUrl/${{ steps.artifacts.outputs.manifest_file }}"
187+
) | ConvertTo-Json
188+
$payload = @{ files = ($files | ConvertFrom-Json) } | ConvertTo-Json -Depth 5
189+
Invoke-RestMethod -Method Post -Uri "https://api.cloudflare.com/client/v4/zones/$env:CLOUDFLARE_ZONE_ID/purge_cache" -Headers @{ Authorization = "Bearer $env:CLOUDFLARE_PURGE_API_TOKEN" } -ContentType "application/json" -Body $payload | Out-Null
190+
191+
- name: Publish Windows download links
37192
shell: pwsh
38193
run: |
39-
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "## Windows placeholder"
40-
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Channel: nightly"
41-
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Status: reserved only; no Windows artifacts are published by this workflow yet"
194+
$baseUrl = "https://desktop-releases.nexu.io/nightly/win32/x64"
195+
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "## Windows Nightly Downloads"
196+
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Installer: $baseUrl/${{ steps.artifacts.outputs.latest_installer }}"
197+
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Manifest: $baseUrl/${{ steps.artifacts.outputs.manifest_file }}"
42198
43199
trigger-e2e:
44200
needs: [build, package-windows]

0 commit comments

Comments
 (0)