Skip to content

Conversation

@jonathanpeppers
Copy link
Member

Implements the first part of the spec mentioned in:

* "Pre-run evaluation"
* If the project is multi-targeted, containing the
`$(TargetFrameworks)` property _and_ that property has more than
one item in it, and `-f` was not supplied...
* Prompt the user to select from a list of the
`$(TargetFrameworks)`
* Non-interactive mode will give a friendly error message,
suggesting to supply the `-f` property, listing available target
frameworks in the project.

Add interactive target framework selection to dotnet run

When running a multi-targeted project without specifying --framework, dotnet run now:

  • Prompts interactively (using Spectre.Console) to select a framework with arrow keys

  • Shows a formatted error list in non-interactive mode with available frameworks

  • Handles selection early before project build/evaluation

  • Removes redundant multi-TFM error checking from ThrowUnableToRunError()

  • Adds a few unit tests to validate these changes.

This is currently WIP, as it introduces a "pre-built" Spectre.Console that I will need to setup in source-build in a PRs elsewhere.

Implements the first part of the spec mentioned in:

https://github.com/dotnet/sdk/blob/522c88a6abfc4a011556f839d15844d07ba62cd9/documentation/specs/dotnet-run-for-maui.md?plain=1#L35-L46

Add interactive target framework selection to `dotnet run`

When running a multi-targeted project without specifying
`--framework`, `dotnet run` now:

* Prompts interactively (using `Spectre.Console`) to select a framework
  with arrow keys

* Shows a formatted error list in non-interactive mode with available
  frameworks

* Handles selection early before project build/evaluation

* Removes redundant multi-TFM error checking from
  `ThrowUnableToRunError()`

* Adds a few unit tests to validate these changes.

This is currently WIP, as it introduces a "pre-built"
`Spectre.Console` that I will need to setup in source-build in a PRs
elsewhere.
There are other tests that do this
This test fails after I made it check TF at runtime.

This was not even the existing behavior, I think we can remove this test.
@jonathanpeppers
Copy link
Member Author

/azp run sdk-unified-build

@azure-pipelines
Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

Copy link
Contributor

Copilot AI left a comment

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 adds interactive target framework selection to the dotnet run command for multi-targeted projects. When a multi-targeted project is run without specifying a framework, the command now prompts the user to select one in interactive mode, or displays a helpful error message with available frameworks in non-interactive mode.

  • Introduces TargetFrameworkSelector class to handle framework selection logic
  • Adds Spectre.Console package for interactive prompting
  • Updates error handling to show available frameworks and example commands
  • Includes comprehensive integration tests for framework selection scenarios

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsTargetFramework.cs Adds comprehensive integration tests for target framework selection behavior
test/TestAssets/TestProjects/DotnetRunMultiTarget/Program.cs Test project that outputs target framework information
test/TestAssets/TestProjects/DotnetRunMultiTarget/DotnetRunMultiTarget.csproj Multi-targeted test project configuration
src/Cli/dotnet/dotnet.csproj Adds Spectre.Console package reference
src/Cli/dotnet/Commands/xlf/*.xlf Adds localization entries for new UI strings (state=new)
src/Cli/dotnet/Commands/Run/TargetFrameworkSelector.cs New class implementing framework selection logic
src/Cli/dotnet/Commands/Run/RunCommand.cs Integrates framework selection into run command execution flow
src/Cli/dotnet/Commands/CliCommandStrings.resx Adds new localizable strings for framework selection UI
Directory.Packages.props Adds Spectre.Console version 0.52.0

Comment on lines 40 to 41
using var collection = new ProjectCollection(globalProperties: globalProperties);
project = collection.LoadProject(projectFilePath);
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

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

The ProjectCollection is disposed immediately after loading the project, but the project variable is used outside the using block (line 49). This could lead to issues since the project is part of the collection that's being disposed. Consider moving the property value retrieval inside the using block or restructuring to avoid using the project after its collection is disposed.

Copilot uses AI. Check for mistakes.
@NikolaMilosavljevic
Copy link
Member

/azp run sdk-unified-build

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger
Copy link
Member

Please also add Spectre.Console here:

sdk/eng/Signing.props

Lines 60 to 67 in 6a6992f

ReSign 3rd party files that we use in the product
-->
<ItemGroup>
<FileSignInfo Include="MessagePack.Annotations.dll" CertificateName="$(ExternalCertificateId)" />
<FileSignInfo Include="MessagePack.dll" CertificateName="$(ExternalCertificateId)" />
<FileSignInfo Include="Nerdbank.Streams.dll" CertificateName="$(ExternalCertificateId)" />
<FileSignInfo Include="Newtonsoft.Json.dll" CertificateName="$(ExternalCertificateId)" />
<FileSignInfo Include="Valleysoft.DockerCredsProvider.dll" CertificateName="$(ExternalCertificateId)" />

@jonathanpeppers
Copy link
Member Author

/azp run sdk-unified-build

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@NikolaMilosavljevic
Copy link
Member

sdk-unified-build pipeline is failing to synchronize the VMR. I've never seen this error before:

info: Rebasing darc/forward/00f07cf-be28ec7 onto HEAD...
dbug: Executing command: 'git -C /__w/1/vmr checkout HEAD'
dbug: Executing command: 'git -C /__w/1/vmr merge --squash darc/forward/00f07cf-be28ec7'
dbug: Executing command: 'git -C /__w/1/vmr branch -D darc/forward/00f07cf-be28ec7'
dbug: Executing command: 'git -C /__w/1/vmr show HEAD:src/source-manifest.json'
dbug: Executing command: 'git -C /__w/1/vmr add /__w/1/vmr/src/source-manifest.json'
fail: Failed to synchronize repo to VMR
      Failed to delete branch darc/forward/00f07cf-be28ec7 in /__w/1/vmr
      Exit code: 1
      Std err:
      error: cannot delete branch 'darc/forward/00f07cf-be28ec7' used by worktree at '/__w/1/vmr'

@premun @dkurepa do you know what might be going on here? Build

@baronfel baronfel added Area-Run Issues relating to `dotnet run` Area-CLI and removed Area-Infrastructure labels Nov 3, 2025
@premun
Copy link
Member

premun commented Nov 3, 2025

@NikolaMilosavljevic same as here: dotnet/source-build-reference-packages#1447 (comment)

You will have to pin darc for the time being (either in dotnet-tools.json or like this)

@jonathanpeppers
Copy link
Member Author

/azp run sdk-unified-build

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonathanpeppers
Copy link
Member Author

/azp run sdk-unified-build

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonathanpeppers
Copy link
Member Author

/azp run sdk-unified-build

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonathanpeppers
Copy link
Member Author

Since sdk-unified-build is failing for unrelated reasons:

Package 'Microsoft.Build.Tasks.Core' 17.12.36 has a known high severity vulnerability,

I created a branch here (and then also sent to internal):

And triggered a build here:

It's ongoing, but if all the source-build legs look ok, this seems safe to merge.

@jonathanpeppers
Copy link
Member Author

Most of the build is green, except for a couple legs had the error:

src/sdk/src/BuiltInTools/dotnet-watch/dotnet-watch.csproj : error NU1603: Warning As Error: dotnet-watch depends on Microsoft.Build.Locator (>= 1.8.1) but Microsoft.Build.Locator 1.8.1 was not found. Microsoft.Build.Locator 1.10.2 was resolved instead.

Somehow, I downgraded this in my manual test, trying again:

@jonathanpeppers
Copy link
Member Author

The source-build leg is fully green in my test:

image

Going to merge!

@jonathanpeppers jonathanpeppers merged commit b465890 into main Nov 21, 2025
26 checks passed
@jonathanpeppers jonathanpeppers deleted the dev/peppers/tf-selection branch November 21, 2025 15:59
@baronfel
Copy link
Member

WHOOO! One small step for the CLI....

@baronfel
Copy link
Member

@jonathanpeppers / @NikolaMilosavljevic if we wanted this in 10.0.2xx, are there source-build/VMR considerations that would block that?

@jonathanpeppers
Copy link
Member Author

I was going to ask how that worked -- if we can add Spectre.Console to 10.0.2xx.

@baronfel
Copy link
Member

Chatted with @MichaelSimons at standup today and he confirmed that there are no negative source-build implications from backporting. Lets's see if it applies via bot...

/backport to release/10.0.2xx

@baronfel
Copy link
Member

/backport to release/10.0.2xx

@github-actions
Copy link
Contributor

Started backporting to release/10.0.2xx (link to workflow run)

@github-actions
Copy link
Contributor

@baronfel backporting to release/10.0.2xx failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch

Applying: [dotnet-cli] prompt for target framework using `Spectre.Console`
.git/rebase-apply/patch:105: trailing whitespace.
        
.git/rebase-apply/patch:219: trailing whitespace.
            
.git/rebase-apply/patch:224: trailing whitespace.
            
.git/rebase-apply/patch:244: trailing whitespace.
            
.git/rebase-apply/patch:1008: trailing whitespace.
        
warning: squelched 6 whitespace errors
warning: 11 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	Directory.Packages.props
M	src/Cli/dotnet/Commands/CliCommandStrings.resx
M	src/Cli/dotnet/Commands/Run/RunCommand.cs
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
M	src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
M	src/Cli/dotnet/dotnet.csproj
Falling back to patching base and 3-way merge...
Auto-merging Directory.Packages.props
Auto-merging src/Cli/dotnet/Commands/CliCommandStrings.resx
Auto-merging src/Cli/dotnet/Commands/Run/RunCommand.cs
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
Auto-merging src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
Auto-merging src/Cli/dotnet/dotnet.csproj
Applying: Fix for `.sln` file passed in
Applying: Use `Interactive` property
Applying: Update GivenDotnetRunSelectsTargetFramework.cs
Applying: Remove duplicative tests
Applying: Better assertion
Applying: Skip previous TFMs on arm64, x64 passes on these
Applying: Remove ItPrefersExplicitFrameworkOptionOverProperty
Applying: Update src/Cli/dotnet/Commands/Run/RunCommand.cs
Applying: Sign `Spectre.Console.dll`
Applying: small tweaks to enable running against singular-valued targetframeworks lists
error: sha1 information is lacking or useless (src/Cli/dotnet/Commands/Run/RunCommand.cs).
error: could not build fake ancestor
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0011 small tweaks to enable running against singular-valued targetframeworks lists
Error: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@baronfel
Copy link
Member

@jonathanpeppers the bot couldn't do the backport - mind taking a stab at it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-CLI Area-Run Issues relating to `dotnet run`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants