Release / release (push) Failing after 4m39s
leftovers Reviewed-on: #5 Co-authored-by: Aleksandr Neychev <alexnejchev73@gmail.com>
164 lines
5.7 KiB
PowerShell
164 lines
5.7 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Builds the CursorLang installer for handing the application round outside
|
|
the Store.
|
|
|
|
.DESCRIPTION
|
|
Nothing has to be installed beyond the .NET SDK: WiX arrives as a NuGet
|
|
package, the same way makeappx does for the MSIX build.
|
|
|
|
Nobody signs the result, so Windows warns about an unknown publisher and the
|
|
user has to insist. Short of a certificate from a trusted authority there is
|
|
no way round that, and it is the reason this installer is meant for people who
|
|
already know where the file came from.
|
|
|
|
The application is published with its own copy of .NET: Windows carries no
|
|
runtime of its own, and a self-contained build is tied to x64.
|
|
|
|
.PARAMETER Install
|
|
Runs the installer once it is built, to see the thing through the way a user
|
|
would.
|
|
|
|
.EXAMPLE
|
|
# Build and run it, to see what a user sees
|
|
pwsh -File Packaging\build-installer.ps1 -Install
|
|
|
|
.EXAMPLE
|
|
# What a release needs
|
|
pwsh -File Packaging\build-installer.ps1 -Version 1.0.1
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
# Three numbers: unlike the Store, an installer keeps no place for a fourth
|
|
[string] $Version = '1.0.0',
|
|
|
|
[switch] $Install,
|
|
|
|
[string] $OutputPath
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$root = $PSScriptRoot
|
|
$repository = Split-Path -Parent $root
|
|
$agentProject = Join-Path $repository 'CursorLang.Agent\CursorLang.Agent.csproj'
|
|
$settingsProject = Join-Path $repository 'CursorLang.Settings\CursorLang.Settings.csproj'
|
|
$installerProject = Join-Path $root 'Installer\CursorLang.wixproj'
|
|
$icon = Join-Path $repository 'CursorLang.Core\Resources\CursorLang.ico'
|
|
$license = Join-Path $repository 'LICENSE'
|
|
|
|
if (-not $OutputPath) { $OutputPath = Join-Path $repository 'artifacts' }
|
|
$stagingRoot = Join-Path $OutputPath 'installer-staging'
|
|
$installersPath = Join-Path $OutputPath 'installers'
|
|
|
|
if ($Version -notmatch '^\d+\.\d+\.\d+$') {
|
|
throw "The version '$Version' does not fit: an installer is versioned by three numbers, for example 1.0.0."
|
|
}
|
|
|
|
if (-not (Test-Path $icon)) {
|
|
throw "The icon is missing from '$icon'. Git LFS may have left a pointer in its place: run git lfs pull."
|
|
}
|
|
|
|
function Invoke-Tool {
|
|
<#
|
|
.SYNOPSIS
|
|
Runs a program and fails the build if it returned an error.
|
|
.DESCRIPTION
|
|
A wrapper of our own is needed because PowerShell does not treat the
|
|
failure of an external program as an error and quietly moves on.
|
|
#>
|
|
param(
|
|
[string] $Path,
|
|
[string[]] $Arguments
|
|
)
|
|
|
|
& $Path @Arguments
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "'$([System.IO.Path]::GetFileName($Path))' exited with code $LASTEXITCODE."
|
|
}
|
|
}
|
|
|
|
function Write-LicenseRtf {
|
|
<#
|
|
.SYNOPSIS
|
|
Turns the plain-text LICENSE into the RTF the wizard needs.
|
|
.DESCRIPTION
|
|
The licence page of a Windows Installer wizard reads RTF and nothing
|
|
else, and keeping a second copy of the licence in the repository would
|
|
mean keeping the two in step by hand. The conversion is as plain as it
|
|
looks: the text carries no formatting to preserve.
|
|
#>
|
|
param([string] $Path)
|
|
|
|
$text = (Get-Content $license -Raw) -replace '\\', '\\\\' -replace '{', '\{' -replace '}', '\}'
|
|
$body = ($text -split "`r?`n") -join '\par' + "`r`n"
|
|
|
|
Set-Content -Path $Path -Value "{\rtf1\ansi\deff0{\fonttbl{\f0 Segoe UI;}}\fs18 $body}" -Encoding ASCII
|
|
}
|
|
|
|
Remove-Item $stagingRoot -Recurse -Force -ErrorAction SilentlyContinue
|
|
New-Item -ItemType Directory -Path $installersPath -Force | Out-Null
|
|
|
|
$licenseRtf = Join-Path $stagingRoot 'License.rtf'
|
|
New-Item -ItemType Directory -Path $stagingRoot -Force | Out-Null
|
|
Write-LicenseRtf -Path $licenseRtf
|
|
|
|
Write-Host 'Building...' -ForegroundColor Cyan
|
|
|
|
$staging = Join-Path $stagingRoot 'x64'
|
|
|
|
# Both halves go into one folder: each of them looks for the other beside
|
|
# itself — the tray menu opens the settings window, and the settings window
|
|
# registers the agent for startup
|
|
foreach ($half in @($agentProject, $settingsProject)) {
|
|
Invoke-Tool -Path 'dotnet' -Arguments @(
|
|
'publish', $half,
|
|
'--configuration', 'Release',
|
|
'--runtime', 'win-x64',
|
|
'--self-contained', 'true',
|
|
"-p:Version=$Version",
|
|
'--output', $staging,
|
|
'--nologo'
|
|
)
|
|
}
|
|
|
|
# Debug symbols only make the download bigger; they are of no use to anyone
|
|
# who installs the application
|
|
Get-ChildItem $staging -Recurse -Filter '*.pdb' | Remove-Item -Force
|
|
|
|
$installer = Join-Path $installersPath "CursorLang-$Version-x64.msi"
|
|
|
|
Invoke-Tool -Path 'dotnet' -Arguments @(
|
|
'build', $installerProject,
|
|
'--configuration', 'Release',
|
|
# The architecture of the package is the architecture of what goes in it:
|
|
# a self-contained build fits nothing else
|
|
'-p:InstallerPlatform=x64',
|
|
# Handed over one by one rather than as a ready list of constants: a
|
|
# semicolon in a property value is where MSBuild stops reading it. The
|
|
# project gathers them into DefineConstants itself
|
|
"-p:CursorLangVersion=$Version",
|
|
"-p:PayloadDir=$staging",
|
|
"-p:IconFile=$icon",
|
|
"-p:LicenseFile=$licenseRtf",
|
|
"-p:OutputPath=$installersPath\",
|
|
"-p:OutputName=CursorLang-$Version-x64",
|
|
'--nologo'
|
|
)
|
|
|
|
if ($Install) {
|
|
Write-Host "Running $([System.IO.Path]::GetFileName($installer))..." -ForegroundColor Cyan
|
|
|
|
# Started the way a user would, with the wizard showing: the point of -Install
|
|
# is to see what the person on the other end sees
|
|
Start-Process 'msiexec.exe' -ArgumentList '/i', "`"$installer`"" -Wait
|
|
}
|
|
|
|
Write-Host ''
|
|
Write-Host 'Done.' -ForegroundColor Green
|
|
Write-Host " $installer"
|
|
|
|
Write-Host ''
|
|
Write-Host ' Nobody signed it, so Windows warns about an unknown publisher.'
|