Skip to content

fix(cli): restore implicit-channel discovery + guard non-interactive fuzzy auto-pick (#17724, #17725)#17728

Merged
davidfowl merged 4 commits into
release/13.4from
mitchdenny/fix-aspire-add-fuzzy-match-17724
May 30, 2026
Merged

fix(cli): restore implicit-channel discovery + guard non-interactive fuzzy auto-pick (#17724, #17725)#17728
davidfowl merged 4 commits into
release/13.4from
mitchdenny/fix-aspire-add-fuzzy-match-17724

Conversation

@mitchdenny
Copy link
Copy Markdown
Member

@mitchdenny mitchdenny commented May 30, 2026

Fixes #17724. Fixes #17725.

What changed

This PR addresses two release/13.4 blockers that share a root cause.

Root cause — how we got here (three layers)

The user-facing symptom is "13.4 hides Kubernetes / Foundry on aspire add, 13.3.5 didn't". That's a regression. But the code responsible for hiding them is identical in both versions — what changed is what populates the input that activates that code.

Layer Where When What
Layer 1 — latent bug IntegrationPackageSearchService.GetIntegrationPackagesWithChannelsAsync narrows the channel set to configuredChannel when non-empty Born 2026-01-13, PR #13705 (polyglot apphost intro) C# short-circuits to null; non-C# reads aspire.config.json "channel" → narrows. If the resolved channel is Quality.Stable, prerelease packages disappear.
Layer 2 — activator aspire init started writing "channel": "<IdentityChannel>" into scaffolded aspire.config.json for both single-file C# and polyglot apphosts 2026-05-26, PR #17452 Every 13.4-init'd apphost now has "channel" populated, activating Layer 1 for polyglot apphosts. C# remains immune via the short-circuit, but only by accident.
Layer 3 — fallback auto-selection AddCommand treated a single fallback candidate as unambiguous Pre-existing With Layers 1 + 2 active, aspire add kube --non-interactive on a TS apphost can silently install Aspire.Hosting.Azure. In interactive mode, aspire add kube can also skip package confirmation whenever fuzzy/no-match fallback collapses to one candidate.

13.3.5 users were immune because no path was writing "channel" into aspire.config.json — the Layer-1 narrowing existed but never had input. PR #17452 was the activator that woke the dormant bug for everyone on 13.4.

Fix #17725IntegrationPackageSearchService no longer narrows

Deleted the configuredChannel narrowing block. The post-retrieval channel set is now:

var channels = hasHives || !string.IsNullOrEmpty(configuredChannel)
    ? allChannels
    : allChannels.Where(c => c.Type is PackageChannelType.Implicit);

Result:

  • TS apphost with "channel" pinned (the Prerelease-only integrations like Aspire.Hosting.Foundry are filtered out of search #17725 case): implicit channel + the pinned channel + any hives. Pre-fix only the pinned channel was searched, so prerelease-only packages (e.g. Aspire.Hosting.Foundry) vanished when pinned to Quality.Stable. Post-fix the implicit channel (Quality.Both) participates, so prerelease packages remain reachable, AND the pinned channel still contributes its feed-specific packages.
  • TS apphost without "channel": implicit channel only (matches C# default).
  • C# apphost: unchanged. GetConfiguredChannel already short-circuits to null for C#, so the gate behavior is identical to before.

The configuredChannel value is still forwarded to PackagingService.GetChannelsAsync as requestedChannelName so out-of-tree apphost staging-channel synthesis (the feature PR #17452 was actually trying to enable) keeps working.

Fix #17724 — exact-match guard and interactive confirmation

AddCommand now tracks whether the candidate set came from exact matching, fuzzy fallback, or the no-match fallback.

  • Non-interactive: aspire add <name> fails fast when <name> does not exactly match a friendly name or package ID, instead of silently auto-picking a fuzzy candidate. Callers must supply an exact package ID or friendly name (for example, aspire add kubernetes rather than aspire add kube).
  • Interactive: exact matches still skip the package-selection prompt, but fuzzy fallback and no-match fallback now ask for confirmation even when the candidate set contains exactly one package. That covers the interactive aspire add kube case from aspire add kube adds first matching integration instead of failing #17724.

This is intentionally orthogonal to Fix #17725 — even if discovery returned every relevant package, silently auto-picking a fuzzy match in a script is wrong, and silently adding a single interactive fuzzy/no-match fallback candidate is too surprising.

Intentional behavior changes (for release notes)

  1. Polyglot apphosts with "channel" set in aspire.config.json previously saw packages from only the pinned channel. They now see packages from the implicit channel and the pinned channel. NuGetPackage.Source carries the originating feed through to install, so feed routing on install is preserved.
  2. aspire add <fuzzy-name> in non-interactive mode now fails fast instead of silently picking a fuzzy match. Use an exact package ID or friendly name.
  3. aspire add <fuzzy-name> in interactive mode now prompts before adding when the result came from fuzzy/no-match fallback, even if only one candidate remains. Exact friendly-name/package-ID matches still do not show the package-selection prompt.

Tests

Added/updated in tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs. All discovery tests use per-channel invocation counters (Interlocked.Increment inside the cache callback) so that "channel X was searched" is asserted directly rather than inferred from dedupe outcomes.

  • IntegrationSearchCommandFormatJsonWithTypeScriptAppHostPinnedToStableChannelStillSurfacesPrereleaseOnlyPackages — primary regression test for Prerelease-only integrations like Aspire.Hosting.Foundry are filtered out of search #17725. Asserts Foundry surfaces AND both the implicit and stable channels are queried.
  • IntegrationSearchCommandTypeScriptAppHostPersistedChannelExpandsDiscoveryWithoutChangingPreferredResult[Theory] with two arms. Asserts (a) the user-visible top result is identical with/without "channel" pinned, AND (b) per-channel invocation counters: implicit-only when no pin, implicit + daily when pinned. Fails fast if anyone re-introduces narrowing OR drops the pinned channel.
  • IntegrationSearchCommandFormatJsonWithTypeScriptAppHostPinnedToChannelAlsoSearchesImplicitChannel + ...PinnedToStagingChannelAlsoSearchesImplicitChannel — assert both channels are queried (counter-backed) and implicit wins the dedupe.
  • AddCommand_NonInteractive_NoExactMatchWithoutVersion_FailsInsteadOfFuzzyAutoPick_Regression17724 — non-interactive add kube fails instead of fuzzy auto-picking, and AddPackageAsync is not called.
  • AddCommand_NonInteractive_ExactMatchWithoutVersion_StillSucceeds — companion happy-path guard for exact friendly-name matching in non-interactive mode.
  • AddCommand_Interactive_SingleFuzzyMatchPromptsBeforeAdding_Regression17724 — interactive add kube prompts before adding when fuzzy fallback returns a single candidate.
  • AddCommandInteractiveDoesNotPromptForIntegrationWhenExactMatchIsFound — exact interactive matches skip the package-selection prompt for both friendly names and package IDs.
  • AddCommand_Interactive_NoFuzzyMatchSinglePackagePromptsBeforeAdding — interactive no-match fallback also prompts before adding when only one candidate remains.

Two pre-existing AddCommandFuzzySearchTests (AddCommand_WithStartsWith_FindsMatchUsingFuzzySearch, AddCommand_WithTypo_FindsMatchUsingFuzzySearch) were implicitly testing the buggy auto-pick behavior under the default non-interactive test host. They've been updated to opt into an interactive host environment so they assert the documented interactive-fuzzy-prompt behavior.

Latest targeted validation passed for the AddCommandTests and AddCommandFuzzySearchTests classes.

Microsoft Reviewers: Open in CodeFlow

…fuzzy auto-pick (#17724, #17725)

## #17725 — Prerelease-only integrations invisible on polyglot apphosts

`IntegrationPackageSearchService.GetIntegrationPackagesWithChannelsAsync`
used to narrow the channel set to whatever `configuredChannel` resolved
to (from `aspire.config.json`'s `"channel"` field). For a polyglot apphost
pinned to a `Quality.Stable` channel this dropped the implicit channel
from discovery, so prerelease-only packages (e.g. `Aspire.Hosting.Foundry`,
`Aspire.Hosting.Kubernetes`) became invisible.

This narrowing was born 2026-01-13 in PR #13705 with a C#-only short-circuit
in `GetConfiguredChannel`. It stayed dormant until PR #17452 (2026-05-26)
started writing `"channel": "<identity>"` into the scaffolded
`aspire.config.json` during `aspire init`. After #17452 every newly-init'd
polyglot apphost in 13.4 had the field populated and tripped the narrowing.
13.3.5 users had no `"channel"` persisted, so the bug was invisible there
— this is a 13.4 regression introduced by the activator, not the
narrowing code itself.

The fix removes the narrowing. The configured channel is still forwarded
to `PackagingService.GetChannelsAsync` as `requestedChannelName` so
out-of-tree apphost staging-channel synthesis keeps working — it just no
longer constrains the post-retrieval filter pipeline. The filter pipeline
is now byte-identical for C# and polyglot apphosts.

## #17724 — `aspire add <fuzzy> --non-interactive` silently picks first match

`AddCommand` falls back to fuzzy search when there's no exact match. The
fuzzy candidates were passed to `GetPackageByInteractiveFlow`, which in
non-interactive mode auto-selected `distinctPackages.First()` and silently
installed it. Combined with #17725, `aspire add kube --non-interactive`
on a TS apphost silently installed `Aspire.Hosting.Azure`.

The existing guard at AddCommand.cs:181 already refused this when
`--version` was supplied. This change generalizes the guard: any
non-interactive invocation without an exact match now fails with a new
`NonInteractiveRequiresExactPackageMatch` resource message. Fuzzy
fallback remains available in interactive mode.

## Tests

- IntegrationSearchCommandFormatJsonWithTypeScriptAppHostPinnedToChannelAlsoSearchesImplicitChannel
- IntegrationSearchCommandFormatJsonWithTypeScriptAppHostPinnedToStagingChannelAlsoSearchesImplicitChannel
- IntegrationSearchCommandFormatJsonWithTypeScriptAppHostPinnedToStableChannelStillSurfacesPrereleaseOnlyPackages
  (primary regression test for #17725 — Foundry case)
- IntegrationSearchCommandTypeScriptAppHostProducesSameResultRegardlessOfPersistedChannel
  (durable structural guard: parameterized over with/without `"channel"`
  in aspire.config.json; asserts the result is identical, proving the
  narrowing is gone)
- AddCommand_NonInteractive_NoExactMatchWithoutVersion_FailsInsteadOfFuzzyAutoPick_Regression17724
  (primary regression test for #17724)
- AddCommand_NonInteractive_ExactMatchWithoutVersion_StillSucceeds
  (companion guard: exact-match happy path keeps working non-interactive)

Two pre-existing AddCommandFuzzySearchTests were testing the buggy
auto-pick behavior implicitly (they used `add postgre` / typo input under
the default non-interactive test host). Updated to opt into an interactive
host environment to assert the documented interactive-fuzzy-prompt behavior.

Full Aspire.Cli.Tests suite: 3900 passed, 21 skipped, 0 failed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 30, 2026 09:27
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

🚀 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 -- 17728

Or

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

@mitchdenny mitchdenny self-assigned this May 30, 2026
@mitchdenny mitchdenny added this to the 13.4 milestone May 30, 2026
Copy link
Copy Markdown
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

Fixes two CLI regressions affecting polyglot AppHosts: (1) integration/package discovery incorrectly constrained by persisted channel, and (2) aspire add in non-interactive mode silently picking a fuzzy match instead of failing.

Changes:

  • Adjust integration search channel selection to avoid incorrectly narrowing results for polyglot AppHosts.
  • Add a non-interactive guard in aspire add requiring an exact match (no fuzzy auto-pick).
  • Add/adjust CLI tests and introduce a new localized error string (RESX + XLF updates).
Show a summary per file
File Description
tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs Adds/updates regression coverage for channel discovery parity and non-interactive add exact-match enforcement.
src/Aspire.Cli/Commands/IntegrationPackageSearchService.cs Changes how channels are selected for integration discovery.
src/Aspire.Cli/Commands/AddCommand.cs Blocks fuzzy fallback in non-interactive mode when there is no exact match; surfaces new error string.
src/Aspire.Cli/Resources/AddCommandStrings.resx Adds NonInteractiveRequiresExactPackageMatch string.
src/Aspire.Cli/Resources/AddCommandStrings.Designer.cs Adds strongly-typed accessor for the new string.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.cs.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.de.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.es.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.fr.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.it.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.ja.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.ko.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.pl.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.pt-BR.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.ru.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.tr.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.zh-Hans.xlf Adds new trans-unit for the non-interactive exact-match error.
src/Aspire.Cli/Resources/xlf/AddCommandStrings.zh-Hant.xlf Adds new trans-unit for the non-interactive exact-match error.

Copilot's findings

Files not reviewed (1)
  • src/Aspire.Cli/Resources/AddCommandStrings.Designer.cs: Language not supported
  • Files reviewed: 17/18 changed files
  • Comments generated: 2

Comment thread src/Aspire.Cli/Commands/IntegrationPackageSearchService.cs Outdated
Comment thread tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs
mitchdenny and others added 2 commits May 30, 2026 19:46
…ns a channel

Address review feedback on PR #17728.

The first revision dropped too much. Removing the
`|| !string.IsNullOrEmpty(configuredChannel)` half of the gate caused a
NEW regression: a TS apphost pinned to "daily" / "staging" / a custom
channel now searched only the implicit channel, losing access to
packages that live on the pinned feed.

Production change in IntegrationPackageSearchService:
  channels = hasHives || !string.IsNullOrEmpty(configuredChannel)
      ? allChannels
      : allChannels.Where(c => c.Type is PackageChannelType.Implicit);

This preserves the #17725 fix (narrowing is still gone, so the implicit
channel always participates and prerelease-only packages like Foundry
remain discoverable when pinned to a Stable-quality channel) while
keeping pinned explicit channels in the search.

Tests strengthened with per-channel invocation counters so that
"channel X was searched" is asserted directly rather than inferred from
the dedupe outcome. The Theory test is reframed: both arms agree on the
user-visible preferred result (Redis 1.0.0, implicit wins), but the
with-channel arm additionally hits the daily channel and the
without-channel arm does not.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds proof-by-test that the IPSS gate behaves identically when the CLI
is shipped as staging (`IdentityChannel == "staging"`) as it does today
with the PR dogfood build (where the channel name was `pr-17728`):

1. Adds `[InlineData("\"staging\"", true)]` to the existing theory
   `…PersistedChannelExpandsDiscoveryWithoutChangingPreferredResult`.
   This proves the IPSS gate (`hasHives || !string.IsNullOrEmpty(
   configuredChannel)`) is channel-name-opaque — `"staging"` and
   `"daily"` produce identical gate behavior.

2. Adds a new fact
   `IntegrationSearchCommandStagingStampedCliWithPinnedStagingApphost
   QueriesBothImplicitAndStagingChannelsAndSurfacesPrereleaseOnlyPackages`
   that exercises the exact shipping shape:
     * Real PackagingService (not the fake TestPackagingService) — so
       the real staging-channel synthesis path is exercised.
     * `IdentityChannel = Staging` — the CLI binary is stamped as the
       staging release identity, which is how shipped staging CLIs run.
     * `aspire.config.json` pins `"channel": "staging"` — which is what
       `aspire new` writes into polyglot apphosts on a staging-stamped
       CLI (see CliTemplateFactory.TypeScriptStarterTemplate).
     * No PR hives — this is a real installed CLI, not a dogfood build.
   Asserts both invariants:
     (i)  Total cache call count >= 2, proving both implicit AND staging
          channels were queried. Pre-fix narrowing would have produced
          exactly 1 call.
     (ii) A prerelease-only package returned only when prerelease=true
          surfaces to the user — proving the #17725 fix holds on a real
          staging release, not just on a PR build.

Together with the existing
`…UsesConfiguredStagingChannelWithRealPackagingService` (apphost-pin
triggers staging synthesis under Stable identity) and
`…UnpinnedAppHostUsesImplicitChannelUnderStagingCli` (staging identity
without pin correctly falls back to implicit-only), the staging
quadrant is now fully covered.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
GitHub was asked to rerun all failed jobs for that attempt, and the rerun is being tracked in the rerun attempt.
The job links below point to the failed attempt jobs that matched the retry-safe transient failure rules.

@mitchdenny
Copy link
Copy Markdown
Member Author

Staging-equivalence proof tests — green ✅

Pushed ec03c67eb: two surgical additions to AddCommandTests.cs that pin the staging-shipping behavior.

Why these tests prove the staging-stamped CLI will behave identically

  1. Code path is channel-name-opaque. IntegrationPackageSearchService.cs:45:

    var channels = hasHives || !string.IsNullOrEmpty(configuredChannel)
        ? allChannels
        : allChannels.Where(c => c.Type is PackageChannelType.Implicit);

    The gate never compares the channel string to a specific name, so "staging""daily""pr-17728" ≡ any non-empty value.

  2. PackagingService auto-synthesizes the staging channel under staging identity. PackagingService.cs:137-141 adds a synthesized staging channel to allChannels whenever _executionContext.IdentityChannel == "staging". The new fact exercises the real PackagingService (not a fake), so the synthesis path runs.

  3. aspire new writes the pin on staging-stamped CLIs. CliTemplateFactory.TypeScriptStarterTemplate.cs:62-73 persists inputs.Channel to aspire.config.json, so a staging-stamped CLI creating a TS apphost writes "channel": "staging". The new fact reproduces that exact config.

What was added

# Test Purpose
1 New [InlineData("\"staging\"", true)] arm on …PersistedChannelExpandsDiscoveryWithoutChangingPreferredResult Pins gate channel-name opacity.
2 New [Fact] IntegrationSearchCommandStagingStampedCliWithPinnedStagingApphostQueriesBothImplicitAndStagingChannelsAndSurfacesPrereleaseOnlyPackages Exact shipping shape: real PackagingService + IdentityChannel=Staging + pinned "staging" in aspire.config.json. Asserts (a) totalCacheCalls >= 2 (both implicit + staging queried — pre-fix narrowing produced exactly 1), (b) prereleaseRequested >= 1 (proves #17725 fix holds on a real staging release).

Results

Build succeeded.
    0 Warning(s)
    0 Error(s)

# Targeted run (3 theory arms + 3 staging-related facts):
Test run summary: Passed!
  total: 6
  failed: 0
  succeeded: 6

# Full AddCommandTests class regression sweep:
Test run summary: Passed!
  total: 50
  failed: 0
  succeeded: 50

Staging quadrant coverage (now complete)

Identity apphost pin Test
Stable "staging" …UsesConfiguredStagingChannelWithRealPackagingService (pre-existing)
Staging (none) …UnpinnedAppHostUsesImplicitChannelUnderStagingCli (pre-existing)
Staging "staging" new …StagingStampedCliWithPinnedStagingApphost… ← the shipping shape
Any name-opacity new [InlineData("\"staging\"", true)] theory arm

// (https://github.com/microsoft/aspire/issues/17724). Refusing with an actionable error
// forces the caller to supply an exact package id or friendly name.
if (filteredPackagesWithShortName.Count == 0 && integrationName is not null && !_hostEnvironment.SupportsInteractiveInput)
{
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.

This still leaves the interactive repro unfixed. aspire add kube (without --non-interactive) follows the fuzzy fallback below, and if that returns a single candidate, GetPackageByInteractiveFlow auto-selects it via distinctPackages.Length == 1 instead of prompting. #17724 was observed in interactive mode too, so this guard needs to apply to fuzzy matches generally, or the single fuzzy-candidate case needs to force an explicit prompt/confirmation instead of silently installing the first match.

Prompt before adding a single fuzzy or no-match fallback candidate in interactive aspire add flows, while preserving exact-match auto-selection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

CLI E2E Tests unknown — 110 passed, 0 failed, 2 unknown (commit cdd0271)

View all recordings
Status Test Recording Job Artifacts
AddPackageInteractiveWhileAppHostRunningDetached Recording #78674241686 Logs
AddPackageWhileAppHostRunningDetached Recording #78674241686 Logs
AgentCommands_AllHelpOutputs_AreCorrect Recording #78674241983 Logs
AgentInitCommand_DefaultSelection_InstallsDefaultSkills Recording #78674241983 Logs
AgentInitCommand_MigratesDeprecatedConfig Recording #78674241983 Logs
AgentInitCommand_NonInteractive_BundleOnlySkillsBeyondCliCatalog_AreInstallable Recording #78674241983 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp Recording #78674241829 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_DevLocalhost Recording #78674241829 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_Isolated Recording #78674241829 Logs
AllPublishMethodsBuildDockerImages Recording #78674241978 Logs
AspireAddAndStartWorkAgainstLegacyAppHostTs Recording #78674241819 Logs
AspireAddPackageVersionToDirectoryPackagesProps Recording #78674241693 Logs
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost Recording #78674241827 Logs
AspireInitWithExistingAppHostDirRecreatesMissingNuGetConfigAndPreservesFiles Recording #78674241766 Logs
AspireInitWithSolutionFileGeneratesAppHostThatBuildsAgainstChannelHive Recording #78674241766 Logs
AspireStartUpdatesStaleTypeScriptAppHostPath Recording #78674241838 Logs
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps Recording #78674241693 Logs
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent Recording #78674241693 Logs
Banner_DisplayedOnFirstRun Recording #78674242075 Logs
Banner_DisplayedWithExplicitFlag Recording #78674242075 Logs
Banner_NotDisplayedWithNoLogoFlag Recording #78674242075 Logs
CertificatesClean_RemovesCertificates Recording #78674241718 Logs
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate Recording #78674241718 Logs
CertificatesTrust_WithUntrustedCert_TrustsCertificate Recording #78674241718 Logs
ConfigSetGet_CreatesNestedJsonFormat Recording #78674241532 Logs
CreateAndRunAspireStarterProject Recording #78674242019 Logs
CreateAndRunAspireStarterProjectWithBundle Recording #78674241993 Logs
CreateAndRunEmptyAppHostProject Recording #78674241862 Logs
CreateAndRunJavaEmptyAppHostProject Recording #78674242070 Logs
CreateAndRunJsReactProject Recording #78674242014 Logs
CreateAndRunPolyglotAppHostWithDevLocalhostUrls Recording #78674242019 Logs
CreateAndRunPythonReactProject Recording #78674242110 Logs
CreateAndRunTypeScriptEmptyAppHostProject Recording #78674241942 Logs
CreateAndRunTypeScriptStarterProject Recording #78674241963 Logs
CreateJavaAppHostWithViteApp Recording #78674241841 Logs
CreateTypeScriptAppHostWithViteApp_AllowsGuestAppPackageManagerToDiffer Recording #78674241971 Logs
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain Recording #78674241971 Logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces Recording #78674241845 Logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces_DevLocalhost Recording #78674241845 Logs
DashboardRunWithOtelTracesReturnsNoTraces Recording #78674241845 Logs
DashboardRunWithOtelTracesReturnsNoTraces_DevLocalhost Recording #78674241845 Logs
DeployK8sBasicApiService Recording #78674241851 Logs
DeployK8sWithExternalHelmChart Recording #78674242084 Logs
DeployK8sWithGarnet Recording #78674241999 Logs
DeployK8sWithMongoDB Recording #78674241725 Logs
DeployK8sWithMySql Recording #78674241940 Logs
DeployK8sWithPostgres Recording #78674241939 Logs
DeployK8sWithRabbitMQ Recording #78674241728 Logs
DeployK8sWithRedis Recording #78674241925 Logs
DeployK8sWithSqlServer Recording #78674241566 Logs
DeployK8sWithValkey Recording #78674241742 Logs
DeployTypeScriptAppToKubernetes Recording #78674241712 Logs
DescribeCommandResolvesReplicaNames Recording #78674241973 Logs
DescribeCommandShowsRunningResources Recording #78674241973 Logs
DetachFormatJsonProducesValidJson Recording #78674241796 Logs
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance Recording #78674241796 Logs
DoPublishAndDeployListStepsWork Recording #78674242006 Logs
DocsCommand_RendersInteractiveMarkdownFromLocalSource Recording #78674242081 Logs
DoctorCommand_DetectsDeprecatedAgentConfig Recording #78674241983 Logs
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain Recording #78674241617 Logs
DoctorCommand_WithSslCertDir_ShowsTrusted Recording #78674241617 Logs
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted Recording #78674241617 Logs
GatewayWithoutExternalEndpoint_FailsPublishWithGuidance Recording #78674242079 Logs
GeneratedAspireDevScript_StartsWatchMode_WithConfiguredToolchain Recording #78674241971 Logs
GlobalMigration_HandlesCommentsAndTrailingCommas Recording #78674241532 Logs
GlobalMigration_HandlesMalformedLegacyJson Recording #78674241532 Logs
GlobalMigration_PreservesAllValueTypes Recording #78674241532 Logs
GlobalMigration_SkipsWhenNewConfigExists Recording #78674241532 Logs
GlobalSettings_MigratedFromLegacyFormat Recording #78674241532 Logs
IngressWithoutExternalEndpoint_FailsPublishWithGuidance Recording #78674242079 Logs
InitTypeScriptAppHost_AugmentsExistingViteRepoInWorkspaceSubdirectory Recording #78674241971 Logs
InteractiveCSharpInitCreatesExpectedFiles Recording #78674242094 Logs
InvalidAppHostPathWithComments_IsHealedOnRun Recording #78674241967 Logs
JavaScriptHostingApisRunFromTypeScriptAppHost Recording #78674241978 Logs
LatestCliCanStartStableChannelAppHost Recording #78674242019 Logs
LatestCliCanStartStableChannelTypeScriptAppHost Recording #78674242019 Logs
LegacySettingsMigration_AdjustsRelativeAppHostPath Recording #78674241838 Logs
LogsCommandShowsResourceLogs Recording #78674241704 Logs
OtelLogsReturnsStructuredLogsFromStarterApp Recording #78674241748 Logs
OtelLogsReturnsStructuredLogsFromStarterAppIsolated Recording #78674241748 Logs
PsCommandListsRunningAppHost Recording #78674241969 Logs
PsFormatJsonOutputsOnlyJsonToStdout Recording #78674241969 Logs
PublishJavaScriptPatternsGeneratesExpectedDockerComposeArtifacts Recording #78674242161 Logs
PublishWithConfigureEnvFileUpdatesEnvOutput Recording #78674242161 Logs
PublishWithDockerComposeServiceCallbackSucceeds Recording #78674242161 Logs
PublishWithoutOutputPathUsesAppHostDirectoryDefault Recording #78674242161 Logs
ResourceCommand_FailedExecution_DisplaysAppHostLogPathAndLogContainsEntries Recording #78674241732 Logs
ResourceCommand_SetAndDeleteParameterUpdatesDescribeOutput Recording #78674241732 Logs
RestoreGeneratesSdkFiles Recording #78674241490 Logs
RestoreGeneratesSdkFiles_WithConfiguredToolchain Recording #78674241571 Logs
RestoreRefreshesGeneratedSdkAfterAddingIntegration Recording #78674241571 Logs
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes Recording #78674241715 Logs
RunFromParentDirectory_UsesExistingConfigNearAppHost Recording #78674242073 Logs
RunReportsSyntaxErrorsForDotNetAppHost Recording #78674241843 Logs
RunReportsSyntaxErrorsForTypeScriptAppHost Recording #78674241843 Logs
SecretCrudOnDotNetAppHost Recording #78674241811 Logs
SecretCrudOnTypeScriptAppHost Recording #78674242008 Logs
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels Recording #78674241655 Logs
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets Recording #78674241699 Logs
StartReportsSyntaxErrorsForDotNetAppHost Recording #78674241843 Logs
StartReportsSyntaxErrorsForTypeScriptAppHost Recording #78674241843 Logs
StopAllAppHostsFromAppHostDirectory Recording #78674242077 Logs
StopJavaPolyglotAppHostUsingApphostDirectory Recording #78674241974 Logs
StopNonInteractiveSingleAppHost Recording #78674242077 Logs
StopTypeScriptPolyglotAppHostUsingApphostDirectory Recording #78674241884 Logs
StopWithNoRunningAppHostExitsSuccessfully Recording #78674241686 Logs
TypeScriptAppHostRunDoesNotDeadlockWhenLazyOptionsInvokeAsyncCallback Recording #78674241942 Logs
UnAwaitedChainsCompileWithAutoResolvePromises Recording #78674241571 Logs
UpdateProjectChannelToStable_CSharpEmptyAppHost_PreservesAspireConfigChannel Recording #78674241857 Logs
UpdateProjectChannelToStable_CSharpSingleFileInit_PreservesAspireConfigChannel Recording #78674241857 Logs
UpdateProjectChannelToStable_TypeScriptSingleFileInit_PreservesAspireConfigChannel Recording #78674241857 Logs
UpdateProjectChannelToStable_TypeScript_PreviewsStablePackagesAndPreservesChannel Recording #78674241857 Logs

📹 Recordings uploaded automatically from CI run #26687745746

@davidfowl davidfowl merged commit 56e8866 into release/13.4 May 30, 2026
615 of 619 checks passed
@davidfowl davidfowl deleted the mitchdenny/fix-aspire-add-fuzzy-match-17724 branch May 30, 2026 20:35
@microsoft-github-policy-service microsoft-github-policy-service Bot modified the milestone: 13.4 May 30, 2026
aspire-repo-bot Bot added a commit to microsoft/aspire.dev that referenced this pull request May 30, 2026
…nd interactive confirmation behavior

Documents the behavior changes from microsoft/aspire#17728:
- Non-interactive mode now requires an exact friendly name or package ID
- Interactive mode now prompts before adding fuzzy/no-match fallback candidates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@aspire-repo-bot
Copy link
Copy Markdown
Contributor

Pull request created: #1139

Generated by PR Documentation Check

@aspire-repo-bot
Copy link
Copy Markdown
Contributor

📝 Documentation has been drafted in microsoft/aspire.dev#1139 targeting release/13.4.

Updated src/frontend/src/content/docs/reference/cli/commands/aspire-add.mdx to reflect the behavior changes in this PR:

  • integration argument: Clarified that interactive mode now prompts before adding any fuzzy or no-match fallback candidate (even a single result), and non-interactive mode requires an exact friendly name or full package ID — partial names produce an error.
  • New example: Added a --non-interactive example showing the exact-name requirement (kubernetes not kube).

Note

This draft PR needs human review before merging.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants