1[CmdletBinding()]
2Param(
3 [Parameter()][Alias('i')][switch]$Install,
4 [Parameter()][Alias('h')][switch]$Help,
5 [Parameter()][Alias('a')][string]$Architecture,
6 [Parameter()][string]$Name
7)
8
9. "$PSScriptRoot/lib/workspace.ps1"
10
11# https://stackoverflow.com/questions/57949031/powershell-script-stops-if-program-fails-like-bash-set-o-errexit
12$ErrorActionPreference = 'Stop'
13$PSNativeCommandUseErrorActionPreference = $true
14
15$buildSuccess = $false
16
17$OSArchitecture = switch ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture) {
18 "X64" { "x86_64" }
19 "Arm64" { "aarch64" }
20 default { throw "Unsupported architecture" }
21}
22
23$Architecture = if ($Architecture) {
24 $Architecture
25} else {
26 $OSArchitecture
27}
28
29$CargoOutDir = "./target/$Architecture-pc-windows-msvc/release"
30
31function Get-VSArch {
32 param(
33 [string]$Arch
34 )
35
36 switch ($Arch) {
37 "x86_64" { "amd64" }
38 "aarch64" { "arm64" }
39 }
40}
41
42Push-Location
43& "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\Launch-VsDevShell.ps1" -Arch (Get-VSArch -Arch $Architecture) -HostArch (Get-VSArch -Arch $OSArchitecture)
44Pop-Location
45
46$target = "$Architecture-pc-windows-msvc"
47
48if ($Help) {
49 Write-Output "Usage: test.ps1 [-Install] [-Help]"
50 Write-Output "Build the installer for Windows.\n"
51 Write-Output "Options:"
52 Write-Output " -Architecture, -a Which architecture to build (x86_64 or aarch64)"
53 Write-Output " -Install, -i Run the installer after building."
54 Write-Output " -Help, -h Show this help message."
55 exit 0
56}
57
58Push-Location -Path crates/zed
59$channel = Get-Content "RELEASE_CHANNEL"
60$env:ZED_RELEASE_CHANNEL = $channel
61$env:RELEASE_CHANNEL = $channel
62Pop-Location
63
64function CheckEnvironmentVariables {
65 if(-not $env:CI) {
66 return
67 }
68
69 $requiredVars = @(
70 'ZED_WORKSPACE', 'RELEASE_VERSION', 'ZED_RELEASE_CHANNEL',
71 'AZURE_TENANT_ID', 'AZURE_CLIENT_ID', 'AZURE_CLIENT_SECRET',
72 'ACCOUNT_NAME', 'CERT_PROFILE_NAME', 'ENDPOINT',
73 'FILE_DIGEST', 'TIMESTAMP_DIGEST', 'TIMESTAMP_SERVER'
74 )
75
76 foreach ($var in $requiredVars) {
77 if (-not (Test-Path "env:$var")) {
78 Write-Error "$var is not set"
79 exit 1
80 }
81 }
82}
83
84function PrepareForBundle {
85 if (Test-Path "$innoDir") {
86 Remove-Item -Path "$innoDir" -Recurse -Force
87 }
88 New-Item -Path "$innoDir" -ItemType Directory -Force
89 Copy-Item -Path "$env:ZED_WORKSPACE\crates\zed\resources\windows\*" -Destination "$innoDir" -Recurse -Force
90 New-Item -Path "$innoDir\make_appx" -ItemType Directory -Force
91 New-Item -Path "$innoDir\appx" -ItemType Directory -Force
92 New-Item -Path "$innoDir\bin" -ItemType Directory -Force
93 New-Item -Path "$innoDir\tools" -ItemType Directory -Force
94
95 rustup target add $target
96}
97
98function GenerateLicenses {
99 $oldErrorActionPreference = $ErrorActionPreference
100 $ErrorActionPreference = 'Continue'
101 . $PSScriptRoot/generate-licenses.ps1
102 $ErrorActionPreference = $oldErrorActionPreference
103}
104
105function BuildZedAndItsFriends {
106 Write-Output "Building Zed and its friends, for channel: $channel"
107 # Build zed.exe, cli.exe and auto_update_helper.exe
108 cargo build --release --package zed --package cli --package auto_update_helper --target $target
109 Copy-Item -Path ".\$CargoOutDir\zed.exe" -Destination "$innoDir\Zed.exe" -Force
110 Copy-Item -Path ".\$CargoOutDir\cli.exe" -Destination "$innoDir\cli.exe" -Force
111 Copy-Item -Path ".\$CargoOutDir\auto_update_helper.exe" -Destination "$innoDir\auto_update_helper.exe" -Force
112 # Build explorer_command_injector.dll
113 switch ($channel) {
114 "stable" {
115 cargo build --release --features stable --no-default-features --package explorer_command_injector --target $target
116 }
117 "preview" {
118 cargo build --release --features preview --no-default-features --package explorer_command_injector --target $target
119 }
120 default {
121 cargo build --release --package explorer_command_injector --target $target
122 }
123 }
124 Copy-Item -Path ".\$CargoOutDir\explorer_command_injector.dll" -Destination "$innoDir\zed_explorer_command_injector.dll" -Force
125}
126
127function BuildRemoteServer {
128 Write-Output "Building remote_server for $target"
129 cargo build --release --package remote_server --target $target
130
131 # Create zipped remote server binary
132 $remoteServerSrc = (Resolve-Path ".\$CargoOutDir\remote_server.exe").Path
133
134 if ($env:CI) {
135 Write-Output "Code signing remote_server.exe"
136 & "$innoDir\sign.ps1" $remoteServerSrc
137 }
138
139 $remoteServerDst = "$env:ZED_WORKSPACE\target\zed-remote-server-windows-$Architecture.zip"
140 Write-Output "Compressing remote_server to $remoteServerDst"
141 Compress-Archive -Path $remoteServerSrc -DestinationPath $remoteServerDst -Force
142
143 Write-Output "Remote server compressed successfully"
144}
145
146function ZipZedAndItsFriendsDebug {
147 $items = @(
148 ".\$CargoOutDir\zed.pdb",
149 ".\$CargoOutDir\cli.pdb",
150 ".\$CargoOutDir\auto_update_helper.pdb",
151 ".\$CargoOutDir\explorer_command_injector.pdb",
152 ".\$CargoOutDir\remote_server.pdb"
153 )
154
155 Compress-Archive -Path $items -DestinationPath ".\$CargoOutDir\zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip" -Force
156}
157
158
159function UploadToSentry {
160 if (-not (Get-Command "sentry-cli" -ErrorAction SilentlyContinue)) {
161 Write-Output "sentry-cli not found. skipping sentry upload."
162 Write-Output "install with: 'winget install -e --id=Sentry.sentry-cli'"
163 return
164 }
165 if (-not (Test-Path "env:SENTRY_AUTH_TOKEN")) {
166 Write-Output "missing SENTRY_AUTH_TOKEN. skipping sentry upload."
167 return
168 }
169 Write-Output "Uploading zed debug symbols to sentry..."
170 for ($i = 1; $i -le 3; $i++) {
171 try {
172 sentry-cli debug-files upload --include-sources --wait -p zed -o zed-dev $CargoOutDir
173 break
174 }
175 catch {
176 Write-Output "Sentry upload attempt $i failed: $_"
177 if ($i -eq 3) {
178 Write-Output "All sentry upload attempts failed"
179 throw
180 }
181 Start-Sleep -Seconds 2
182 }
183 }
184}
185
186function MakeAppx {
187 switch ($channel) {
188 "stable" {
189 $manifestFile = "$env:ZED_WORKSPACE\crates\explorer_command_injector\AppxManifest.xml"
190 }
191 "preview" {
192 $manifestFile = "$env:ZED_WORKSPACE\crates\explorer_command_injector\AppxManifest-Preview.xml"
193 }
194 default {
195 $manifestFile = "$env:ZED_WORKSPACE\crates\explorer_command_injector\AppxManifest-Nightly.xml"
196 }
197 }
198 Copy-Item -Path "$manifestFile" -Destination "$innoDir\make_appx\AppxManifest.xml"
199 # Add makeAppx.exe to Path
200 $sdk = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64"
201 $env:Path += ';' + $sdk
202 makeAppx.exe pack /d "$innoDir\make_appx" /p "$innoDir\zed_explorer_command_injector.appx" /nv
203}
204
205function SignZedAndItsFriends {
206 if (-not $env:CI) {
207 return
208 }
209
210 $files = "$innoDir\Zed.exe,$innoDir\cli.exe,$innoDir\auto_update_helper.exe,$innoDir\zed_explorer_command_injector.dll,$innoDir\zed_explorer_command_injector.appx"
211 & "$innoDir\sign.ps1" $files
212}
213
214function DownloadAMDGpuServices {
215 # If you update the AGS SDK version, please also update the version in `crates/gpui/src/platform/windows/directx_renderer.rs`
216 $url = "https://codeload.github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/zip/refs/tags/v6.3.0"
217 $zipPath = ".\AGS_SDK_v6.3.0.zip"
218 # Download the AGS SDK zip file
219 Invoke-WebRequest -Uri $url -OutFile $zipPath
220 # Extract the AGS SDK zip file
221 Expand-Archive -Path $zipPath -DestinationPath "." -Force
222}
223
224function DownloadConpty {
225 $url = "https://github.com/microsoft/terminal/releases/download/v1.23.13503.0/Microsoft.Windows.Console.ConPTY.1.23.251216003.nupkg"
226 $zipPath = ".\Microsoft.Windows.Console.ConPTY.1.23.251216003.nupkg"
227 Invoke-WebRequest -Uri $url -OutFile $zipPath
228 Expand-Archive -Path $zipPath -DestinationPath ".\conpty" -Force
229}
230
231function CollectFiles {
232 Move-Item -Path "$innoDir\zed_explorer_command_injector.appx" -Destination "$innoDir\appx\zed_explorer_command_injector.appx" -Force
233 Move-Item -Path "$innoDir\zed_explorer_command_injector.dll" -Destination "$innoDir\appx\zed_explorer_command_injector.dll" -Force
234 Move-Item -Path "$innoDir\cli.exe" -Destination "$innoDir\bin\zed.exe" -Force
235 Move-Item -Path "$innoDir\zed.sh" -Destination "$innoDir\bin\zed" -Force
236 Move-Item -Path "$innoDir\auto_update_helper.exe" -Destination "$innoDir\tools\auto_update_helper.exe" -Force
237 if($Architecture -eq "aarch64") {
238 New-Item -Type Directory -Path "$innoDir\arm64" -Force
239 Move-Item -Path ".\conpty\build\native\runtimes\arm64\OpenConsole.exe" -Destination "$innoDir\arm64\OpenConsole.exe" -Force
240 Move-Item -Path ".\conpty\runtimes\win-arm64\native\conpty.dll" -Destination "$innoDir\conpty.dll" -Force
241 }
242 else {
243 New-Item -Type Directory -Path "$innoDir\x64" -Force
244 New-Item -Type Directory -Path "$innoDir\arm64" -Force
245 Move-Item -Path ".\AGS_SDK-6.3.0\ags_lib\lib\amd_ags_x64.dll" -Destination "$innoDir\amd_ags_x64.dll" -Force
246 Move-Item -Path ".\conpty\build\native\runtimes\x64\OpenConsole.exe" -Destination "$innoDir\x64\OpenConsole.exe" -Force
247 Move-Item -Path ".\conpty\build\native\runtimes\arm64\OpenConsole.exe" -Destination "$innoDir\arm64\OpenConsole.exe" -Force
248 Move-Item -Path ".\conpty\runtimes\win-x64\native\conpty.dll" -Destination "$innoDir\conpty.dll" -Force
249 }
250}
251
252function BuildInstaller {
253 $issFilePath = "$innoDir\zed.iss"
254 switch ($channel) {
255 "stable" {
256 $appId = "{{2DB0DA96-CA55-49BB-AF4F-64AF36A86712}"
257 $appIconName = "app-icon"
258 $appName = "Zed"
259 $appDisplayName = "Zed"
260 $appSetupName = "Zed-$Architecture"
261 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
262 $appMutex = "Zed-Stable-Instance-Mutex"
263 $appExeName = "Zed"
264 $regValueName = "Zed"
265 $appUserId = "ZedIndustries.Zed"
266 $appShellNameShort = "Z&ed"
267 $appAppxFullName = "ZedIndustries.Zed_1.0.0.0_neutral__japxn1gcva8rg"
268 }
269 "preview" {
270 $appId = "{{F70E4811-D0E2-4D88-AC99-D63752799F95}"
271 $appIconName = "app-icon-preview"
272 $appName = "Zed Preview"
273 $appDisplayName = "Zed Preview"
274 $appSetupName = "Zed-$Architecture"
275 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
276 $appMutex = "Zed-Preview-Instance-Mutex"
277 $appExeName = "Zed"
278 $regValueName = "ZedPreview"
279 $appUserId = "ZedIndustries.Zed.Preview"
280 $appShellNameShort = "Z&ed Preview"
281 $appAppxFullName = "ZedIndustries.Zed.Preview_1.0.0.0_neutral__japxn1gcva8rg"
282 }
283 "nightly" {
284 $appId = "{{1BDB21D3-14E7-433C-843C-9C97382B2FE0}"
285 $appIconName = "app-icon-nightly"
286 $appName = "Zed Nightly"
287 $appDisplayName = "Zed Nightly"
288 $appSetupName = "Zed-$Architecture"
289 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
290 $appMutex = "Zed-Nightly-Instance-Mutex"
291 $appExeName = "Zed"
292 $regValueName = "ZedNightly"
293 $appUserId = "ZedIndustries.Zed.Nightly"
294 $appShellNameShort = "Z&ed Editor Nightly"
295 $appAppxFullName = "ZedIndustries.Zed.Nightly_1.0.0.0_neutral__japxn1gcva8rg"
296 }
297 "dev" {
298 $appId = "{{8357632E-24A4-4F32-BA97-E575B4D1FE5D}"
299 $appIconName = "app-icon-dev"
300 $appName = "Zed Dev"
301 $appDisplayName = "Zed Dev"
302 $appSetupName = "Zed-$Architecture"
303 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
304 $appMutex = "Zed-Dev-Instance-Mutex"
305 $appExeName = "Zed"
306 $regValueName = "ZedDev"
307 $appUserId = "ZedIndustries.Zed.Dev"
308 $appShellNameShort = "Z&ed Dev"
309 $appAppxFullName = "ZedIndustries.Zed.Dev_1.0.0.0_neutral__japxn1gcva8rg"
310 }
311 default {
312 Write-Error "can't bundle installer for $channel."
313 exit 1
314 }
315 }
316
317 # Windows runner 2022 default has iscc in PATH, https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md
318 # Currently, we are using Windows 2022 runner.
319 # Windows runner 2025 doesn't have iscc in PATH for now, https://github.com/actions/runner-images/issues/11228
320 $innoSetupPath = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe"
321
322 $definitions = @{
323 "AppId" = $appId
324 "AppIconName" = $appIconName
325 "OutputDir" = "$env:ZED_WORKSPACE\target"
326 "AppSetupName" = $appSetupName
327 "AppName" = $appName
328 "AppDisplayName" = $appDisplayName
329 "RegValueName" = $regValueName
330 "AppMutex" = $appMutex
331 "AppExeName" = $appExeName
332 "ResourcesDir" = "$innoDir"
333 "ShellNameShort" = $appShellNameShort
334 "AppUserId" = $appUserId
335 "Version" = "$env:RELEASE_VERSION"
336 "SourceDir" = "$env:ZED_WORKSPACE"
337 "AppxFullName" = $appAppxFullName
338 }
339
340 $defs = @()
341 foreach ($key in $definitions.Keys) {
342 $defs += "/d$key=`"$($definitions[$key])`""
343 }
344
345 $innoArgs = @($issFilePath) + $defs
346 if($env:CI) {
347 $signTool = "powershell.exe -ExecutionPolicy Bypass -File $innoDir\sign.ps1 `$f"
348 $innoArgs += "/sDefaultsign=`"$signTool`""
349 }
350
351 # Execute Inno Setup
352 Write-Host "🚀 Running Inno Setup: $innoSetupPath $innoArgs"
353 $process = Start-Process -FilePath $innoSetupPath -ArgumentList $innoArgs -NoNewWindow -Wait -PassThru
354
355 if ($process.ExitCode -eq 0) {
356 Write-Host "✅ Inno Setup successfully compiled the installer"
357 Write-Output "SETUP_PATH=target/$appSetupName.exe" >> $env:GITHUB_ENV
358 $script:buildSuccess = $true
359 }
360 else {
361 Write-Host "❌ Inno Setup failed: $($process.ExitCode)"
362 $script:buildSuccess = $false
363 }
364}
365
366ParseZedWorkspace
367$innoDir = "$env:ZED_WORKSPACE\inno\$Architecture"
368$debugArchive = "$CargoOutDir\zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip"
369$debugStoreKey = "$env:ZED_RELEASE_CHANNEL/zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip"
370
371CheckEnvironmentVariables
372PrepareForBundle
373GenerateLicenses
374BuildZedAndItsFriends
375BuildRemoteServer
376MakeAppx
377SignZedAndItsFriends
378ZipZedAndItsFriendsDebug
379DownloadAMDGpuServices
380DownloadConpty
381CollectFiles
382BuildInstaller
383
384if($env:CI) {
385 UploadToSentry
386}
387
388if ($buildSuccess) {
389 Write-Output "Build successful"
390 if ($Install) {
391 Write-Output "Installing Zed..."
392 Start-Process -FilePath "$env:ZED_WORKSPACE/target/ZedEditorUserSetup-x64-$env:RELEASE_VERSION.exe"
393 }
394 exit 0
395}
396else {
397 Write-Output "Build failed"
398 exit 1
399}