Build and release the launcher, agent, and setup
Overview · Architecture · Olympus integration · Operations
These instructions start in the root of the Olympus Launcher repository, alongside Olympus.Deployment.slnx. Commands are PowerShell. Examples use 1.0.1 as a new bootstrap release; replace it with the actual next release number. They do not build the real Olympus application from its separate repository.
Prepare the build machine
- Check out the intended source revision and open
Olympus.Deployment.slnxin Visual Studio. - Install the SDK selected by
global.json: .NET SDK 10.0.402, allowing the configured patch roll-forward. Confirm withdotnet --versionfrom this repository. - Ensure NuGet can reach
nuget.org;NuGet.Configselects that source. The projects restore the pinned WiX Toolset 7.0.0 SDK and its extensions automatically. A separate globalwixinstallation is not required for the normal build script. - For the default Native AOT agent, install Visual Studio's Desktop development with C++ tools, the Windows SDK, and compiler/linker libraries for each target CPU. A normal C# build succeeding does not prove that Native AOT publishing will succeed. Validate production binaries on each native CPU.
- For Visual Studio editing/build support of
.wixprojprojects, install HeatWave. It is optional when running the PowerShell build script through the .NET CLI. - Review the WiX binary-tools agreement and your organization's maintenance arrangements. The repository's
AcceptEula=wix7property records the project owner's acceptance. The scripts do not purchase tooling or configure signing certificates.
The launcher is always a self-contained managed WinForms single-file application, with trimming and Native AOT disabled. The agent defaults to Native AOT. -AgentMode Managed deliberately substitutes a self-contained managed single-file agent when native compiler tools are unavailable. Both modes avoid requiring an installed .NET runtime for these two bootstrap programs; prerequisites of the real Olympus application remain separate.
Choose and record the bootstrap version
- Choose a new three-part numeric version, for example
1.0.1. The MSI limits are255.255.65535. Application prerelease suffixes such as-preview1are not setup versions. - Update
<Version>inOlympus.Launcher/Olympus.Launcher.csprojandOlympus.Agent/Olympus.Agent.csprojto the intended bootstrap release. Their numeric assembly versions are what the running programs use for minimum-version checks. - Pass the same number explicitly as
-Versionto every packaging command. The script overrides the C#Versionand WiXSetupVersionproperties for that build. Keeping the project defaults current also makes ordinary Visual Studio builds report the expected version. - Record the source revision and release notes. Increase the release number whenever distributing changed bootstrap files, including changes in
Olympus.Deployment.Core.
minimumLauncherVersion and minimumAgentVersion in the application feed are minimum bootstrap requirements, not the Olympus application version. If a release needs newer bootstrap tools, make the new setup available before raising those minimums. Each running process enforces its own minimum; it does not silently upgrade itself.
Step 1: build and run the automated checks
In Visual Studio choose View → Terminal. Confirm the terminal's directory is the repository root, then run:
dotnet build Olympus.Deployment.slnx -c Release --disable-build-servers -m:1
if ($LASTEXITCODE -ne 0) { throw 'Solution build failed.' }
dotnet run --project tests/Olympus.Deployment.Tests.csproj -c Release --no-build
if ($LASTEXITCODE -ne 0) { throw 'Deployment checks failed.' }
The test suite is a console executable; use dotnet run, not dotnet test. Ordinary Build Solution builds the C# projects and tests. The two WiX projects are intentionally excluded from that operation because packaging needs architecture-specific published binaries.
The packaging script currently passes NuGetAudit=false to its child builds; a successful package build is therefore not a dependency vulnerability audit. Apply the organization's dependency review separately.
Step 2A: publish new launcher and agent binaries only
Use this route when you need the new published bootstrap executables before creating setup files:
.\scripts\Build-Installer.ps1 -Version 1.0.1 -PublishOnly
This publishes both CPUs, validates each executable's PE machine type, and checks that the output does not require loose DLL/JSON runtime files. It prints a separate absolute payload directory for each CPU:
artifacts/installer-payloads/1.0.1/x64/<unique-build-id>/
Launcher/Olympus.Launcher.exe
Agent/Olympus.Agent.exe
artifacts/installer-payloads/1.0.1/arm64/<unique-build-id>/
Launcher/Olympus.Launcher.exe
Agent/Olympus.Agent.exe
The unique folder prevents stale outputs from another publish or CPU entering a package. Retain the printed paths. PDB/XML outputs may also be present for development, but setup installs only the two EXEs.
For managed-agent development builds:
.\scripts\Build-Installer.ps1 -Version 1.0.1 -AgentMode Managed -PublishOnly
For only one target, add -Architecture x64 or -Architecture arm64. The script never silently falls back from Native AOT to managed output.
Step 2B: publish and create both setup variants
This is the usual end-to-end packaging command. It republishes both executables; running Step 2A first is not required.
.\scripts\Build-Installer.ps1 -Version 1.0.1
On a machine without the C++ toolchain, select the managed agent explicitly:
.\scripts\Build-Installer.ps1 -Version 1.0.1 -AgentMode Managed
The script publishes fresh Release payloads, validates them, cleanly rebuilds Olympus.Setup and its referenced MSI for each architecture, runs MSI contract checks, and writes build metadata. Output:
artifacts/installer/x64/
OlympusSetup-1.0.1-x64.exe
Olympus-1.0.1-x64.msi
build-info.json
artifacts/installer/arm64/
OlympusSetup-1.0.1-arm64.exe
Olympus-1.0.1-arm64.msi
build-info.json
Distribute the EXE for the branded user experience. The MSI is available for managed deployment and standard Windows Installer UI. Olympus.Setup is the wrapper; Olympus.Installer is the actual file/registration package. Do not distribute the payload folder as a substitute for an installation.
build-info.json records version, CPU, agent mode, build time, payload path, unsigned status, and SHA-256 hashes of the EXE/MSI. It is overwritten for that CPU on the next successful build, so archive it with the release. It contains a build-machine path: use release-approved metadata if publishing it beyond the engineering audience. Signing changes file hashes; refresh release checksums after signing.
Step 3: add a Visual Studio menu command
- Open Tools → External Tools → Add.
- Set Title to
Build Olympus Installers. - Set Command to
powershell.exe(or browse to the team's installed PowerShell executable). - Set Initial directory to
$(SolutionDir). - Enter these Arguments for a managed-agent build:
-NoProfile -ExecutionPolicy Bypass -File "$(SolutionDir)scripts\Build-Installer.ps1" -Version 1.0.1 -AgentMode Managed
- Check Use Output window and save the entry.
- Select Tools → Build Olympus Installers whenever a new package build is needed. Update its version argument for each release. For production Native AOT builds, remove
-AgentMode Managedafter installing the native tools.
The execution-policy argument applies to this PowerShell invocation; it does not change the machine's stored policy. If company policy prescribes another approved script invocation, use that. See Visual Studio external tools.
The menu entry is a developer's Visual Studio setting, not part of the solution. A teammate must create it once, or run the equivalent command in the integrated terminal. Right-clicking a WiX project does not perform the script's publish stage; on a clean checkout it will report missing payloads.
Step 4: validate the compiled packages
The script already runs these checks; they can also be repeated against an archived MSI:
.\scripts\Test-Installer.ps1 -Path .\artifacts\installer\x64\Olympus-1.0.1-x64.msi -Architecture x64
.\scripts\Test-Installer.ps1 -Path .\artifacts\installer\arm64\Olympus-1.0.1-arm64.msi -Architecture arm64
They read MSI tables without installing anything: publisher, scope, CPU, payloads, registry ownership, logon command, safe protocol command, taskbar shortcut identity, data preservation, and post-commit agent startup. WiX's ICE validation also runs during MSI builds. Windows Installer must be available; a restricted sandbox may block validation. Do not treat disabling ICE validation as a release fix. Only ICE91 is intentionally suppressed because this product installs into the current user's LocalAppData.
Install/upgrade tests are different from these table checks. Run the native-machine acceptance matrix for both CPUs, including repair, running-agent upgrades, uninstall/reinstall, taskbar pinning, and DPI checks. Close setup preview windows and stop debugging setup before rebuilding to avoid locked EXEs.
Step 5: sign and distribute
The checked-in build script produces unsigned files and has no certificate or signing target. Before a production release, integrate the organization's Authenticode signing process in this order:
- Publish launcher/agent payloads and sign them before packaging.
- Build the MSI from those signed payloads, then sign the MSI.
- Build the Burn EXE from that signed MSI.
- Detach and sign the Burn engine, reattach it, then sign the full EXE.
- Verify signatures, rerun package/release checks, and calculate final checksums.
- Archive the approved source revision, both CPU artifacts, matching payloads/symbols as required, agent mode, verification results, and final metadata.
- Publish the matching EXE download for each supported CPU through the approved company distribution channel. Publish the MSI separately only where IT deployment needs it.
These are signing integration requirements, not steps the current script automates. Simply signing the outer EXE is insufficient; see WiX's signing sequence. Re-running the full build script after signing would republish/rebuild unsigned files, so insert signing into the pipeline rather than signing intermediate files and then starting the script over.
Keep the MSI and bundle UpgradeCodes stable. Same-version duplicate MSI installations and downgrades are blocked. For a CPU switch, distribute a higher bootstrap release or uninstall/reinstall as described in the installer guide. Do not distribute a rebuilt, changed payload under an already released version.
Separate procedure: release the real Olympus application
This repository does not build or upload the production Olympus application and does not publish service responses. The application/service owners complete these steps in their own release systems:
- Build Olympus for its supported Windows deployment targets. Include all required binaries/resources and the application integration changes.
- Choose a new immutable application version and a consistent spelling of it. Application versions can have three/four numeric components and optional
-alphaNor-previewNstages; setup versions cannot. - Place the full application output at the root of a ZIP, with the declared executable at its relative path. Do not put the contents underneath an extra enclosing version folder. Do not include
Dataor a generated.deployment-receipt.json. - Hash the final ZIP and upload it to an immutable HTTPS location without redirects or embedded credentials.
- Publish the matching per-architecture deployment response, minimum application/bootstrap versions, prerequisite declarations, and data compatibility ID. The current client always requests channel
0; a version suffix does not select a different channel. - Test first installation, upgrade, offline use, startup failure, and safe update notification against the published representation before widening rollout.
For example, after placing a real x64 application payload in the stated staging folder:
$payload = Resolve-Path .\artifacts\olympus-payload\win-x64
$zip = Join-Path $PWD 'artifacts\Olympus-2026.10.5-win-x64.zip'
if (Test-Path -LiteralPath $zip) { throw 'Choose a new immutable release output.' }
Compress-Archive -Path (Join-Path $payload '*') -DestinationPath $zip
Get-FileHash -LiteralPath $zip -Algorithm SHA256
These paths are illustrative staging locations; the payload must already exist. The resulting hash belongs in package.sha256. Review hidden files and deployment content when selecting a ZIP tool; verify the complete packaged application, not just the entry EXE. See the service contract for transport and package rules. New-TestDeployment.ps1 generates only the dummy fixture and currently accepts numeric versions; it is not the production application release pipeline.