Fix #463 and #464: surface progress and stop lying about why init skipped SDK setup#484
Merged
Conversation
On a fresh machine, `winapp init` could hang silently for ~30s after
answering the manifest-overwrite prompt. The next step (`AskSdkInstallModeAsync`)
performed two slow network/IO operations with no visible output:
1. `dotNetService.HasPackageReferenceAsync(csproj, "Microsoft.WindowsAppSDK")`,
which runs `dotnet list package --format json` and triggers an implicit
`dotnet restore` on a cold NuGet cache.
2. `Task.WhenAll` over 6 parallel NuGet feed queries (3 modes × 2 packages)
to label the SDK install prompt.
Both happened before any prompt or status output, and the early-exit when
the project already references WinAppSDK only logged at Debug level, so the
user saw nothing at all.
Changes:
* `DotNetService.HasPackageReferenceAsync`: try a fast XPath-style XDocument
scan of the csproj for an inline `<PackageReference Include="..."/>` first.
Only positive matches short-circuit; absence still falls back to
`dotnet list package` because Directory.Packages.props / SDK-imported
packages aren't visible in the raw csproj.
* `WorkspaceSetupService`: wrap the slow ops in a Spectre `Status` spinner
(with a graceful log-line fallback when output is redirected or
Information logging is off).
* Promote the "project already references WinAppSDK; skipping setup" log
from Debug to Information so the user knows why we proceeded silently.
Tests: 766/766 passing. Two new unit tests cover the XML fast path
(inline PackageReference + case-insensitive Include attribute).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
WorkspaceSetupService printed 'SDK installation skipped by user choice' whenever options.SdkInstallMode == None at the end of init. That fired even when the .NET path auto-set it to None because the project already references Microsoft.WindowsAppSDK, which is not a 'user choice'. The specific reason is now logged where the decision is made: * AskSdkInstallModeAsync logs the auto-skip line for .NET projects * The interactive prompt logs 'Setup SDKs: Do not setup SDKs' * --setup-sdks=none is the user's own input and needs no echo so the trailing 'by user choice' line was redundant as well as wrong. Delete it (and the matching unreachable LogDebug for non-.NET projects). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Improves winapp init user experience by surfacing progress during slow SDK-detection/version lookups and by correcting misleading messaging when Windows App SDK setup is skipped.
Changes:
- Add Spectre.Console status spinners (with fallback messaging) around slow SDK reference detection and NuGet version fetches.
- Add a fast XML scan path for detecting inline
<PackageReference />in.csprojfiles before falling back todotnet list package. - Remove/adjust “skipped by user choice” messaging so skip reasons aren’t misattributed.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/winapp-CLI/WinApp.Cli/Services/WorkspaceSetupService.cs | Adds status spinner wrapper for long-running init steps and refines skip logging to avoid misleading output. |
| src/winapp-CLI/WinApp.Cli/Services/DotNetService.cs | Adds a fast XML-based check for inline PackageReference to avoid slow dotnet list package on cold machines. |
| src/winapp-CLI/WinApp.Cli.Tests/DotNetServiceTests.cs | Adds unit tests covering the new XML fast path behavior. |
| docs/npm-usage.md | Updates npm usage docs to reflect manifest filename support text. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Contributor
Build Metrics ReportBinary Sizes
Test Results✅ 766 passed out of 766 tests in 373.0s (+2 tests, -84.8s vs. baseline) Test Coverage❌ 20.8% line coverage, 35.1% branch coverage · ✅ no change vs. baseline CLI Startup Time38ms median (x64, Updated 2026-04-20 23:43:54 UTC · commit |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
zateutsch
approved these changes
Apr 21, 2026
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.
Closes #463 and #464.
#463 —
winapp initcan be silent for ~30s on a fresh machineAfter answering "No" to the manifest-overwrite prompt,
AskSdkInstallModeAsyncperformed two slow operations with no visible output:dotNetService.HasPackageReferenceAsync(csproj, "Microsoft.WindowsAppSDK")runsdotnet list package --format json, which triggers an implicitdotnet restoreon a cold NuGet cache (30s+ for projects like AI Dev Gallery).Task.WhenAllover 6 parallel NuGet feed queries (3 modes × 2 packages) used to label the SDK install prompt.Both happened before any prompt was rendered, and the early-exit when the project already references WinAppSDK only logged at Debug level — so the user saw nothing at all.
Fixes:
DotNetService.HasPackageReferenceAsync: try a fastXDocumentscan of the.csprojfor an inline<PackageReference Include="…"/>first. Only positive matches short-circuit; absence still falls back todotnet list packagebecause Directory.Packages.props / SDK-imported packages aren't visible in the raw csproj.WorkspaceSetupService: wrap the slow ops in a SpectreStatusspinner ("Detecting project SDK references…" / "Fetching latest SDK versions…"), with a log-line fallback when output is redirected or Information logging is off.#464 —
winapp initsays "SDK installation skipped by user choice" when it wasn'tWorkspaceSetupServicealways printedSDK installation skipped by user choicewheneveroptions.SdkInstallMode == None. That fires even when the .NET path auto-sets None because the project already references WinAppSDK — not a user choice.Fix: delete the trailing "by user choice" line. The actual reason is now logged at the decision site:
AskSdkInstallModeAsynclogs the auto-skip line ("Project already references Microsoft.WindowsAppSDK; skipping Windows App SDK setup.") in the .NET case.Setup SDKs: Do not setup SDKswhen the user picks that option.--setup-sdks=noneis the user's own input and needs no echo.The matching unreachable
LogDebugfor non-.NET projects was removed for the same reason.Tests
HasPackageReferenceAsync(inlinePackageReference+ case-insensitiveIncludeattribute).scripts/build-cli.ps1 -SkipMsix -SkipNpm -SkipTestsclean (an unrelated stale regen ofdocs/npm-usage.mdcame along).