@@ -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