Adjust required CLI behavior for C# AppHosts - #18850
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 61a40a86-50a4-4fe4-ae28-e57d4c7559dd
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18850Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18850" |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Restores direct C# AppHost launching by default while adding opt-in Aspire CLI and DNX delegation.
Changes:
- Defaults
AspireUseCliBundletofalseand adds ASPIRE010 guidance. - Adds Aspire/DNX resolution, validation, and run-hook behavior.
- Expands MSBuild and SDK target coverage.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
tests/Directory.Build.props |
Suppresses ASPIRE010 in tests. |
tests/Aspire.Hosting.Tests/MSBuildTests.cs |
Tests defaults, diagnostics, and metadata. |
tests/Aspire.Hosting.Sdk.Tests/Aspire.Hosting.Sdk.Tests.csproj |
Makes hosting tasks available to tests. |
tests/Aspire.Hosting.Sdk.Tests/AppHostSdkTargetsTests.cs |
Tests Aspire and DNX delegation. |
src/Aspire.Hosting.Tasks/ResolveAspireCliInvocation.cs |
Selects the CLI invocation mode. |
src/Aspire.Hosting.Tasks/ResolveAspireCliBundle.cs |
Reuses shared PATH resolution. |
src/Aspire.Hosting.Tasks/CommandPathResolver.cs |
Implements command discovery. |
src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.props |
Restores the disabled-by-default setting. |
src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets |
Implements delegation and diagnostics. |
src/Aspire.AppHost.Sdk/SDK/Sdk.in.targets |
Aligns SDK defaults. |
playground/Directory.Build.props |
Suppresses ASPIRE010 in playground builds. |
docs/list-of-diagnostics.md |
Documents ASPIRE010 and ASPIRE011. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 61a40a86-50a4-4fe4-ae28-e57d4c7559dd
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets:275
- A failed DNX version probe silently disables delegation because
_AspireCliVersionSupportsRunHookremains false, so a missing or unrestoredaspire.clilocal tool causes the AppHost to launch directly. That contradicts the DNX contract documented below: the actualdnxinvocation never runs, so users never receive the local-tool restore error. For DNX selection, either fail this preflight with the DNX error or preserve delegation on probe failure sodnxcan report the actionable restore failure.
<_AspireCliVersionCommand Condition="'$(AspireCliPath)' == '' and '$(_AspireResolvedCliInvocationMode)' == 'Dnx'">dnx $(_AspireCliDnxPackageId) -- --version</_AspireCliVersionCommand>
src/Aspire.Hosting.Tasks/CommandPathResolver.cs:39
- On Unix,
File.Existsalso accepts files without any execute bit. Such a file namedaspireearlier onPATHis selected as the CLI, its version probe fails with permission denied, and a valid lateraspireordnxcandidate is never considered. Match executable lookup semantics by rejecting non-executable Unix candidates (the repository'sPathLookupHelper.FileExistsAndIsExecutabledemonstrates the required check).
if (seenPaths.Add(candidate) && File.Exists(candidate))
{
yield return candidate;
This comment has been minimized.
This comment has been minimized.
Use the resolved CLI executable for Unix launches and pass --yes so DNX can restore Aspire.Cli during noninteractive dotnet run invocations. Preserve system command paths in the SDK tests while isolating the selected CLI. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 61a40a86-50a4-4fe4-ae28-e57d4c7559dd
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (2)
src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets:217
- Making bundle resolution optional as soon as a
dnxexecutable is found leaves an invalid fallback path. If restoring/probingaspire.clifails or reports a version below 13.5,_AspireCliVersionSupportsRunHookremains false anddotnet runlaunches the AppHost directly. Because CLI opt-in also skipped the DCP/Dashboard package references and this condition suppressed ASPIRE009, that AppHost has neither build-time discovery metadata nor runtime paths injected by the CLI. Only permit missing bundle metadata after a usable DNX invocation is confirmed, or fail the DNX probe instead of falling back to direct launch.
<_AspireCliBundleResolutionOptional Condition="'$(_AspireResolvedCliInvocationMode)' == 'Dnx' and '$(AspireCliPath)' == '' and '$(AspireCliBundlePath)' == ''">true</_AspireCliBundleResolutionOptional>
src/Aspire.Hosting.Tasks/CommandPathResolver.cs:37
- On Unix, existence does not mean the candidate is an executable command. A non-executable file named
aspireearlier onPATHis selected here, its version probe fails, and the resolver never tries a later executable or DNX, so CLI delegation unexpectedly falls back to direct launch. Filter Unix candidates by executable permissions (with appropriate handling for the task assembly's target frameworks) before returning them.
if (seenPaths.Add(candidate) && File.Exists(candidate))
This comment has been minimized.
This comment has been minimized.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 61a40a86-50a4-4fe4-ae28-e57d4c7559dd
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets:291
- The preceding comment is now inaccurate: DNX probe failures do fail the target via the new
<Error>elements, and DNX uses a 120-second timeout rather than 5 seconds. Please describe both the ordinary Aspire fallback and the DNX failure behavior so future changes do not rely on the old contract.
Timeout="$(_AspireCliVersionTimeout)"
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
PR Testing ReportPR Information
Artifact Version VerificationInstalled PR #18850 from CI run The fresh PR hive contains the matching Scenarios1. Default direct AppHost launchPassed. A fresh Evidence: 2. PATH native Aspire delegation and argv preservationPassed. With Evidence: 3. Automatic real DNX fallbackPassed. With the PATH Aspire executable hidden and no tool manifest, the exact paired Evidence: 4. Forced DNXPassed. With Evidence: 5. Invalid explicit CLI path (
|
| Scenario | Result |
|---|---|
Exact gcabe057e artifact verification |
Passed |
| Default direct launch | Passed |
| Direct forwarded arguments | Passed |
| PATH native Aspire delegation | Passed |
| PATH argv preservation | Passed |
| Automatic real DNX fallback | Passed |
| Forced DNX | Passed |
ASPIRE009 invalid path |
Passed |
ASPIRE011 missing DNX |
Passed |
Overall Result
PR #18850 verified against cabe057e7c9518320f3b7421aa6ecce2aa98598a.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 61a40a86-50a4-4fe4-ae28-e57d4c7559dd
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 61a40a86-50a4-4fe4-ae28-e57d4c7559dd
Tests selector (audit mode)The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement. Runs the full test matrix + all jobs (ALL) — a rule matching 'Aspire.slnx' selects ALL Selection computed for commit |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
This comment has been minimized.
This comment has been minimized.
|
The CI build failed due to test failure(s) that appear unrelated to the PR changes. These may be flaky tests. Suspected flaky test(s):
Suggested actions:
You can re-run the failed jobs from the workflow run page. |
|
📝 Documentation has been drafted in microsoft/aspire.dev#1512 targeting Added new diagnostic pages for
Note This draft PR needs human review before merging. |
Description
Launching a C# AppHost with
dotnet runor an IDE should continue to work without requiring the Aspire CLI, while users who opt into CLI delegation should be able to use either an installedaspirecommand or DNX.This change:
AspireUseCliBundletofalseby default and emitsASPIRE010with migration guidance.AspireCliPath, forced DNX mode,aspireonPATH, thendnxonPATH.AspireCliInvocationMode=Dnxto force DNX and reportsASPIRE011when DNX is unavailable.dnx --yes aspire.cli@$(AspireHostingSDKVersion)so noninteractive launches restore and execute the exact CLI version paired with the AppHost SDK rather than an unpinned package.PATHthrough launch and rejects non-executable PATH candidates on Unix.ASPIRE009for invalid explicitly configured CLI or bundle paths.The DNX invocation and explicit-path behavior reuse the relevant implementation from #18331.
User-facing usage
To enable CLI delegation and automatically prefer
aspirebefore falling back to DNX:This opt-in permits DNX to restore and execute the exact
Aspire.Cliversion paired with the AppHost SDK from the user's configured NuGet sources whenaspireis not available onPATH.--yesis required becausedotnet runis noninteractive.To force DNX:
Validation included:
AppHostSdkTargetsTestson Linux; 34 passed and the Unix-only test was skipped on Windows.MSBuildTests.aspire, automatic DNX, forced DNX, and explicit-path launches through healthy dashboard startup.aspire, restores the pinned localAspire.Clipackage through SDK DNX, reaches healthy AppHost startup, and verifies forwarded arguments.ASPIRE009,ASPIRE010, andASPIRE011failure and warning scenarios.Fixes #18447
Checklist
<remarks />and<code />elements on your triple slash comments?docs/list-of-diagnostics.md.