Fix mixed-quality staging package discovery - #19426
Conversation
Official staging feeds can contain stable packages alongside integrations that deliberately remain prerelease. Discover both qualities for staging identities while preserving strict stable and daily channel filtering. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2b95dfd3-c558-45ae-8d8e-d798fbd8d10c
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19426Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19426" |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Fixes staging package discovery so stable-shaped staging CLIs can find prerelease-only integrations.
Changes:
- Uses
Bothquality for official staging identities. - Expands package-discovery and command-selection regression tests.
- Updates staging validation scripts and documentation.
Show a summary per file
| File | Description |
|---|---|
src/Aspire.Cli/Packaging/PackagingService.cs |
Changes staging quality selection. |
tests/Aspire.Cli.Tests/Packaging/PackagingServiceTests.cs |
Tests staging channel construction. |
tests/Aspire.Cli.Tests/Packaging/PackageChannelTests.cs |
Tests quality-specific discovery. |
tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs |
Adds language/channel selection coverage. |
tests/Aspire.Cli.Tests/Projects/PrebuiltAppHostServerTests.cs |
Updates real service construction. |
tests/Aspire.Cli.Tests/TestServices/TestAppHostProjectFactory.cs |
Adds package callback support. |
tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs |
Removes version-shape override. |
eng/scripts/debug-stable.sh |
Updates expected staging quality. |
eng/scripts/debug-stable.ps1 |
Updates expected staging quality. |
eng/scripts/debug-aspire-channel.sh |
Adds a minimal TypeScript AppHost. |
eng/scripts/debug-aspire-channel.ps1 |
Adds a minimal TypeScript AppHost. |
docs/cli-staging-validation.md |
Documents mixed-quality staging behavior. |
.agents/skills/cli-channel-debugging/SKILL.md |
Updates channel-emulation guidance. |
Review details
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 13/13 changed files
- Comments generated: 1
- Review effort level: Balanced
PR Testing ReportPR Information
Artifact Version Verification
The CLI and packages were installed using the PR's dogfood command into an isolated path. The CLI's embedded short SHA, Changes AnalyzedFiles Changed
Change Categories
Test MethodThe PR dogfood CLI was the only binary under test.
Result Matrix
All template and package-add commands exited Test Scenarios ExecutedScenario 1: Actual PR build and local hiveObjective: Verify the PR build resolves packages from its co-installed hive and does not fall through to daily or stable packages. Coverage Type: Happy path and source-isolation boundary Evidence:
Observation: The package and template hive behavior is intact for both AppHost languages. Scenario 2: Daily build emulationObjective: Verify a daily identity stays on the shared prerelease feed for both AppHost languages. Coverage Type: Happy path and channel-precedence boundary Evidence:
Observation: The staging fix does not alter daily package selection. Scenario 3: Stable-shaped staging build emulationObjective: Verify a stable-shaped staging build can discover stable and deliberately prerelease packages from the same SHA-specific feed. Coverage Type: Primary regression scenario Evidence:
Observation: This directly proves the feed is mixed-quality and that Scenario 4: Current released build emulationObjective: Verify the latest released identity remains on NuGet.org and preserves shipped package-selection behavior. Coverage Type: Regression boundary Evidence:
Observation: The Azure Kubernetes result is the existing exact-ID fallback/implicit-channel behavior that allows a prerelease-only integration to accompany a stable release. It does not indicate that the explicit Stable broad-discovery contract was relaxed; production changes did not touch Negative and Boundary CoverageRemote identities cannot leak the PR hiveExpected Outcome: Daily, staging, and stable emulations must not select Status: ✅ Passed The neutral CLI copy used identity-specific Stable broad discovery remains strictExpected Outcome: Status: ✅ Passed The added Language-path parityExpected Outcome: C# and TypeScript must select the same package version for each identity even though C# can obtain feed mappings through NuGet configuration while TypeScript relies on its explicit configured channel. Status: ✅ Passed All four identity rows produced identical package versions across both languages. Additional Validation
Evidence
No screenshots were captured because this PR changes package resolution rather than visual UI. Summary
Overall Result✅ PR VERIFIED The fix is correctly scoped to official staging identities. It resolves the TypeScript/polyglot staging regression without changing PR hive selection, daily prerelease selection, released stable behavior, or the strict broad-discovery semantics of |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Cover both stable-versus-same-line-preview and current-preview-versus-older-stable selection through staging package discovery and the add version picker. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2b95dfd3-c558-45ae-8d8e-d798fbd8d10c
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. 2 / 101 test projects · 5 jobs, from 11 changed files. Selected test projects (2 / 101)
Selected jobs (5)
How these were chosen — grouped by what changed📦 affected project 🧪 🧪 🧪 🧪 🧪 🧪 Job reasons
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. |
James Newton-King (JamesNK)
left a comment
There was a problem hiding this comment.
Reviewed staging channel construction, package/version selection consumers, cross-shell diagnostics, and the added regression coverage at ce1c3f99.
I also installed the PR CLI (13.6.0-pr.19426.gce1c3f99) and exercised stable-shaped staging discovery from fresh C# and TypeScript AppHosts. Both resolved the SHA-specific feed with quality=Both; stable Redis 13.5.0 and prerelease-only Azure Kubernetes 13.5.0-preview.1.26415.2 were both discoverable.
No blocking issues found.
PR Testing Report:
|
| Scenario | Identity knobs | Aspire package source |
|---|---|---|
| PR hive | Baked pr-19426 / 13.6.0-pr.19426.gce1c3f99; no ASPIRE_CLI_* overrides |
CI-built pr-19426 local hive |
| Daily | ASPIRE_CLI_CHANNEL=daily, ASPIRE_CLI_VERSION=13.6.0-preview.1.26416.1 |
Shared dotnet9 daily feed |
| Stable-shaped staging | ASPIRE_CLI_CHANNEL=staging, ASPIRE_CLI_VERSION=13.5.0, ASPIRE_CLI_COMMIT=45f7776ddb51ba976a32ece224ef8b23ed989a91 |
SHA-specific darc-pub-microsoft-aspire-45f7776d feed |
| Released stable | ASPIRE_CLI_CHANNEL=stable, ASPIRE_CLI_VERSION=13.4.6 |
NuGet.org |
ASPIRE_CLI_PACKAGES was unset in every row. Daily, staging, and stable used a neutral copy of the
PR CLI plus isolated ASPIRE_HOME, NuGet, npm, and .NET caches, so the installed PR hive could not
replace or mask their remote channels.
Scenarios
Each identity used fresh directories for these four cells:
aspire new aspire-empty --language csharpfollowed bydotnet build apphost.cs.aspire new aspire-ts-emptyfollowed bynpm run aspire:build.aspire init --language csharpin a solution containing an existing ASP.NET Core project,
followed bydotnet buildof the generated AppHost project.aspire init --language typescriptin an existing npm project, followed by the generated
npm run aspire:builddelegation.
Every CLI invocation was non-interactive and suppressed agent initialization.
Result Matrix
| Identity | Command | AppHost | Selected/pinned package identity | Persisted TS channel | CLI | Build | Metadata |
|---|---|---|---|---|---|---|---|
| PR | new |
C# single-file | Aspire.AppHost.Sdk@13.6.0-pr.19426.gce1c3f99 |
N/A | ✅ | ✅ | ✅ |
| PR | new |
TypeScript | PR template/hive | pr-19426 |
✅ | ✅ | ✅ |
| PR | init |
C# project | Aspire.AppHost.Sdk/13.6.0-pr.19426.gce1c3f99 |
N/A | ✅ | ✅ | ✅ |
| PR | init |
TypeScript brownfield | Aspire.Hosting.JavaScript 13.6.0-pr.19426.gce1c3f99 |
pr-19426 |
✅ | ✅ | ✅ |
| Daily | new |
C# single-file | Aspire.AppHost.Sdk@13.6.0-preview.1.26416.1 |
N/A | ✅ | ✅ | ✅ |
| Daily | new |
TypeScript | Daily template | daily |
✅ | ✅ | ✅ |
| Daily | init |
C# project | Aspire.AppHost.Sdk/13.6.0-preview.1.26416.1 |
N/A | ✅ | ✅ | ✅ |
| Daily | init |
TypeScript brownfield | Aspire.Hosting.JavaScript 13.6.0-preview.1.26416.1 |
daily |
✅ | ✅ | ✅ |
| Staging | new |
C# single-file | Aspire.AppHost.Sdk@13.5.0 |
N/A | ✅ | ✅ | ✅ |
| Staging | new |
TypeScript | Staging template | staging |
✅ | ✅ | ✅ |
| Staging | init |
C# project | Aspire.AppHost.Sdk/13.5.0 |
N/A | ✅ | ✅ | ✅ |
| Staging | init |
TypeScript brownfield | Aspire.Hosting.JavaScript 13.5.0 |
staging |
✅ | ✅ | ✅ |
| Stable | new |
C# single-file | Aspire.AppHost.Sdk@13.4.6 |
N/A | ✅ | ✅ | ✅ |
| Stable | new |
TypeScript | Stable template | none | ✅ | ✅ | ✅ |
| Stable | init |
C# project | Aspire.AppHost.Sdk/13.4.6 |
N/A | ✅ | ✅ | ✅ |
| Stable | init |
TypeScript brownfield | Aspire.Hosting.JavaScript 13.4.6 |
none | ✅ | ✅ | ✅ |
All 16 cells returned:
command_exit=0build_exit=0metadata_exit=0
Channel and Version Evidence
PR hive
- C#
newandinitgenerated NuGet mappings to the isolated
install/hives/pr-19426/packagesdirectory. - C# project-mode
initinstalled the exact local package:
Aspire.ProjectTemplates.13.6.0-pr.19426.gce1c3f99.nupkg. - TypeScript
newandinitpersistedchannel: "pr-19426".
Daily
- C#
newandinitgenerated mappings to the shareddotnet9feed. - C# project-mode
initinstalled:
Aspire.ProjectTemplates@13.6.0-preview.1.26416.1. - TypeScript
newandinitpersistedchannel: "daily". - TypeScript
initpinnedAspire.Hosting.JavaScriptto
13.6.0-preview.1.26416.1.
Stable-shaped staging
-
All four staging commands resolved:
feed=.../darc-pub-microsoft-aspire-45f7776d/nuget/v3/index.json, quality=Both -
C#
newpinned the single-file SDK to stable13.5.0. -
C# project-mode
initqueried both stable and prerelease results, then installed stable
Aspire.ProjectTemplates@13.5.0from the SHA-specific staging feed. -
TypeScript
newandinitpersistedchannel: "staging". -
TypeScript
initpinned stableAspire.Hosting.JavaScript13.5.0.
This is the important boundary for the production change: Both does not cause the stable staging
template or stable JavaScript integration to drift to a prerelease. SemVer still selects stable
13.5.0, while prerelease-only integrations remain discoverable from the same staging feed.
Released stable
- C#
newandinitpinnedAspire.AppHost.Sdkto13.4.6. - C# project-mode
initinstalledAspire.ProjectTemplates@13.4.6from NuGet.org. - TypeScript did not persist a channel, preserving released stable's implicit public-feed behavior.
- TypeScript
initpinnedAspire.Hosting.JavaScriptto13.4.6.
Isolation and Boundary Checks
- No generated daily, staging, or stable project contained a reference to
13.6.0-pr.19426.... - PR-generated C# NuGet configurations mapped Aspire packages to the PR hive.
- Daily-generated C# NuGet configurations mapped Aspire packages to
dotnet9. - Staging-generated C# NuGet configurations mapped Aspire packages to the SHA-specific darc feed.
- Stable generated no unnecessary channel-specific NuGet configuration.
- TypeScript channel persistence matched the identity in every non-stable row and remained absent
for stable. - PR CI currently reports 364 successful checks, zero failures, and zero pending checks.
Harness Note
An initial harness pass assumed C# aspire-empty produced a .csproj. The command correctly
produced the current single-file apphost.cs shape, so the artifact detector was corrected and the
entire matrix was rerun from fresh directories. The final results above are from that clean rerun.
Evidence
pr-19426-new-init-matrix-results.tsvpr-19426-new-init-evidence.tar.gz- Per-cell
command.log,build.log, and preparation logs. - Generated
aspire.config.json, NuGet configuration, AppHost source/projects, and package
manifests.
- Per-cell
run-pr-19426-new-init-matrix.sh
No screenshots were captured because the changed behavior is package/channel resolution rather than
visual UI.
Overall Result
✅ PR VERIFIED
aspire new and aspire init remain functional and buildable for C# and TypeScript AppHosts across
PR hives, daily builds, stable-shaped staging builds, and the current released stable build. The
staging Both change preserves stable template/package selection while enabling mixed-quality
staging discovery.
|
/backport to release/13.5 |
|
Started backporting to |
|
Mitch Denny (@mitchdenny) backporting to git am output$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Fix mixed-quality staging package discovery
Using index info to reconstruct a base tree...
M src/Aspire.Cli/Packaging/PackagingService.cs
M tests/Aspire.Cli.Tests/Packaging/PackageChannelTests.cs
M tests/Aspire.Cli.Tests/Packaging/PackagingServiceTests.cs
M tests/Aspire.Cli.Tests/Projects/PrebuiltAppHostServerTests.cs
M tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs
Falling back to patching base and 3-way merge...
Auto-merging src/Aspire.Cli/Packaging/PackagingService.cs
Auto-merging tests/Aspire.Cli.Tests/Packaging/PackageChannelTests.cs
CONFLICT (content): Merge conflict in tests/Aspire.Cli.Tests/Packaging/PackageChannelTests.cs
Auto-merging tests/Aspire.Cli.Tests/Packaging/PackagingServiceTests.cs
Auto-merging tests/Aspire.Cli.Tests/Projects/PrebuiltAppHostServerTests.cs
Auto-merging tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs
error: Failed to merge in the changes.
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 0001 Fix mixed-quality staging package discovery
Error: The process '/usr/bin/git' failed with exit code 128 |
Documents microsoft/aspire#19426 - Fix mixed-quality staging package discovery. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Pull request created: #1505
|
|
📝 Documentation has been drafted in microsoft/aspire.dev#1505 targeting Added a note and example to the Note This draft PR needs human review before merging. |
Description
Stable-shaped staging builds can publish a mixed package set to their SHA-specific feed: most packages use the stable build version, while integrations such as Azure Kubernetes deliberately remain prerelease. The TypeScript/polyglot
aspire addpath used the explicit staging channel and filtered it as stable-only, so those integrations disappeared from discovery. C# appeared to work because its generated NuGet configuration exposed the same feed through an implicitBothchannel, masking the incorrectly narrow staging channel.Official staging identities now discover both stable and prerelease packages from their SHA-specific feed. This is intentionally scoped to staging channel construction: released Stable broad discovery remains stable-only, Daily remains prerelease-only, and feature-flag-only staging retains its existing stable-only behavior. Existing exact-package fallback is unchanged, so a released CLI can still add a release-matched integration that deliberately remains prerelease.
The regression coverage includes real
PackagingServicechannel construction and polyglot tag discovery, strict Stable/Prerelease/Both package-channel contracts, and a C#/TypeScript × staging/daily/PR command-selection matrix. The staging validation scripts now create a minimal TypeScript AppHost so they reach package discovery.User-facing usage
On a stable-shaped staging CLI, Azure Kubernetes is now available from both C# and TypeScript AppHosts:
Validation
The PR dogfood CLI was verified across fresh C# and TypeScript AppHosts for all supported identity shapes:
13.6.0-pr.19426.g6c29f90e13.6.0-preview.1.26416.113.5.0+45f7776d...13.5.0and Azure Kubernetes13.5.0-preview.1.26415.2resolved from the same SHA feed withquality=Both13.4.613.4.6-preview.1.26319.6All eight runtime cells passed. The full
Aspire.Cli.Testsproject also passed with 4,991 tests succeeding and 34 platform-specific tests skipped. See the full PR testing report.Fixes #19423
Checklist
<remarks />and<code />elements on your triple slash comments?