From 3543f8acbffe9f5e0b99daf1dd913533c75b4b10 Mon Sep 17 00:00:00 2001 From: Kevin Harder Date: Tue, 13 Oct 2026 19:52:44 -0500 Subject: [PATCH 1/2] Consolidate WinGet release documentation --- README.md | 2 +- docs/architecture.md | 2 +- docs/index.md | 3 +-- docs/signing-and-distribution.md | 33 ++++++++++++++++++++++++++ docs/winget-submission.md | 40 -------------------------------- 5 files changed, 36 insertions(+), 44 deletions(-) delete mode 100644 docs/winget-submission.md diff --git a/README.md b/README.md index d184c60..17dbe08 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ **Recommended: download the portable ZIP** from [GitHub Releases](https://github.com/harder/wingetscout/releases). It includes `wingetscout.exe` and the companion files needed for the full WinGet COM experience. No .NET runtime or installer is required. -A WinGet community package is being prepared as `Harder.WinGetScout`. Use the release ZIP until the [community submission](https://github.com/harder/wingetscout/blob/main/docs/winget-submission.md) is accepted. +A WinGet community package has been submitted as `Harder.WinGetScout`. Use the release ZIP until the [community submission](https://github.com/microsoft/winget-pkgs/pull/451328) is accepted. After that package is accepted, `winget install -e --id Harder.WinGetScout` will install the ZIP into WinGet's managed portable directory and add `wingetscout` to your user `PATH`. Open a **new terminal** to use the command from any folder. The WinGet manifest already requests this behavior; it does not require a separate installer or manual PATH editing. WinGet verifies the downloaded ZIP hash, but it does not sign the executable. See [signing and distribution](https://github.com/harder/wingetscout/blob/main/docs/signing-and-distribution.md). diff --git a/docs/architecture.md b/docs/architecture.md index d404b99..6851f88 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -93,6 +93,6 @@ lock files cover the normal app, the MSIX Identity variant, and tests. `.github/workflows/ci.yml` builds and tests, while `.github/workflows/release.yml` publishes x64 and ARM64 assets, checksums, and attestations. The portable ZIP keeps the COM companion -files together. See the [WinGet submission runbook](winget-submission.md) +files together. See [release and WinGet updates](signing-and-distribution.md#releases-and-winget-updates) for the community package workflow and the [website guide](website.md) for the documentation site. diff --git a/docs/index.md b/docs/index.md index 32038c2..31e43a0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -7,7 +7,6 @@ Start with the [README](../README.md) for installation and a quick tour, or | --- | --- | | [Usage](usage.md) | Navigation, package actions, saved sets, and update checks | | [Architecture](architecture.md) | Backend, UI, workflow, Native AOT, and release code | -| [Signing and distribution](signing-and-distribution.md) | Portable and MSIX release plan and signing | -| [WinGet submission](winget-submission.md) | Community package manifest generation and validation | +| [Signing and distribution](signing-and-distribution.md) | Releases, WinGet manifest updates, and portable/MSIX signing | | [Directory submissions](directory-submissions.md) | Other listing and package directory submissions | | [Website](website.md) | Building the site and refreshing its screenshots | diff --git a/docs/signing-and-distribution.md b/docs/signing-and-distribution.md index 4d806d5..ceb1331 100644 --- a/docs/signing-and-distribution.md +++ b/docs/signing-and-distribution.md @@ -8,6 +8,39 @@ WinGet verifies the ZIP against `InstallerSha256`, extracts it into a managed po Signed **MSIX** is a later distribution option. It supplies Windows package identity for the out-of-process WinGet COM backend and needs a certificate trusted by the target PC. Its Native AOT build also ships `Microsoft.Management.Deployment.winmd` so WinRT can resolve the projected types; identity alone is insufficient. The release workflow builds and signs MSIX only when all signing settings below exist. At present it signs the MSIX package, **not** the portable ZIP's executable. The build modes and activation check are documented in the [README](../README.md#backends-and-capabilities). +## Releases and WinGet updates + +GitHub releases can ship while a WinGet submission is under review. Bump +`WinGetScout.csproj` to a new version, merge it into `main`, and push a matching +`v` tag on that commit. The release workflow checks the version and +main ancestry, stages and verifies all assets, and publishes the release. +Keep published assets immutable: an existing WinGet manifest's URLs and hashes +must continue to identify the same bytes. Publish a new version for fixes. + +For stable releases, the workflow downloads the published ZIPs back and saves +their three-file WinGet manifest set as the `winget-manifests-` workflow +artifact. To regenerate and validate that set locally: + +```powershell +$version = '1.0.2' # substitute an already published release +pwsh ./packaging/prepare-winget-submission.ps1 -Version $version +``` + +The helper requires `gh`, a GitHub login, and `winget`. Test installation, +`wingetscout --smoke`, `wingetscout --comdiag`, and uninstall in Windows Sandbox +using the published ZIPs. For a local-manifest install before catalog acceptance, +uninstall with `winget uninstall --manifest `; the final +community package ID may not yet resolve. See Microsoft's +[submission and Sandbox validation instructions](https://learn.microsoft.com/en-us/windows/package-manager/package/repository). + +Keep the package ID `Harder.WinGetScout`. Each WinGet PR contains only one +version's three YAML files under `manifests/h/Harder/WinGetScout//`. +If the initial package PR is still open, the recommended approach for shipping +the newest build first is to update that PR's branch with the new manifest set, +remove the previously proposed version's files, and update its title and test +notes. Validation must run again. If the earlier version has already merged, +submit the new version in a separate PR and retain the accepted version's files. + ## Get a publicly trusted signature for MSIX The workflow is wired to [Azure Artifact Signing](https://learn.microsoft.com/en-us/azure/artifact-signing/quickstart), previously called Azure Trusted Signing. Its Basic tier currently costs about US$10 per month; check [Microsoft's current pricing](https://learn.microsoft.com/en-us/azure/artifact-signing/how-to-change-sku) before creating an account. Public Trust is available to individual developers in the US and Canada, and to organizations in Microsoft's listed regions. For individual validation, the Azure billing account must be **Individual**, and its legal name and address must match the government ID used for verification. diff --git a/docs/winget-submission.md b/docs/winget-submission.md deleted file mode 100644 index 5df0a72..0000000 --- a/docs/winget-submission.md +++ /dev/null @@ -1,40 +0,0 @@ -# Publish Scout in WinGet - -The community package ID is `Harder.WinGetScout`. Submit the **portable ZIP** for each architecture. Each ZIP contains `wingetscout.exe` and the WinGet in-process COM DLLs in a stable `wingetscout/` folder. This path matters because scheduled update checks record the executable's absolute path. The standalone EXE lacks the COM DLLs; signed MSIX can be added later after testing. - -The installer manifest has `InstallerType: zip`, `NestedInstallerType: portable`, `PortableCommandAlias: wingetscout`, and `ArchiveBinariesDependOnPath: true`. WinGet installs the files in its managed per-user portable package directory and adds the executable's directory to the user `PATH`, so a new terminal can run `wingetscout` from anywhere. WinGet verifies the ZIP's SHA-256 hash; it does **not** provide a publisher signature or remove all Windows reputation warnings. No separate installer is needed. - -1. Merge and release a new Scout version with a matching `WinGetScout.csproj` `` and `v` tag. The release workflow builds and attests the ZIPs, publishes an immutable GitHub Release, downloads the published ZIPs back, and uploads a `winget-manifests-` workflow artifact containing the three-file manifest set. -2. Download that artifact from the successful release workflow run. The files are under `manifests/h/Harder/WinGetScout//`. To regenerate directly from the published ZIPs and validate in one command on Windows, run: - - ```powershell - $version = '1.0.1' # replace with the published release version - pwsh ./packaging/prepare-winget-submission.ps1 -Version $version - ``` - - The helper needs `gh`, `winget`, and a GitHub login with access to the public release. It downloads the exact published assets and uses [new-winget-manifest.ps1](../packaging/new-winget-manifest.ps1) to check the archive layout and compute SHA-256 values. The release workflow also verifies its published ZIPs are byte-for-byte identical to its build artifacts. Before submitting, inspect the generated URLs and hashes against the GitHub Release. -3. Test in Windows Sandbox. A clean Sandbox does not include WinGet, so first install it in a Sandbox PowerShell window using [Microsoft's documented bootstrap](https://learn.microsoft.com/en-us/windows/package-manager/winget/#install-winget-on-windows-sandbox): - - ```powershell - $ProgressPreference = 'SilentlyContinue' - Install-PackageProvider -Name NuGet -Force | Out-Null - Install-Module -Name Microsoft.WinGet.Client -Force -Repository PSGallery | Out-Null - Repair-WinGetPackageManager -AllUsers - winget --version - ``` - - Make the three YAML files available inside Sandbox, then run: - - ```powershell - $manifest = 'C:\ScoutInput\manifests' # change to the mapped manifest directory - winget validate --manifest $manifest - winget settings --enable LocalManifestFiles - winget install --manifest $manifest --accept-package-agreements --accept-source-agreements --disable-interactivity - ``` - - Open a **new terminal** and run `Get-Command wingetscout`, `wingetscout --smoke`, and `wingetscout --comdiag`. Before the package enters the community source, a local-manifest install is registered under WinGet's temporary `DefaultSource`. In the new terminal, set `$manifest` to the mapped directory again, then run `winget list --name 'Scout for WinGet' --exact` and `winget uninstall --manifest $manifest --disable-interactivity`. Confirm that `Get-Command wingetscout` no longer finds the alias. The final community package ID, `Harder.WinGetScout`, becomes usable with `winget list -e --id Harder.WinGetScout` and `winget uninstall -e --id Harder.WinGetScout` **after** the package is published in WinGet. Do not run install tests against an existing Scout data folder without backing it up. -4. Submit **only the three manifest YAML files** for one version in a PR to [microsoft/winget-pkgs](https://github.com/microsoft/winget-pkgs). Use the generated path `manifests/h/Harder/WinGetScout//`. Fork the repository, create a branch based on its current `master`, copy the three files into that path, and open a PR with the title `New package: Harder.WinGetScout version `. Check for an existing PR before opening another. Follow the repository CLA and [validation checks](https://github.com/microsoft/winget-pkgs/blob/master/doc/Validation.md); review the PR's Checks tab and respond to any bot feedback. Do not add the manifest files directly to the Scout release or advertise the WinGet command until that PR is accepted. - -5. For later releases, generate the next version's manifests and submit them to the same package ID. The `Harder.WinGetScout` package can later add signed MSIX installers only after their certificate subject, signature hash, identity, and upgrade behavior have been validated. - -The GitHub release must remain immutable after generating checksums. The release workflow stages all assets as a draft, checks their SHA-256 digests, and then publishes the complete release. It rejects reruns whenever a release for the tag already exists, including a draft left by a failed run. Inspect and remove an incomplete draft before retrying the tag; never replace assets on a published release, since that invalidates the community manifest. Publish a new version instead. See [Microsoft's authoring and validation guidance](https://github.com/microsoft/winget-pkgs/blob/master/doc/Authoring.md). From abe9acde9e08ee9dc765ab9eab2c5569f554dcf1 Mon Sep 17 00:00:00 2001 From: Kevin Harder Date: Tue, 13 Oct 2026 20:58:17 -0500 Subject: [PATCH 2/2] Preserve new-terminal alias verification in WinGet checklist --- docs/signing-and-distribution.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/signing-and-distribution.md b/docs/signing-and-distribution.md index ceb1331..2d0dc6f 100644 --- a/docs/signing-and-distribution.md +++ b/docs/signing-and-distribution.md @@ -26,9 +26,11 @@ $version = '1.0.2' # substitute an already published release pwsh ./packaging/prepare-winget-submission.ps1 -Version $version ``` -The helper requires `gh`, a GitHub login, and `winget`. Test installation, -`wingetscout --smoke`, `wingetscout --comdiag`, and uninstall in Windows Sandbox -using the published ZIPs. For a local-manifest install before catalog acceptance, +The helper requires `gh`, a GitHub login, and `winget`. Test installation in +Windows Sandbox using the published ZIPs. After installation, open a new terminal +so it sees the updated user `PATH`, and use `Get-Command wingetscout` to verify the +command alias resolves to the installed package. Run `wingetscout --smoke`, +`wingetscout --comdiag`, and test uninstall. For a local-manifest install before catalog acceptance, uninstall with `winget uninstall --manifest `; the final community package ID may not yet resolve. See Microsoft's [submission and Sandbox validation instructions](https://learn.microsoft.com/en-us/windows/package-manager/package/repository).