Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f54cd9b
wip - msix
Jun 1, 2026
87e5289
Add target-size 16/20/44 tray icon PNGs from PR #468
Jun 5, 2026
fca1e37
Phase 2: drop -p:Unpackaged=true from WinUI csproj
Jun 5, 2026
e443c3c
Phase 3A: Remove Inno installer (MSIX-primary cleanup)
Jun 5, 2026
c47575d
Phase 3B: Remove Updatum (GitHub-Release-ZIP in-app updater)
Jun 5, 2026
c385ddf
Fix: register toast COM activator in Package.appxmanifest
Jun 5, 2026
bf8c247
build.ps1: hard-fail -PackageMsix when dev signing cert is missing
Jun 6, 2026
c04a7f6
cleanup
Jun 9, 2026
8b4bf80
fix notifications in appxmanifest
Jun 9, 2026
83d1613
Phase 4: AppInstaller stable feed + render/validate scripts + feed PR…
Jun 9, 2026
2aa4d3d
Phase 4: adopt MSBuild default MSIX naming for release assets
Jun 9, 2026
c0b9cc5
Phase 5: sign and publish MSIX release artifacts
Jun 9, 2026
ccb9343
Phase 6: retire loose-tray build pipeline
Jun 9, 2026
57b9ccc
chore(msix): update stale master->main branch references
Jun 9, 2026
98f03c7
ci(msix): run GitVersion in build-msix so MSIX payload carries SemVer
Jun 9, 2026
c4f5d62
ci(msix): TEMP unblock build-msix from needs:[test, e2etests] for fas…
Jun 9, 2026
91f6f3f
ci(msix): use 'dotnet publish' so VC++ runtime is copied into the MSI…
Jun 9, 2026
b51787e
build(msix): register VC++ runtime as ResolvedFileToPublish so it lan…
Jun 9, 2026
2516bd3
build(msix): version MSIX from GitVersion instead of the SDK default …
Jun 10, 2026
68dac18
ci(msix): TEMP disable GitHub Release creation; upload signed MSIX as…
Jun 10, 2026
9f195d6
ci(msix): TEMP skip Verify tag version output for msixtest signing re…
Jun 10, 2026
9777606
ci(msix): TEMP AppInstaller silent-update rehearsal infrastructure
Jun 10, 2026
f4e29dd
ci(msix): pivot rehearsal to SemVer-patch bump (0.6.4 -> 0.6.5), drop…
Jun 10, 2026
8d40aaa
msixtest: bump AppInstaller schema to 2021 to fix LogHr 8007000D "dat…
Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions .github/workflows/appinstaller-feed-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
name: AppInstaller Feed PR

on:
workflow_dispatch:
inputs:
tag:
description: Release tag whose signed MSIX assets should advance the stable AppInstaller feed
required: true
type: string

permissions:
contents: write
pull-requests: write

jobs:
update-feed:
runs-on: windows-latest

steps:
- uses: actions/checkout@v6
with:
ref: main
fetch-depth: 0

- name: Render stable AppInstaller feed files
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
$ErrorActionPreference = 'Stop'

$repo = '${{ github.repository }}'
$tag = '${{ inputs.tag }}'.Trim()
if ([string]::IsNullOrWhiteSpace($tag)) {
throw "tag input is required."
}
if (-not $tag.StartsWith('v', [StringComparison]::OrdinalIgnoreCase)) {
throw "Release tag must start with 'v'. Got '$tag'."
}
if ($tag.Contains('-')) {
throw "Pre-release AppInstaller feed updates are blocked until alpha channel policy is decided. Tag: $tag"
}

$release = gh release view $tag --repo $repo --json tagName,isPrerelease,assets | ConvertFrom-Json
if ($release.isPrerelease) {
throw "Pre-release AppInstaller feed updates are blocked until alpha channel policy is decided. Tag: $tag"
}

$versionText = $tag.Substring(1)
if ($versionText -notmatch '^\d+\.\d+\.\d+$') {
throw "Stable release tag must be vX.Y.Z so the MSIX/AppInstaller version can be rendered as X.Y.Z.0. Got '$tag'."
}
$version = "$versionText.0"
$publisher = 'CN=OpenClaw Foundation, O=OpenClaw Foundation, L=Mill Valley, S=California, C=US'
$identityName = 'OpenClaw.Companion'
$feedDir = 'installer\appinstaller'
New-Item -ItemType Directory -Force -Path $feedDir | Out-Null

function Get-RequiredAsset {
param([Parameter(Mandatory)] [string] $Pattern)
$matches = @($release.assets | Where-Object { $_.name -like $Pattern })
if ($matches.Count -ne 1) {
$available = ($release.assets | ForEach-Object { $_.name }) -join ', '
throw "Expected exactly one release asset matching '$Pattern' for $tag; found $($matches.Count). Assets: $available"
}
return $matches[0]
}

function Get-ReleaseAssetUri {
param([Parameter(Mandatory)] [string] $AssetName)
$escapedName = [Uri]::EscapeDataString($AssetName)
return "https://github.com/$repo/releases/download/$tag/$escapedName"
}

$x64Asset = Get-RequiredAsset -Pattern "OpenClaw.Companion_${version}_x64.msix"
$arm64Asset = Get-RequiredAsset -Pattern "OpenClaw.Companion_${version}_arm64.msix"
$x64Uri = Get-ReleaseAssetUri -AssetName $x64Asset.name
$arm64Uri = Get-ReleaseAssetUri -AssetName $arm64Asset.name

$rawBase = "https://raw.githubusercontent.com/$repo/main/installer/appinstaller"
$x64FeedPath = Join-Path $feedDir 'openclaw-x64.appinstaller'
$arm64FeedPath = Join-Path $feedDir 'openclaw-arm64.appinstaller'

.\scripts\render-appinstaller.ps1 `
-Version $version `
-Publisher $publisher `
-IdentityName $identityName `
-ProcessorArchitecture x64 `
-MsixUri $x64Uri `
-AppInstallerUri "$rawBase/openclaw-x64.appinstaller" `
-OutputPath $x64FeedPath

.\scripts\render-appinstaller.ps1 `
-Version $version `
-Publisher $publisher `
-IdentityName $identityName `
-ProcessorArchitecture arm64 `
-MsixUri $arm64Uri `
-AppInstallerUri "$rawBase/openclaw-arm64.appinstaller" `
-OutputPath $arm64FeedPath

.\scripts\validate-appinstaller-hosting.ps1 `
-AppInstallerPath $x64FeedPath `
-MsixUri $x64Uri `
-AllowGitHubContentTypes
.\scripts\validate-appinstaller-hosting.ps1 `
-AppInstallerPath $arm64FeedPath `
-MsixUri $arm64Uri `
-AllowGitHubContentTypes

$branch = "automation/appinstaller-feed-$($tag -replace '[^A-Za-z0-9._-]', '-')"
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git checkout -B $branch
git add $feedDir

$changes = git status --short -- $feedDir
if ([string]::IsNullOrWhiteSpace($changes)) {
Write-Host "Stable AppInstaller feed already points at $tag; no PR needed."
exit 0
}

git commit -m "chore(msix): update AppInstaller feed for $tag" `
-m "Advance the stable Windows AppInstaller feed to the signed MSIX assets from $tag." `
-m "Merging this PR advances the auto-update source for installed MSIX clients."
git push --force-with-lease origin $branch

$bodyPath = Join-Path $env:RUNNER_TEMP 'appinstaller-feed-pr.md'
$body = @"
Updates the stable Windows AppInstaller feed files for ``$tag``.

Merging this PR advances installed MSIX clients that poll the stable feed:

- x64 feed: ``$rawBase/openclaw-x64.appinstaller``
- ARM64 feed: ``$rawBase/openclaw-arm64.appinstaller``
- x64 MSIX: ``$x64Uri``
- ARM64 MSIX: ``$arm64Uri``

Validation performed:

- Rendered both feed files from ``scripts/render-appinstaller.ps1``
- Parsed local AppInstaller XML before publishing
- Validated GitHub release MSIX headers with candidate GitHub content-type compatibility enabled
- Blocked pre-release/alpha feed updates until channel policy is decided

Note: the MSIX is built with ``WindowsAppSDKSelfContained=true``, so the feed
intentionally omits any ``<Dependencies>`` block — Windows installs the runtime
bundled inside the .msix and never fetches a separate framework package.
"@
Set-Content -Path $bodyPath -Value $body -Encoding UTF8

$existingPr = gh pr list --repo $repo --base main --head $branch --json number --jq '.[0].number'
if ([string]::IsNullOrWhiteSpace($existingPr)) {
gh pr create `
--repo $repo `
--base main `
--head $branch `
--title "chore(msix): update AppInstaller feed for $tag" `
--body-file $bodyPath
}
else {
gh pr edit $existingPr `
--repo $repo `
--title "chore(msix): update AppInstaller feed for $tag" `
--body-file $bodyPath
}
Loading
Loading