Skip to content

Update FindSolutionFilesAtOrAbovePath to prioritize *.slnx over *.sln found in parent directories - #55048

Merged
MichaelSimons merged 1 commit into
mainfrom
michaelsimons/fix-flaky-postaction-sln-not-found
Jun 29, 2026
Merged

Update FindSolutionFilesAtOrAbovePath to prioritize *.slnx over *.sln found in parent directories#55048
MichaelSimons merged 1 commit into
mainfrom
michaelsimons/fix-flaky-postaction-sln-not-found

Conversation

@MichaelSimons

@MichaelSimons MichaelSimons commented Jun 28, 2026

Copy link
Copy Markdown
Member

Root Cause

The FindSolutionFilesAtOrAbovePath method in DotnetSlnPostActionProcessor used a two-pass strategy:

  1. First, search the entire parent directory chain for *.sln files
  2. Only if no .sln file is found anywhere up to the root, search for *.slnx

Since dotnet new sln now creates .slnx files by default, the *.sln search would walk all the way up from the output directory to the filesystem root. If a stale or unrelated .sln file existed in any ancestor directory (from parallel tests, other repos, the CI workspace, etc.), it would be returned instead of the .slnx in the output directory. When that transient file was subsequently deleted by another process between the search and the File.Exists validation in PathUtility.EnsureAllPathsExist, the error "Failed to add project(s) to the solution: File <path>.sln not found." occurred.

Additionally, on Windows, Directory.EnumerateFileSystemEntries(dir, "*.sln") can match .slnx files through the legacy FindFirstFile 8.3 short-name matching behavior. While .NET's managed filter usually rejects these, the behavior can vary across configurations.

Fix

Changed FindSolutionFilesAtOrAbovePath to search for both .sln and .slnx at each directory level before walking up to the parent. This ensures:

  • A .slnx in the output directory is found immediately without searching ancestors
  • .sln is still preferred over .slnx when both exist at the same level
  • Explicit EndsWith filtering guards against Windows legacy glob matching

Testing

  • All existing DotnetSlnPostActionTests pass (14 tests)
  • Added new test AddProjectToSolutionPostActionPrefersNearbySlnxOverDistantSln that specifically verifies the fix: a .slnx in the output directory is found even when a .sln exists in a parent directory

Related to #54942

The FindSolutionFilesAtOrAbovePath method previously searched the entire
parent directory chain for *.sln files before ever looking for *.slnx.
Since 'dotnet new sln' now creates .slnx files by default, this meant
the search would walk all the way up to the root for *.sln. If a stale
or unrelated .sln file existed in any ancestor directory (from parallel
tests, other repos, etc.), it would be returned instead of the .slnx in
the output directory. When that file was subsequently deleted by another
process, File.Exists would fail with 'File not found'.

Fix: Search for both .sln and .slnx at each directory level before
walking up to the parent. This ensures a .slnx in the output directory
is found immediately, preventing the search from walking up into
unrelated directories. Also add explicit extension filtering to guard
against Windows legacy glob matching behavior where *.sln can match
*.slnx via 8.3 short name patterns.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@baronfel

Copy link
Copy Markdown
Member

I suspect the previous behavior was intended to be defensive - slnx have ben around for quite some time now and are a sibling of sln, it makes perfect sense to check for them at each 'level' and treat either one as a stop condition.

@MichaelSimons MichaelSimons changed the title Fix flaky PostActionTests.AddProjectToSolution - solution file not found Update FindSolutionFilesAtOrAbovePath to prioritize *.slnx over *.sln found in parent directories Jun 29, 2026
@MichaelSimons
MichaelSimons marked this pull request as ready for review June 29, 2026 20:41
@MichaelSimons
MichaelSimons requested a review from a team as a code owner June 29, 2026 20:41
Copilot AI review requested due to automatic review settings June 29, 2026 20:41
@MichaelSimons
MichaelSimons enabled auto-merge (squash) June 29, 2026 20:42

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

This PR fixes flaky dotnet new solution post-action behavior by changing solution discovery to prefer a nearby .slnx over an unrelated .sln found higher up the directory tree, aligning with dotnet new sln now producing .slnx by default.

Changes:

  • Update FindSolutionFilesAtOrAbovePath to search for both .sln and .slnx at each directory level before walking up, ensuring nearer solutions win.
  • Add explicit EndsWith filtering to guard against Windows legacy 8.3 short-name glob matching quirks.
  • Add a regression test verifying a .slnx in the output directory is chosen over a .sln in a parent directory.

Reviewed changes

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

File Description
src/Cli/dotnet/Commands/New/PostActions/DotnetSlnPostActionProcessor.cs Changes solution-file discovery to check .sln and .slnx per-directory level (preferring .sln only when co-located), avoiding distant-parent .sln selection.
test/dotnet.Tests/CommandTests/New/DotnetSlnPostActionTests.cs Adds a regression test covering the “nearby .slnx beats parent .sln” scenario.

@MichaelSimons
MichaelSimons merged commit 2345a18 into main Jun 29, 2026
28 checks passed
@MichaelSimons
MichaelSimons deleted the michaelsimons/fix-flaky-postaction-sln-not-found branch June 29, 2026 22:23
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 11.0-preview7 milestone Jun 30, 2026
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