Skip to content

Show folder-mode discovery breadcrumb only at debug verbosity - #730

Merged
Nikola Metulev (nmetulev) merged 3 commits into
mainfrom
azchohfi-folder-mode-breadcrumb-debug
Aug 11, 2026
Merged

Show folder-mode discovery breadcrumb only at debug verbosity#730
Nikola Metulev (nmetulev) merged 3 commits into
mainfrom
azchohfi-folder-mode-breadcrumb-debug

Conversation

@azchohfi

Copy link
Copy Markdown
Contributor

Problem

winapp run printed this at Information level (the default verbosity) whenever the input resolved to a directory:

🔎 No .csproj/.sln/.slnx with a runnable app found in '<path>' — running it as a build-output folder.

That path isn't exceptional — it's what every dotnet run through the Microsoft.Windows.SDK.BuildTools.WinApp package does, because the targets point winapp at $(OutputPath). So a completely routine, successful run looked like something had gone wrong:

> dotnet run -- --devtools
Using launch settings from ...\launchSettings.json...
🔎 No .csproj/.sln/.slnx with a runnable app found in '...\net10.0-windows10.0.26100.0\win-x64' — running it as a build-output folder.
✅ 6F7000C9-...-285859963E7A_1z32rh13vfry6 launched (PID: 33808)

Change

One line — the breadcrumb moves from LogLevel.Information to LogLevel.Debug.

It isn't removed, because it still earns its place: it's how someone who pointed at a source directory expecting a build discovers why nothing was built. --verbose still shows it.

Tests

RunCommandTests runs at LogLevel.Debug (the level --verbose selects), so it structurally cannot observe what a default-verbosity run prints — a test added there would have passed before and after this change.

So there are two:

Test Level Asserts
RunCommand_FolderMode_AtDebugVerbosity_PrintsDiscoveryBreadcrumb Debug still reachable via --verbose
RunCommand_FolderMode_AtDefaultVerbosity_OmitsDiscoveryBreadcrumb Information hidden by default

The second lives in a small companion class pinned to LogLevel.Information, following the existing BuildToolsServicePrintErrorsTests pattern. I verified it genuinely pins the behavior by reverting the production line to Information and confirming it fails, then restoring it.

TestManifestContent changed privateinternal so the companion class can reuse it rather than duplicating the manifest XML.

Validation

10/10 tests pass in the affected area. Regression check confirmed the new test fails without the fix.

`winapp run` printed "No .csproj/.sln/.slnx with a runnable app found in
'<path>' - running it as a build-output folder." at Information level whenever
the input resolved to a directory.

That path is not exceptional. It is what every `dotnet run` through the
Microsoft.Windows.SDK.BuildTools.WinApp package does, because the targets point
winapp at $(OutputPath). The result was a scary-looking line on a completely
routine, successful run:

    > dotnet run -- --devtools
    No .csproj/.sln/.slnx with a runnable app found in '...\win-x64' - running
    it as a build-output folder.
    App launched (PID: 33808)

The message is still useful when someone points at a source directory expecting
a build and wants to know why nothing was built, so it moves to Debug rather
than being removed - `--verbose` still shows it.

RunCommandTests runs at LogLevel.Debug, so it cannot observe default-verbosity
output. A companion class pinned to LogLevel.Information covers the suppression;
it fails if the level is moved back to Information.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a209763e-7185-4986-bf0b-98e52c06b4be
Copilot AI balanced review requested due to automatic review settings August 11, 2026 21:53
Comment thread src/winapp-CLI/WinApp.Cli.Tests/RunCommandTests.cs Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Moves the folder-mode discovery breadcrumb to debug verbosity while retaining troubleshooting visibility via --verbose.

Changes:

  • Gates the breadcrumb on LogLevel.Debug.
  • Adds tests for debug and default verbosity behavior.
  • Reuses shared manifest test data.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
RunCommand.cs Restricts the breadcrumb to debug verbosity.
RunCommandTests.cs Verifies breadcrumb visibility at debug and Information levels.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Two review follow-ups:

- The check-docs gate requires a docs update alongside a CLI change. Because the
  breadcrumb is now debug-only, `docs/usage.md` explains how to surface it: the
  `winapp run` section already describes folder-vs-project mode selection, so the
  note lives there and points at --verbose for diagnosing an unexpected mode.

- Code-quality flagged Path.Combine for silently dropping earlier arguments when
  a later segment is rooted. Path.Join has no such behavior and is what the rest
  of the test project uses.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a209763e-7185-4986-bf0b-98e52c06b4be
@github-actions

Copy link
Copy Markdown
Contributor

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 38.62 MB 38.62 MB ✅ 0.0 KB (0.00%)
CLI (x64) 38.73 MB 38.73 MB ✅ 0.0 KB (0.00%)
MSIX (ARM64) 16.02 MB N/A N/A
MSIX (x64) 17.01 MB N/A N/A
NPM Package 33.42 MB N/A N/A
NuGet Package 33.45 MB N/A N/A

Test Results

4550 passed, 1 failed, 5 skipped out of 4556 tests in 665.2s (+2 tests, +20.1s vs. baseline)

Test Coverage

89.1% line coverage, 82.4% branch coverage · ✅ no change vs. baseline

CLI Startup Time

50ms median (x64, winapp --version) · ✅ no change vs. baseline


Updated 2026-08-11 22:24:35 UTC · commit 437b4de · workflow run

@nmetulev
Nikola Metulev (nmetulev) merged commit 2adc6ac into main Aug 11, 2026
31 of 32 checks passed
@nmetulev
Nikola Metulev (nmetulev) deleted the azchohfi-folder-mode-breadcrumb-debug branch August 11, 2026 22:47
Nikola Metulev (nmetulev) pushed a commit that referenced this pull request Aug 12, 2026
## Problem

`RunDotnetProcessAsync_Cancellation_KillsProcessTree` fails
intermittently on CI — it just took down `build-and-package` on #730,
which is a docs/logging-only PR:

```
System.IO.IOException: The process cannot access the file
'...\winapp_treekill_dff98ff32ad34e73be394cf6119af1dc.pid' because it is being used by another process.
   at System.IO.File.InternalReadAllTextAsync(...)
   at DotNetServiceTests.WaitForPidFileAsync(...) DotNetServiceTests.cs:1864
   at DotNetServiceTests.RunDotnetProcessAsync_Cancellation_KillsProcessTree() ...:1748
```

## Root cause

`WaitForPidFileAsync` polls for the PID file the spawned PowerShell root
writes with `Set-Content`:

```csharp
if (File.Exists(pidFile))
{
    var text = (await File.ReadAllTextAsync(pidFile, cancellationToken)).Trim();   // ← throws
```

`File.Exists` turns true the instant `Set-Content` **creates** the file,
but PowerShell still holds the write handle for a short window
afterwards. A read landing inside that window fails with a sharing
violation, and the exception escaped the polling loop instead of being
treated as "not ready yet".

Reproduced directly rather than inferred:

```powershell
$fs = [System.IO.File]::Open($pidFile, 'Create', 'Write', 'None')
[System.IO.File]::Exists($pidFile)      # True
[System.IO.File]::ReadAllText($pidFile) # IOException: ... being used by another process
```

That is exactly the CI error, and it explains why it's load-dependent:
the window is tiny, so it only loses the race on a busy agent.

## Fix

Catch the transient IO failure and keep polling. A sharing violation
here means "not written yet" — precisely the condition the loop already
exists to wait out.

An empty or partially written file needed no new handling: the existing
`int.TryParse` guard already keeps polling until the value parses.

## Validation

- Target test passed 3/3 locally after the change.
- `WaitForPidFileAsync` has exactly one caller, so the blast radius is
that one test.
- No docs needed: `check-docs` keys off `src/winapp-CLI/**/Commands/`,
and this is test-only.

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a209763e-7185-4986-bf0b-98e52c06b4be
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants