Skip to content

Commit c226db9

Browse files
committed
feat(msix): generate App Installer file for automatic updates
Generate an install-{arch}.appinstaller file alongside each MSIX package. The file lives at the stable CDN URL (releases/latest) and points to the immutable versioned MSIX, so Windows App Installer checks for updates on launch (daily) and via a background task, updating silently without user interaction. The release workflow uploads the .appinstaller files as release assets and to the CDN with the application/appinstaller content type. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X95PpvsxLn7q5S54kTPYhY
1 parent 8be5a13 commit c226db9

4 files changed

Lines changed: 82 additions & 3 deletions

File tree

.github/workflows/release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ jobs:
132132
name: msix-artifact-${{ matrix.arch }}
133133
path: |
134134
packages/msix/out/install-${{ matrix.arch }}.msix
135+
packages/msix/out/install-${{ matrix.arch }}.appinstaller
135136
release:
136137
runs-on: ubuntu-latest
137138
needs:
@@ -149,7 +150,9 @@ jobs:
149150
run: |
150151
echo v${{ needs.changelog.outputs.version }} > version.txt
151152
az storage blob upload-batch --destination releases/v${{ needs.changelog.outputs.version }} --source .
153+
az storage blob upload-batch --destination releases/v${{ needs.changelog.outputs.version }} --overwrite true --source . --pattern "*.appinstaller" --content-type "application/appinstaller"
152154
az storage blob upload-batch --destination releases/latest --overwrite true --source .
155+
az storage blob upload-batch --destination releases/latest --overwrite true --source . --pattern "*.appinstaller" --content-type "application/appinstaller"
153156
- name: Create draft release 📝
154157
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228
155158
with:

packages/msix/README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,24 @@ the repository's `dist` folder.
1515
./build.ps1 -Architecture x64 -Version "1.3.37"
1616
```
1717

18-
The package is created at `out/install-x64.msix`.
18+
The package is created at `out/install-x64.msix`, along with an App Installer
19+
file at `out/install-x64.appinstaller`.
20+
21+
The `.appinstaller` file references the published package on the CDN and enables
22+
automatic updates: Windows re-checks the stable URL it was installed from
23+
(daily on launch and via a background task) and updates the package silently
24+
when a new version is available.
1925

2026
## Install the package
2127

2228
```powershell
2329
Add-AppxPackage -Path ./out/install-x64.msix
2430
```
2531

32+
## Install via App Installer (with auto-update)
33+
34+
```powershell
35+
Add-AppxPackage -AppInstallerFile https://cdn.ohmyposh.dev/releases/latest/install-x64.appinstaller
36+
```
37+
2638
[Windows SDK]: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/

packages/msix/build.ps1

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
.PARAMETER Copy
2222
When specified, copies the appropriate executable from the dist folder before packaging.
2323
24+
.PARAMETER DownloadUrl
25+
The base URL where releases are published, used in the generated App Installer file.
26+
Defaults to "https://cdn.ohmyposh.dev/releases".
27+
2428
.EXAMPLE
2529
.\build.ps1 -Architecture x64 -Version "1.2.3" -Copy
2630
@@ -32,7 +36,7 @@
3236
Creates and signs the MSIX package for arm64 architecture with version 1.2.3.
3337
3438
.OUTPUTS
35-
Creates install-{Architecture}.msix in the 'out' directory.
39+
Creates install-{Architecture}.msix and install-{Architecture}.appinstaller in the 'out' directory.
3640
3741
.NOTES
3842
Requires the Windows SDK for MSIX packaging and signing.
@@ -56,7 +60,11 @@ param(
5660
[switch]$Sign,
5761

5862
[Parameter()]
59-
[switch]$Copy
63+
[switch]$Copy,
64+
65+
[Parameter()]
66+
[ValidateNotNullOrEmpty()]
67+
[string]$DownloadUrl = "https://cdn.ohmyposh.dev/releases"
6068
)
6169

6270
# Set error handling preferences
@@ -226,6 +234,35 @@ catch {
226234
throw
227235
}
228236

237+
Write-Verbose "Creating App Installer file" -Verbose
238+
239+
try {
240+
$appInstallerPath = "$currentPath/out/install-$Architecture.appinstaller"
241+
$identity = $manifestDocument.Package.Identity
242+
243+
# The App Installer file lives at a stable URL so Windows can poll it for updates,
244+
# while the package URL is immutable per version to avoid mid-publish races.
245+
$appInstaller = @"
246+
<?xml version="1.0" encoding="utf-8"?>
247+
<AppInstaller xmlns="http://schemas.microsoft.com/appx/appinstaller/2018" Version="$Version.0" Uri="$DownloadUrl/latest/install-$Architecture.appinstaller">
248+
<MainPackage Name="$($identity.Name)" Version="$Version.0" Publisher="$($identity.Publisher)" ProcessorArchitecture="$Architecture" Uri="$DownloadUrl/v$Version/install-$Architecture.msix" />
249+
<UpdateSettings>
250+
<OnLaunch HoursBetweenUpdateChecks="24" />
251+
<AutomaticBackgroundTask />
252+
<ForceUpdateFromAnyVersion>true</ForceUpdateFromAnyVersion>
253+
</UpdateSettings>
254+
</AppInstaller>
255+
"@
256+
257+
$appInstaller | Out-File -FilePath $appInstallerPath -Encoding UTF8
258+
259+
Write-Verbose "Created App Installer file: $appInstallerPath" -Verbose
260+
}
261+
catch {
262+
Write-Error "Failed to create App Installer file: ${_}"
263+
throw
264+
}
265+
229266
if ($Sign) {
230267
$signingTools = Initialize-SigningEnvironment -SDKVersion $SDKVersion
231268
Invoke-PackageSigning -PackagePath $msixPackagePath -SigningTools $signingTools

website/docs/installation/windows.mdx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ When using oh-my-posh inside the WSL, make sure to follow the [Linux][linux] ins
2929
values={[
3030
{ label: 'winget', value: 'winget', },
3131
{ label: 'manual', value: 'manual', },
32+
{ label: 'App Installer', value: 'appinstaller', },
3233
{ label: 'chocolatey', value: 'chocolatey'},
3334
]
3435
}>
@@ -49,6 +50,21 @@ Open a PowerShell prompt and run the following command:
4950
Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://ohmyposh.dev/install.ps1'))
5051
```
5152

53+
</TabItem>
54+
<TabItem value="appinstaller">
55+
56+
Installing via App Installer keeps Oh My Posh up to date automatically:
57+
Windows checks for a new version in the background and updates the package
58+
without any interaction needed.
59+
60+
Open a PowerShell prompt and run the following command:
61+
62+
```powershell
63+
Add-AppxPackage -AppInstallerFile https://cdn.ohmyposh.dev/releases/latest/install-x64.appinstaller
64+
```
65+
66+
For ARM64, use `install-arm64.appinstaller` instead.
67+
5268
</TabItem>
5369
<TabItem value="chocolatey">
5470

@@ -76,6 +92,7 @@ choco install oh-my-posh
7692
values={[
7793
{ label: 'winget', value: 'winget', },
7894
{ label: 'manual', value: 'manual', },
95+
{ label: 'App Installer', value: 'appinstaller', },
7996
{ label: 'chocolatey', value: 'chocolatey'},
8097
]
8198
}>
@@ -87,6 +104,16 @@ Open a PowerShell prompt and run the following command:
87104
winget upgrade JanDeDobbeleer.OhMyPosh --source winget
88105
```
89106

107+
</TabItem>
108+
<TabItem value="appinstaller">
109+
110+
No action needed, Windows updates Oh My Posh automatically in the background.
111+
To force an update check, run the install command again:
112+
113+
```powershell
114+
Add-AppxPackage -AppInstallerFile https://cdn.ohmyposh.dev/releases/latest/install-x64.appinstaller
115+
```
116+
90117
</TabItem>
91118
<TabItem value="manual">
92119

0 commit comments

Comments
 (0)