bundle-windows.ps1

  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 CollectFiles {
140    Move-Item -Path "$innoDir\zed_explorer_command_injector.appx" -Destination "$innoDir\appx\zed_explorer_command_injector.appx" -Force
141    Move-Item -Path "$innoDir\zed_explorer_command_injector.dll" -Destination "$innoDir\appx\zed_explorer_command_injector.dll" -Force
142    Move-Item -Path "$innoDir\cli.exe" -Destination "$innoDir\bin\zed.exe" -Force
143    Move-Item -Path "$innoDir\auto_update_helper.exe" -Destination "$innoDir\tools\auto_update_helper.exe" -Force
144}
145
146function BuildInstaller {
147    $issFilePath = "$innoDir\zed.iss"
148    switch ($channel) {
149        "stable" {
150            $appId = "{{2DB0DA96-CA55-49BB-AF4F-64AF36A86712}"
151            $appIconName = "app-icon"
152            $appName = "Zed"
153            $appDisplayName = "Zed"
154            $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION"
155            # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
156            $appMutex = "Zed-Stable-Instance-Mutex"
157            $appExeName = "Zed"
158            $regValueName = "Zed"
159            $appUserId = "ZedIndustries.Zed"
160            $appShellNameShort = "Z&ed"
161            $appAppxFullName = "ZedIndustries.Zed_1.0.0.0_neutral__japxn1gcva8rg"
162        }
163        "preview" {
164            $appId = "{{F70E4811-D0E2-4D88-AC99-D63752799F95}"
165            $appIconName = "app-icon-preview"
166            $appName = "Zed Preview"
167            $appDisplayName = "Zed Preview"
168            $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION-preview"
169            # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
170            $appMutex = "Zed-Preview-Instance-Mutex"
171            $appExeName = "Zed"
172            $regValueName = "ZedPreview"
173            $appUserId = "ZedIndustries.Zed.Preview"
174            $appShellNameShort = "Z&ed Preview"
175            $appAppxFullName = "ZedIndustries.Zed.Preview_1.0.0.0_neutral__japxn1gcva8rg"
176        }
177        "nightly" {
178            $appId = "{{1BDB21D3-14E7-433C-843C-9C97382B2FE0}"
179            $appIconName = "app-icon-nightly"
180            $appName = "Zed Nightly"
181            $appDisplayName = "Zed Nightly"
182            $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION-nightly"
183            # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
184            $appMutex = "Zed-Nightly-Instance-Mutex"
185            $appExeName = "Zed"
186            $regValueName = "ZedNightly"
187            $appUserId = "ZedIndustries.Zed.Nightly"
188            $appShellNameShort = "Z&ed Editor Nightly"
189            $appAppxFullName = "ZedIndustries.Zed.Nightly_1.0.0.0_neutral__japxn1gcva8rg"
190        }
191        "dev" {
192            $appId = "{{8357632E-24A4-4F32-BA97-E575B4D1FE5D}"
193            $appIconName = "app-icon-dev"
194            $appName = "Zed Dev"
195            $appDisplayName = "Zed Dev"
196            $appSetupName = "ZedEditorUserSetup-x64-$env:RELEASE_VERSION-dev"
197            # The mutex name here should match the mutex name in crates\zed\src\zed\windows_only_instance.rs
198            $appMutex = "Zed-Dev-Instance-Mutex"
199            $appExeName = "Zed"
200            $regValueName = "ZedDev"
201            $appUserId = "ZedIndustries.Zed.Dev"
202            $appShellNameShort = "Z&ed Dev"
203            $appAppxFullName = "ZedIndustries.Zed.Dev_1.0.0.0_neutral__japxn1gcva8rg"
204        }
205        default {
206            Write-Error "can't bundle installer for $channel."
207            exit 1
208        }
209    }
210
211    # Windows runner 2022 default has iscc in PATH, https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md
212    # Currently, we are using Windows 2022 runner.
213    # Windows runner 2025 doesn't have iscc in PATH for now, https://github.com/actions/runner-images/issues/11228
214    # $innoSetupPath = "iscc.exe"
215    $innoSetupPath = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe"
216
217    $definitions = @{
218        "AppId"          = $appId
219        "AppIconName"    = $appIconName
220        "OutputDir"      = "$env:ZED_WORKSPACE\target"
221        "AppSetupName"   = $appSetupName
222        "AppName"        = $appName
223        "AppDisplayName" = $appDisplayName
224        "RegValueName"   = $regValueName
225        "AppMutex"       = $appMutex
226        "AppExeName"     = $appExeName
227        "ResourcesDir"   = "$innoDir"
228        "ShellNameShort" = $appShellNameShort
229        "AppUserId"      = $appUserId
230        "Version"        = "$env:RELEASE_VERSION"
231        "SourceDir"      = "$env:ZED_WORKSPACE"
232        "AppxFullName"   = $appAppxFullName
233    }
234
235    $signTool = "powershell.exe -ExecutionPolicy Bypass -File $innoDir\sign.ps1 `$f"
236
237    $defs = @()
238    foreach ($key in $definitions.Keys) {
239        $defs += "/d$key=`"$($definitions[$key])`""
240    }
241
242    $innoArgs = @($issFilePath) + $defs + "/sDefaultsign=`"$signTool`""
243
244    # Execute Inno Setup
245    Write-Host "🚀 Running Inno Setup: $innoSetupPath $innoArgs"
246    $process = Start-Process -FilePath $innoSetupPath -ArgumentList $innoArgs -NoNewWindow -Wait -PassThru
247
248    if ($process.ExitCode -eq 0) {
249        Write-Host "✅ Inno Setup successfully compiled the installer"
250        Write-Output "SETUP_PATH=target/$appSetupName.exe" >> $env:GITHUB_ENV
251        $script:buildSuccess = $true
252    }
253    else {
254        Write-Host "❌ Inno Setup failed: $($process.ExitCode)"
255        $script:buildSuccess = $false
256    }
257}
258
259ParseZedWorkspace
260$innoDir = "$env:ZED_WORKSPACE\inno"
261$debugArchive = ".\target\release\zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip"
262$debugStoreKey = "$env:ZED_RELEASE_CHANNEL/zed-$env:RELEASE_VERSION-$env:ZED_RELEASE_CHANNEL.dbg.zip"
263
264CheckEnvironmentVariables
265PrepareForBundle
266GenerateLicenses
267BuildZedAndItsFriends
268MakeAppx
269SignZedAndItsFriends
270ZipZedAndItsFriendsDebug
271CollectFiles
272BuildInstaller
273
274UploadToBlobStorePublic -BucketName "zed-debug-symbols" -FileToUpload $debugArchive -BlobStoreKey $debugStoreKey
275UploadToSentry
276
277if ($buildSuccess) {
278    Write-Output "Build successful"
279    if ($Install) {
280        Write-Output "Installing Zed..."
281        Start-Process -FilePath "$env:ZED_WORKSPACE/target/ZedEditorUserSetup-x64-$env:RELEASE_VERSION.exe"
282    }
283    exit 0
284}
285else {
286    Write-Output "Build failed"
287    exit 1
288}