1[CmdletBinding()]
2Param(
3 [Parameter()][Alias('i')][switch]$Install,
4 [Parameter()][Alias('h')][switch]$Help,
5 [Parameter()][string]$Name
6)
7
8. "$PSScriptRoot/lib/blob-store.ps1"
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
17if ($Help) {
18 Write-Output "Usage: test.ps1 [-Install] [-Help]"
19 Write-Output "Build the installer for Windows.\n"
20 Write-Output "Options:"
21 Write-Output " -Install, -i Run the installer after building."
22 Write-Output " -Help, -h Show this help message."
23 exit 0
24}
25
26Push-Location -Path crates/zed
27$channel = Get-Content "RELEASE_CHANNEL"
28$env:ZED_RELEASE_CHANNEL = $channel
29$env:RELEASE_CHANNEL = $channel
30Pop-Location
31
32function CheckEnvironmentVariables {
33 $requiredVars = @(
34 'ZED_WORKSPACE', 'RELEASE_VERSION', 'ZED_RELEASE_CHANNEL',
35 'AZURE_TENANT_ID', 'AZURE_CLIENT_ID', 'AZURE_CLIENT_SECRET',
36 'ACCOUNT_NAME', 'CERT_PROFILE_NAME', 'ENDPOINT',
37 'FILE_DIGEST', 'TIMESTAMP_DIGEST', 'TIMESTAMP_SERVER'
38 )
39
40 foreach ($var in $requiredVars) {
41 if (-not (Test-Path "env:$var")) {
42 Write-Error "$var is not set"
43 exit 1
44 }
45 }
46}
47
48function PrepareForBundle {
49 if (Test-Path "$innoDir") {
50 Remove-Item -Path "$innoDir" -Recurse -Force
51 }
52 New-Item -Path "$innoDir" -ItemType Directory -Force
53 Copy-Item -Path "$env:ZED_WORKSPACE\crates\zed\resources\windows\*" -Destination "$innoDir" -Recurse -Force
54 New-Item -Path "$innoDir\make_appx" -ItemType Directory -Force
55 New-Item -Path "$innoDir\appx" -ItemType Directory -Force
56 New-Item -Path "$innoDir\bin" -ItemType Directory -Force
57 New-Item -Path "$innoDir\tools" -ItemType Directory -Force
58}
59
60function GenerateLicenses {
61 $oldErrorActionPreference = $ErrorActionPreference
62 $ErrorActionPreference = 'Continue'
63 . $PSScriptRoot/generate-licenses.ps1
64 $ErrorActionPreference = $oldErrorActionPreference
65}
66
67function BuildZedAndItsFriends {
68 Write-Output "Building Zed and its friends, for channel: $channel"
69 # Build zed.exe, cli.exe and auto_update_helper.exe
70 cargo build --release --package zed --package cli --package auto_update_helper
71 Copy-Item -Path ".\target\release\zed.exe" -Destination "$innoDir\Zed.exe" -Force
72 Copy-Item -Path ".\target\release\cli.exe" -Destination "$innoDir\cli.exe" -Force
73 Copy-Item -Path ".\target\release\auto_update_helper.exe" -Destination "$innoDir\auto_update_helper.exe" -Force
74 # Build explorer_command_injector.dll
75 switch ($channel) {
76 "stable" {
77 cargo build --release --features stable --no-default-features --package explorer_command_injector
78 }
79 "preview" {
80 cargo build --release --features preview --no-default-features --package explorer_command_injector
81 }
82 default {
83 cargo build --release --package explorer_command_injector
84 }
85 }
86 Copy-Item -Path ".\target\release\explorer_command_injector.dll" -Destination "$innoDir\zed_explorer_command_injector.dll" -Force
87}
88
89function ZipZedAndItsFriendsDebug {
90 $items = @(
91 ".\target\release\zed.pdb",
92 ".\target\release\cli.pdb",
93 ".\target\release\auto_update_helper.pdb",
94 ".\target\release\explorer_command_injector.pdb"
95 )
96
97 Compress-Archive -Path $items -DestinationPath ".\target\release\zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip" -Force
98}
99
100
101function UploadToSentry {
102 if (-not (Get-Command "sentry-cli" -ErrorAction SilentlyContinue)) {
103 Write-Output "sentry-cli not found. skipping sentry upload."
104 Write-Output "install with: 'winget install -e --id=Sentry.sentry-cli'"
105 return
106 }
107 if (-not (Test-Path "env:SENTRY_AUTH_TOKEN")) {
108 Write-Output "missing SENTRY_AUTH_TOKEN. skipping sentry upload."
109 return
110 }
111 Write-Output "Uploading zed debug symbols to sentry..."
112 sentry-cli debug-files upload --include-sources --wait -p zed -o zed-dev .\target\release\
113}
114
115function MakeAppx {
116 switch ($channel) {
117 "stable" {
118 $manifestFile = "$env:ZED_WORKSPACE\crates\explorer_command_injector\AppxManifest.xml"
119 }
120 "preview" {
121 $manifestFile = "$env:ZED_WORKSPACE\crates\explorer_command_injector\AppxManifest-Preview.xml"
122 }
123 default {
124 $manifestFile = "$env:ZED_WORKSPACE\crates\explorer_command_injector\AppxManifest-Nightly.xml"
125 }
126 }
127 Copy-Item -Path "$manifestFile" -Destination "$innoDir\make_appx\AppxManifest.xml"
128 # Add makeAppx.exe to Path
129 $sdk = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64"
130 $env:Path += ';' + $sdk
131 makeAppx.exe pack /d "$innoDir\make_appx" /p "$innoDir\zed_explorer_command_injector.appx" /nv
132}
133
134function SignZedAndItsFriends {
135 $files = "$innoDir\Zed.exe,$innoDir\cli.exe,$innoDir\auto_update_helper.exe,$innoDir\zed_explorer_command_injector.dll,$innoDir\zed_explorer_command_injector.appx"
136 & "$innoDir\sign.ps1" $files
137}
138
139function DownloadAMDGpuServices {
140 # If you update the AGS SDK version, please also update the version in `crates/gpui/src/platform/windows/directx_renderer.rs`
141 $url = "https://codeload.github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/zip/refs/tags/v6.3.0"
142 $zipPath = ".\AGS_SDK_v6.3.0.zip"
143 # Download the AGS SDK zip file
144 Invoke-WebRequest -Uri $url -OutFile $zipPath
145 # Extract the AGS SDK zip file
146 Expand-Archive -Path $zipPath -DestinationPath "." -Force
147}
148
149function DownloadConpty {
150 # If you update the Conpty version, please also update the version in `crates/zed/build.rs`.
151 $url = "https://www.nuget.org/api/v2/package/CI.Microsoft.Windows.Console.ConPTY/1.22.250314001"
152 $zipPath = ".\conpty.zip"
153 Invoke-WebRequest -Uri $url -OutFile $zipPath
154 Expand-Archive -Path $zipPath -DestinationPath ".\conpty" -Force
155}
156
157function CollectFiles {
158 Move-Item -Path "$innoDir\zed_explorer_command_injector.appx" -Destination "$innoDir\appx\zed_explorer_command_injector.appx" -Force
159 Move-Item -Path "$innoDir\zed_explorer_command_injector.dll" -Destination "$innoDir\appx\zed_explorer_command_injector.dll" -Force
160 Move-Item -Path "$innoDir\cli.exe" -Destination "$innoDir\bin\zed.exe" -Force
161 Move-Item -Path "$innoDir\zed.sh" -Destination "$innoDir\bin\zed" -Force
162 Move-Item -Path "$innoDir\auto_update_helper.exe" -Destination "$innoDir\tools\auto_update_helper.exe" -Force
163 Move-Item -Path ".\AGS_SDK-6.3.0\ags_lib\lib\amd_ags_x64.dll" -Destination "$innoDir\amd_ags_x64.dll" -Force
164 Move-Item -Path ".\conpty\build\native\runtimes\*" -Destination "$innoDir\bin" -Force
165 Move-Item -Path ".\conpty\runtimes\win10-x64\native\conpty.dll" -Destination "$innoDir\bin\conpty.dll" -Force
166}
167
168function BuildInstaller {
169 $issFilePath = "$innoDir\zed.iss"
170 switch ($channel) {
171 "stable" {
172 $appId = "{{2DB0DA96-CA55-49BB-AF4F-64AF36A86712}"
173 $appIconName = "app-icon"
174 $appName = "Zed"
175 $appDisplayName = "Zed"
176 $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION"
177 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
178 $appMutex = "Zed-Stable-Instance-Mutex"
179 $appExeName = "Zed"
180 $regValueName = "Zed"
181 $appUserId = "ZedIndustries.Zed"
182 $appShellNameShort = "Z&ed"
183 $appAppxFullName = "ZedIndustries.Zed_1.0.0.0_neutral__japxn1gcva8rg"
184 }
185 "preview" {
186 $appId = "{{F70E4811-D0E2-4D88-AC99-D63752799F95}"
187 $appIconName = "app-icon-preview"
188 $appName = "Zed Preview"
189 $appDisplayName = "Zed Preview"
190 $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION-preview"
191 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
192 $appMutex = "Zed-Preview-Instance-Mutex"
193 $appExeName = "Zed"
194 $regValueName = "ZedPreview"
195 $appUserId = "ZedIndustries.Zed.Preview"
196 $appShellNameShort = "Z&ed Preview"
197 $appAppxFullName = "ZedIndustries.Zed.Preview_1.0.0.0_neutral__japxn1gcva8rg"
198 }
199 "nightly" {
200 $appId = "{{1BDB21D3-14E7-433C-843C-9C97382B2FE0}"
201 $appIconName = "app-icon-nightly"
202 $appName = "Zed Nightly"
203 $appDisplayName = "Zed Nightly"
204 $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION-nightly"
205 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
206 $appMutex = "Zed-Nightly-Instance-Mutex"
207 $appExeName = "Zed"
208 $regValueName = "ZedNightly"
209 $appUserId = "ZedIndustries.Zed.Nightly"
210 $appShellNameShort = "Z&ed Editor Nightly"
211 $appAppxFullName = "ZedIndustries.Zed.Nightly_1.0.0.0_neutral__japxn1gcva8rg"
212 }
213 "dev" {
214 $appId = "{{8357632E-24A4-4F32-BA97-E575B4D1FE5D}"
215 $appIconName = "app-icon-dev"
216 $appName = "Zed Dev"
217 $appDisplayName = "Zed Dev"
218 $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION-dev"
219 # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
220 $appMutex = "Zed-Dev-Instance-Mutex"
221 $appExeName = "Zed"
222 $regValueName = "ZedDev"
223 $appUserId = "ZedIndustries.Zed.Dev"
224 $appShellNameShort = "Z&ed Dev"
225 $appAppxFullName = "ZedIndustries.Zed.Dev_1.0.0.0_neutral__japxn1gcva8rg"
226 }
227 default {
228 Write-Error "can't bundle installer for $channel."
229 exit 1
230 }
231 }
232
233 # Windows runner 2022 default has iscc in PATH, https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md
234 # Currently, we are using Windows 2022 runner.
235 # Windows runner 2025 doesn't have iscc in PATH for now, https://github.com/actions/runner-images/issues/11228
236 $innoSetupPath = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe"
237
238 $definitions = @{
239 "AppId" = $appId
240 "AppIconName" = $appIconName
241 "OutputDir" = "$env:ZED_WORKSPACE\target"
242 "AppSetupName" = $appSetupName
243 "AppName" = $appName
244 "AppDisplayName" = $appDisplayName
245 "RegValueName" = $regValueName
246 "AppMutex" = $appMutex
247 "AppExeName" = $appExeName
248 "ResourcesDir" = "$innoDir"
249 "ShellNameShort" = $appShellNameShort
250 "AppUserId" = $appUserId
251 "Version" = "$env:RELEASE_VERSION"
252 "SourceDir" = "$env:ZED_WORKSPACE"
253 "AppxFullName" = $appAppxFullName
254 }
255
256 $signTool = "powershell.exe -ExecutionPolicy Bypass -File $innoDir\sign.ps1 `$f"
257
258 $defs = @()
259 foreach ($key in $definitions.Keys) {
260 $defs += "/d$key=`"$($definitions[$key])`""
261 }
262
263 $innoArgs = @($issFilePath) + $defs + "/sDefaultsign=`"$signTool`""
264
265 # Execute Inno Setup
266 Write-Host "🚀 Running Inno Setup: $innoSetupPath $innoArgs"
267 $process = Start-Process -FilePath $innoSetupPath -ArgumentList $innoArgs -NoNewWindow -Wait -PassThru
268
269 if ($process.ExitCode -eq 0) {
270 Write-Host "✅ Inno Setup successfully compiled the installer"
271 Write-Output "SETUP_PATH=target/$appSetupName.exe" >> $env:GITHUB_ENV
272 $script:buildSuccess = $true
273 }
274 else {
275 Write-Host "❌ Inno Setup failed: $($process.ExitCode)"
276 $script:buildSuccess = $false
277 }
278}
279
280ParseZedWorkspace
281$innoDir = "$env:ZED_WORKSPACE\inno"
282$debugArchive = ".\target\release\zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip"
283$debugStoreKey = "$env:ZED_RELEASE_CHANNEL/zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip"
284
285CheckEnvironmentVariables
286PrepareForBundle
287GenerateLicenses
288BuildZedAndItsFriends
289MakeAppx
290SignZedAndItsFriends
291ZipZedAndItsFriendsDebug
292DownloadAMDGpuServices
293DownloadConpty
294CollectFiles
295BuildInstaller
296
297UploadToBlobStorePublic -BucketName "zed-debug-symbols" -FileToUpload $debugArchive -BlobStoreKey $debugStoreKey
298UploadToSentry
299
300if ($buildSuccess) {
301 Write-Output "Build successful"
302 if ($Install) {
303 Write-Output "Installing Zed..."
304 Start-Process -FilePath "$env:ZED_WORKSPACE/target/ZedEditorUserSetup-x64-$env:RELEASE_VERSION.exe"
305 }
306 exit 0
307}
308else {
309 Write-Output "Build failed"
310 exit 1
311}