Add Windows MSI installer pipeline - #61
Open
portons wants to merge 19 commits into
Open
Conversation
portons
force-pushed
the
codex/windows-native-installer
branch
from
July 1, 2026 17:10
82a7220 to
94a425e
Compare
portons
force-pushed
the
codex/windows-native-installer
branch
from
July 1, 2026 17:13
94a425e to
8dd3dc5
Compare
portons
marked this pull request as ready for review
July 1, 2026 17:16
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a Windows MSI distribution channel for the Xyte CLI (WiX-based packaging + CI/release automation), and updates the CLI upgrade flow to detect the install channel and recommend/execute the appropriate updater (WinGet for MSI, npm for npm installs). It also introduces Windows-specific setup/migration guidance and validation scripts to keep the packaging surface area consistent.
Changes:
- Introduce install-channel detection (
install-channel.json/ env overrides) and propagateinstallChannelinto upgrade check/result contracts and CLI output. - Route upgrade recommendations/execution by install channel (WinGet for
windows-msi, npm fornpm). - Add Windows MSI packaging/signing scripts, validation checks, CI/release workflow steps, and documentation.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/upgrade.test.ts | Extends upgrade tests to cover install-channel-aware recommendations and WinGet upgrade execution. |
| tests/install-channel.test.ts | Adds coverage for install channel detection (default npm, MSI via install-channel.json). |
| tests/fixtures/golden/upgrade-check.json | Updates golden fixture to include installChannel. |
| tests/contracts.test.ts | Updates contract validation payload to include installChannel in upgrade result. |
| tests/cli-logging.test.ts | Minor test cleanup (let → const). |
| src/utils/install-channel.ts | Adds install-channel detection and parsing for MSI installs. |
| src/contracts/upgrade.ts | Extends upgrade schemas/contracts with installChannel and channel-specific recommendedCommand. |
| src/cli/upgrade.ts | Uses detected install channel to recommend and apply upgrades via npm vs WinGet. |
| src/cli/index.ts | Prints install channel in upgrade --check and upgrade text output. |
| skills/xyte-cli/schemas/upgrade-result.v1.schema.json | Adds installChannel to the shipped skill schema for upgrade result. |
| skills/xyte-cli/schemas/upgrade-check.v1.schema.json | Adds installChannel to the shipped skill schema for upgrade check. |
| scripts/validate_windows_packaging.mjs | Adds a metadata validation script to ensure key Windows packaging/docs markers exist. |
| scripts/sign_windows_msi.ps1 | Adds optional MSI Authenticode signing step for Windows runners. |
| scripts/package_windows_msi.mjs | Implements the MSI payload builder, WiX project generation, WinGet manifests, and optional signing. |
| README.md | Links Windows installer docs and clarifies Windows install guidance. |
| packaging/windows/scripts/configure-xyte-cli.ps1 | Adds a post-install setup/migration assistant (API key setup + npm migration). |
| packaging/windows/Product.wxs.template | Adds WiX template for MSI with PATH update and Start Menu shortcuts + first-run action. |
| package.json | Adds package:windows-msi and validate:windows-packaging scripts. |
| docs/windows-installer.md | New Windows installer documentation (install, migration, enterprise, updates, build). |
| docs/schemas/upgrade-result.v1.schema.json | Adds installChannel to documented upgrade-result schema. |
| docs/schemas/upgrade-check.v1.schema.json | Adds installChannel to documented upgrade-check schema. |
| docs/release.md | Documents Windows MSI release asset generation, signing, and WinGet submission notes. |
| docs/reference/commands.html | Adds reference note about installChannel and update commands. |
| docs/getting-started.md | Updates Windows Node install instructions (winget install -e --id ...). |
| docs/commands.md | Documents upgrade channel behavior and recommended commands. |
| .github/workflows/release-assets.yml | Adds Windows MSI build job and attaches MSI + WinGet manifests to releases/checksums. |
| .github/workflows/ci.yml | Adds a Windows CI job to validate packaging metadata and build the MSI artifact. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix the setup assistant readiness check: display readiness uncaptured,
gate on `setup status --field state` (the exit code carried no signal
and the -AllowFailure capture mixed stdout with the returned code),
and end with an explicit `exit 0`.
- Bump upgrade contracts to v2: freeze the published v1 schemas at their
original content and ship new v2 schemas with installChannel required,
instead of mutating v1 under an unchanged schemaVersion.
- Harden the Node runtime download cache: download via .partial + rename,
and evict poisoned cache files on checksum failure.
- Run one upgrade check per CLI invocation: compute checkForUpgrade
lazily so `upgrade --yes` no longer double-fetches the registry and
double-detects the install channel.
- Slim InstallChannel to {kind, packageId}: drop the dead updateCommand/
releaseUrl fields and share a single WINDOWS_MSI_PACKAGE_ID constant.
- Replace validator string-pins with real unit tests for parseArgs/
validateArgs/findExpectedSha256; move the release-needs invariant to a
workflow comment.
- Consolidate CI smokes: assert the MSI's machine PATH entry, publish it
via GITHUB_PATH once, and make the transcript recording the assistant
smoke (one execution instead of three).
- Verify Windows release assets are actually attached after publish.
- Restore the const lint fix in cli-logging.test.ts (lint fails without it).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dynamic file-URL import resolved differently under vitest on Windows and failed suite load with a SyntaxError. Use a static relative import (uniform vite transform pipeline on all platforms) with a declaration file for the plain .mjs script. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Windows runners check out with CRLF; a shebang line ending in CRLF makes vitest fail to load the .mjs with a bare SyntaxError, which broke tests/windows-packaging.test.ts on windows-latest. The scripts are only ever invoked via `node scripts/...`, so the shebangs were inert. Reproduced and verified under simulated CRLF checkout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add the missing CHANGELOG entry for the Windows MSI channel and the upgrade-contract v1 -> v2 compatibility boundary. - Evict the cached SHASUMS file too on checksum mismatch so a stale well-formed checksum list cannot loop fresh downloads into failure. - Relax $ErrorActionPreference around the npm migration probe: Windows PowerShell 5.1 turns redirected native stderr into terminating errors, so npm warnings could crash the assistant. - Pin the readiness "ready" comparison in the packaging validator (CI smoke only exercises the needs_setup branch). - Deduplicate the checkForUpgrade call in the upgrade handler. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three gaps the install smoke could not see: - Run the setup assistant under Windows PowerShell 5.1, the host real users get from the Start Menu (CI previously only exercised pwsh 7). - Resolve the installed Start Menu shortcuts via COM and execute their actual target/arguments, validating the WiX-generated quoting. - Exercise the npm migration path end to end: install the packed tarball as a global, run the assistant with -AssumeYes, and assert the global copy was removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a non-gating windows-installer-demo job that installs the MSI with the full msiexec UI - crossing the UILevel >= 5 gate so the Configure Xyte CLI custom action auto-launches, which the silent smoke cannot reach - while screen-recording the desktop with ffmpeg and capturing stills at each phase. The uploaded artifact lets a human watch the interactive install continuation without a Windows machine. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment on lines
65
to
69
| export function buildUpgradeCheck(args: { | ||
| packageName: string; | ||
| installChannel?: 'npm' | 'windows-msi'; | ||
| recommendedCommand?: string; | ||
| currentVersion: string; |
Comment on lines
72
to
+78
| const upToDate = compareSemver(args.currentVersion, args.latestVersion) >= 0; | ||
| const installChannel = args.installChannel ?? 'npm'; | ||
| const recommendedCommand = | ||
| args.recommendedCommand ?? | ||
| (installChannel === 'windows-msi' | ||
| ? 'winget upgrade --id Xyte.XyteCLI --exact' | ||
| : `npm install --global ${args.packageName}@latest`); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Validation
Notes