Skip to content

Preserve ASPIRE010 and add ASPIRE013 for required CLI bundles - #21288

Merged
David Pine (IEvangelist) merged 2 commits into
mainfrom
ievangelist-apphost-diagnostic-compatibility
Nov 6, 2026
Merged

David Pine (IEvangelist) merged 2 commits into
mainfrom
ievangelist-apphost-diagnostic-compatibility

Conversation

@IEvangelist

Copy link
Copy Markdown
Member

Description

Diagnostic IDs must keep their meaning across releases. #20867 changed ASPIRE010 from a suppressible warning about optional CLI bundle features into an unsuppressible error requiring the bundle. Existing suppression settings and the published diagnostic reference therefore describe a different contract.

Restore ASPIRE010's original warning text, severity, and help link for non-C# AppHosts, where opting out remains supported. Introduce ASPIRE013 for the required-bundle error in C# AppHosts, without changing the C# bundle requirement or ASPIRE012 SDK-obsolescence warning. The two diagnostics are mutually exclusive.

Update the product diagnostic list and migration guide, and cover enabled/disabled bundles, C#/non-C# applicability, both warning IDs in NoWarn, and the complete set of emitted Aspire diagnostics.

Related documentation discussion: microsoft/aspire.dev#1880. That documentation PR should preserve the ASPIRE010 warning reference and document ASPIRE013 separately. Publishing the ASPIRE013 article and configuring https://aka.ms/aspire/diagnostics/aspire013 are coordinated documentation follow-ups; this product PR does not publish the site or configure the redirect.

User-facing usage

For a C# AppHost, this continues to fail the build, now with error ASPIRE013 rather than a repurposed ASPIRE010:

<PropertyGroup>
  <AspireUseCliBundle>false</AspireUseCliBundle>
</PropertyGroup>

For a non-C# AppHost, opting out emits the original warning ASPIRE010, which remains suppressible with <NoWarn>$(NoWarn);ASPIRE010</NoWarn>. Adding either ASPIRE010 or ASPIRE013 to NoWarn does not bypass the C# requirement.

Validation

  • .\restore.cmd — passed.
  • dotnet build tests\Aspire.Hosting.Sdk.Tests\Aspire.Hosting.Sdk.Tests.csproj --no-restore --verbosity quiet — passed, with four NU1902/NU1903 audit warnings for System.Security.Cryptography.Pkcs 10.0.12. No dependency versions are changed by this PR.
  • Native Microsoft.Testing.Platform execution — passed, 14/14 tests:
& .\artifacts\bin\Aspire.Hosting.Sdk.Tests\Debug\net10.0\Aspire.Hosting.Sdk.Tests.exe --filter-method "*.CliBundleDiagnosticsRespectLanguageAndWarningSuppression" --filter-method "*.AppHostSdkEmitsObsoleteWarning" --filter-method "*.AppHostSdkObsoleteWarningCanBeSuppressed" --filter-method "*.MinimumSdkVersionErrorDoesNotFireForNonSdkAppHost" --filter-method "*.ComputeRunArgumentsDoesNotUseAspireCliWhenCliBundleIsDisabled" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • git diff --check — passed.
  • The initial dotnet test invocation below built the project but timed out in a child MSBuild invocation and was stopped. Retrying the diagnostic matrix with NuGet audit disabled also timed out and was stopped. Running the same selected tests with the built native MTP executable succeeded as recorded above.
dotnet test --project tests\Aspire.Hosting.Sdk.Tests\Aspire.Hosting.Sdk.Tests.csproj --no-launch-profile -- --filter-method "*.CliBundleDiagnosticsRespectLanguageAndWarningSuppression" --filter-method "*.AppHostSdkEmitsObsoleteWarning" --filter-method "*.AppHostSdkObsoleteWarningCanBeSuppressed" --filter-method "*.MinimumSdkVersionErrorDoesNotFireForNonSdkAppHost" --filter-method "*.ComputeRunArgumentsDoesNotUseAspireCliWhenCliBundleIsDisabled" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"

Full solution and cross-platform validation were not run locally.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

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

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 21288

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 21288"

@github-actions github-actions Bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Oct 23, 2026
@aspire-repo-bot
aspire-repo-bot Bot requested a balanced review from Copilot October 23, 2026 13:53
@github-actions

This comment has been minimized.

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.

🟢 Approval recommended

The focused diagnostic changes match the intended contracts, include regression coverage, and have no unresolved blocking findings.

No open issues 🎉

What changed in this PR

Preserves Aspire diagnostic compatibility by restoring ASPIRE010’s warning contract and assigning ASPIRE013 to the existing C# CLI bundle requirement.

Changes:

  • Restores suppressible ASPIRE010 for non-C# AppHosts and introduces mutually exclusive, unsuppressible ASPIRE013 for C# AppHosts.
  • Expands regression coverage for bundle settings, language applicability, suppression, and emitted diagnostics.
  • Updates diagnostic and migration documentation without changing ASPIRE012.
File Description
tests/​Aspire.Hosting.Sdk.Tests/​AppHostSdkTargetsTests.cs Adds diagnostic and suppression test cases.
src/​Aspire.Hosting.AppHost/​build/​Aspire.Hosting.AppHost.in.targets Separates optional-bundle warnings from required-bundle errors.
docs/​migrate-from-apphost-sdk.md References ASPIRE013 for the required bundle.
docs/​list-of-diagnostics.md Documents both diagnostic contracts and language applicability.

Review effort: Balanced

@IEvangelist
David Pine (IEvangelist) enabled auto-merge (squash) October 23, 2026 14:03
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

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.

The C#/non-C# split looks correct: the two diagnostics are mutually exclusive, ASPIRE010 matches its previous wording and severity for non-C# AppHosts, and the C# requirement is unchanged. I found 4 minor issues and no blocking bugs: 1 diagnostic ID conflict, 1 help link and 2 test gaps.

This is a comment rather than an approval because auto-merge is on, and an approval could merge the PR before these are read.

One issue is outside the diff, so it can't be an inline comment: CliBundleDefaultResolvesBundleWithoutOptIn in tests/Aspire.Hosting.Tests/MSBuildTests.cs:443 still has Assert.DoesNotContain("ASPIRE010", output). That test builds a C# AppHost, which can no longer emit ASPIRE010, so the assertion can't fail. If the default regressed, the build would fail with ASPIRE013 and BuildProject's exit-code check would catch it, so the line can be removed.

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.

I found no new issues. The three open threads from my earlier review are all minor and can be handled after merge:

  • The ASPIRE013 ID conflict is best fixed by renumbering in #21592 (and in draft #19880), so this PR can merge first.
  • The aspire013 aka.ms redirect and the aspire.dev article are documentation follow-ups that are already listed in the PR description.
  • Covering the default-off path for non-C# AppHosts is a test follow-up.

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

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Tests selector

45 / 101 PR test projects · 3 PR jobs, from 3 changed files.

Selected PR test projects (45 / 101)

Aspire.Cli.EndToEnd.Tests, Aspire.Hosting.Analyzers.Tests, Aspire.Hosting.Azure.EntraId.Tests, Aspire.Hosting.Azure.Kubernetes.Tests, Aspire.Hosting.Azure.Kusto.Tests, Aspire.Hosting.Azure.Tests, Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Browsers.Tests, Aspire.Hosting.Containers.Tests, Aspire.Hosting.DevTunnels.Tests, Aspire.Hosting.Docker.Tests, Aspire.Hosting.Dotnet.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.EntityFrameworkCore.Tests, Aspire.Hosting.Foundry.Tests, Aspire.Hosting.Garnet.Tests, Aspire.Hosting.Go.Tests, Aspire.Hosting.Java.Tests, Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Kafka.Tests, Aspire.Hosting.Keycloak.Tests, Aspire.Hosting.Kubernetes.Tests, Aspire.Hosting.Maui.Tests, Aspire.Hosting.Milvus.Tests, Aspire.Hosting.MongoDB.Tests, Aspire.Hosting.MySql.Tests, Aspire.Hosting.Nats.Tests, Aspire.Hosting.OpenAI.Tests, Aspire.Hosting.Oracle.Tests, Aspire.Hosting.Orleans.Tests, Aspire.Hosting.PostgreSQL.Tests, Aspire.Hosting.Python.Tests, Aspire.Hosting.Qdrant.Tests, Aspire.Hosting.RabbitMQ.Tests, Aspire.Hosting.Radius.Tests, Aspire.Hosting.Redis.Tests, Aspire.Hosting.Rust.Tests, Aspire.Hosting.Sdk.Tests, Aspire.Hosting.Seq.Tests, Aspire.Hosting.SqlServer.Tests, Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Hosting.Valkey.Tests, Aspire.Hosting.Yarp.Tests, Aspire.Playground.Tests

Selected PR jobs (3)

cli-starter-validation, extension-e2e, typescript-api-compat


How these were chosen — grouped by what changed

⚠️ 43 of the 45 selected test projects come from a single change — src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets.

🔧 src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets (changed source)
→ 43 via the project graph

show 43

Aspire.Hosting.Analyzers.Tests, Aspire.Hosting.Azure.EntraId.Tests, Aspire.Hosting.Azure.Kubernetes.Tests, Aspire.Hosting.Azure.Kusto.Tests, Aspire.Hosting.Azure.Tests, Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Browsers.Tests, Aspire.Hosting.Containers.Tests, Aspire.Hosting.DevTunnels.Tests, Aspire.Hosting.Docker.Tests, Aspire.Hosting.Dotnet.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.EntityFrameworkCore.Tests, Aspire.Hosting.Foundry.Tests, Aspire.Hosting.Garnet.Tests, Aspire.Hosting.Go.Tests, Aspire.Hosting.Java.Tests, Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Kafka.Tests, Aspire.Hosting.Keycloak.Tests, Aspire.Hosting.Kubernetes.Tests, Aspire.Hosting.Maui.Tests, Aspire.Hosting.Milvus.Tests, Aspire.Hosting.MongoDB.Tests, Aspire.Hosting.MySql.Tests, Aspire.Hosting.Nats.Tests, Aspire.Hosting.OpenAI.Tests, Aspire.Hosting.Oracle.Tests, Aspire.Hosting.Orleans.Tests, Aspire.Hosting.PostgreSQL.Tests, Aspire.Hosting.Python.Tests, Aspire.Hosting.Qdrant.Tests, Aspire.Hosting.RabbitMQ.Tests, Aspire.Hosting.Radius.Tests, Aspire.Hosting.Redis.Tests, Aspire.Hosting.Rust.Tests, Aspire.Hosting.Seq.Tests, Aspire.Hosting.SqlServer.Tests, Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Hosting.Valkey.Tests, Aspire.Hosting.Yarp.Tests, Aspire.Playground.Tests

📦 affected project Aspire.Hosting.AppHost
→ 1 test: Aspire.Cli.EndToEnd.Tests

🧪 tests/Aspire.Hosting.Sdk.Tests/AppHostSdkTargetsTests.cs (changed test)
→ 1 directly: Aspire.Hosting.Sdk.Tests

🧪 tests/Aspire.Hosting.Tests/MSBuildTests.cs (changed test)
→ 1 directly: Aspire.Hosting.Tests

Job reasons

Job Triggered by
cli-starter-validation affected project Aspire.Hosting.AppHost
extension-e2e • src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets
• affected project Aspire.Hosting.AppHost
typescript-api-compat affected project Aspire.Hosting.AppHost

Selection computed for commit b279349.

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.

🟢 Approval recommended

No active review issues remain for the diagnostic-compatibility changes.

No open issues 🎉

Review effort: Balanced

@IEvangelist
David Pine (IEvangelist) enabled auto-merge (squash) November 6, 2026 04:15
@IEvangelist
David Pine (IEvangelist) merged commit ba43a21 into main Nov 6, 2026
607 of 610 checks passed
@aspire-repo-bot

Copy link
Copy Markdown
Contributor

Pull request created: #2071

Generated by PR Documentation Check · copilot · auto · 30 AIC · ⌖ 1.4 AIC · ⊞ 7.4K

@aspire-repo-bot

Copy link
Copy Markdown
Contributor

📝 Documentation has been drafted in microsoft/aspire.dev#2071 targeting release/17.0.

Adds ASPIRE013 diagnostic page, scopes ASPIRE010 to non-C# AppHosts, and updates overview, aspire-sdk, and ASPIRE009 pages. Signals: diagnostic_documentation_changed (docs/list-of-diagnostics.md), pr_body_has_cli_flag_mention, pr_body_has_user_facing_section.

Note

This draft PR needs human review before merging.

David Fowler (davidfowl) added a commit that referenced this pull request Nov 6, 2026
#21288 keeps ASPIRE013 for the required C# CLI-bundle error and #21545
proposes ASPIRE014, so move this warning to the next unused ID.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
David Fowler (davidfowl) added a commit that referenced this pull request Nov 7, 2026
## Description

`AspireCliInvocationMode` only recognized `Dnx` and `DnxPinned`; every
other value (for example `DnxPinnedd` or `DefinitelyInvalid`) silently
fell through to `Path` resolution, so typos never surfaced.

**Root cause:** `_ResolveAspireCliInvocation` passed the raw value to
`ResolveAspireCliInvocation`, which treats anything other than
`Dnx`/`DnxPinned` as `Path`. The only validation target
(`_ValidateAspireCliDnxInvocationMode`) is conditioned on a DNX mode, so
it was skipped for unrecognized values.

**Fix:** `_ResolveAspireCliInvocation` emits a new suppressible
`ASPIRE014` warning when the value is not `Path`, `Dnx` or `DnxPinned`
(case-insensitive), and resolution continues in `Path` mode as before. I
chose a warning instead of an error so that existing builds keep working
while the mistake becomes visible. `ASPIRE013` is skipped because open
PRs #21288 and #19880 both propose it. `docs/list-of-diagnostics.md`
documents `ASPIRE014`.

Fixes #19714

### Before (main)

Playground `DotnetProject.AppHost` with `-p:AspireUseCliBundle=true
-p:AspireCliInvocationMode=DefinitelyInvalid
-t:_ResolveAspireCliInvocation -v:diag`:

```text
Task Parameter:AspireCliInvocationMode=DefinitelyInvalid
Aspire CLI invocation selection: Dnx (aspire: , dnx: /root/aspire/.dotnet/dnx)   <- Path-mode fallback (no aspire on PATH)
    0 Error(s)
    0 Warning(s)
```

A full `dotnet build` of the AppHost with the same value also reported
`0 Warning(s)`.

### After

```text
Aspire.Hosting.AppHost.in.targets(221,5): warning ASPIRE014: DotnetProject.AppHost is configured with AspireCliInvocationMode=DefinitelyInvalid, which is not a supported value. Supported values are Path, Dnx, and DnxPinned. The default Path invocation mode will be used.
Aspire CLI invocation selection: Dnx (aspire: , dnx: /root/aspire/.dotnet/dnx)
    0 Error(s)
    1 Warning(s)
```

Valid values (`Path`, `DnxPinned`) still resolve to `Aspire` and `Dnx`
without a warning.

### End-to-end with Aspire

I ran `dotnet run` on `playground/DotnetProject/DotnetProject.AppHost`
with `AspireCliInvocationMode=DefinitelyInvalid` and the Aspire CLI
built from this branch (`17.0.0-dev`) on `PATH`. The warning appears
during the build, and the AppHost then launches through `aspire run`
(Path mode):

```text
Building...
...Aspire.Hosting.AppHost.in.targets(221,5): warning ASPIRE014: DotnetProject.AppHost is configured with AspireCliInvocationMode=DefinitelyInvalid, which is not a supported value. Supported values are Path, Dnx, and DnxPinned. The default Path invocation mode will be used.
Connecting to AppHost...
Starting dashboard...
     AppHost:  DotnetProject.AppHost.csproj
               Press CTRL+C to stop the AppHost and exit.
```

(The dashboard was skipped locally with
`SkipDashboardProjectReference=true`.)

### Tests

New tests in `tests/Aspire.Hosting.Sdk.Tests/AppHostSdkTargetsTests.cs`:

-
`ComputeRunArgumentsWarnsAndUsesPathModeWhenInvocationModeIsUnsupported`
(`DefinitelyInvalid`, `DnxPinnedd`): asserts that `ASPIRE014` is emitted
and that the fake `aspire` from `PATH` is selected.
- `ComputeRunArgumentsDoesNotWarnWhenInvocationModeIsSupported` (unset,
`Path`, `pAtH`, `Dnx`, `DnxPinned`).
- `UnsupportedInvocationModeWarningCanBeSuppressed`
(`NoWarn=ASPIRE014`).

Without the fix, the two unsupported-value cases fail (`total: 8,
failed: 2`). With the fix, the full `Aspire.Hosting.Sdk.Tests` project
passes: 98 total, 94 passed, 0 failed, 4 skipped (Windows-only).

### Playground

No playground file changed. In-repo playground AppHosts don't import
`Aspire.Hosting.AppHost.props`, so `AspireUseCliBundle` isn't enabled by
default and the packaged tasks assembly isn't present. Setting
`AspireCliInvocationMode` in a playground project would therefore have
no effect in a normal repo build. The playground proof above runs the
existing `DotnetProject.AppHost` and passes those properties on the
command line.

## Checklist

- Is this feature complete?
  - [x] Yes. Ready to ship.
  - [ ] No. Follow-up changes expected.
- Are you including unit tests for the changes and scenario tests if
relevant?
  - [x] Yes
  - [ ] No
- Did you add public API?
  - [ ] Yes
  - [x] No
- Does the change make any security assumptions or guarantees?
  - [ ] Yes
  - [x] No

**🤖 Posted by AspireAgent (AI Agent)**

Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants