fix(cli): honor --source for TypeScript empty AppHost restore#17166
fix(cli): honor --source for TypeScript empty AppHost restore#17166radical wants to merge 3 commits into
Conversation
aspire new aspire-empty --language typescript --source <pr-hive> --version <pr-version> parsed --source, but the empty AppHost TypeScript scaffolding path dropped it before the prebuilt AppHost restored Aspire.Hosting and TypeScript code-generation packages. The bundled restore then searched channel sources, missed the requested PR hive packages, and NuGet floated to a stale preview package set, which later failed with TypeLoadException when the generator loaded against the PR CLI's Aspire.TypeSystem. Flow TemplateInputs.Source into ScaffoldContext, pass it to IAppHostServerProject.PrepareAsync, and have PrebuiltAppHostServer add that source to package and closure restores. When a source override is present, use exact version ranges so restore fails rather than silently resolving a different Aspire prerelease. Fixes microsoft#17159 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17166Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17166" |
|
There is a second part of the fix that improves this when |
Remove whitespace-only changes that are unrelated to the source restore fix, keeping the PR focused on the explicit package source propagation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR Testing ReportPR Information
CLI Version Verification
Changes AnalyzedFiles Changed
Change Categories
Test Scenarios ExecutedScenario 1: PR CLI install + version matchObjective: Install the PR dogfood CLI and verify it matches the PR head commit. Evidence:
Scenario 2: TypeScript empty template with explicit PR hive sourceObjective: Verify Command shape: aspire new aspire-empty --language typescript --name PrSourceTs3 --output <temp>/PrSourceTs3 --version 13.4.0-pr.17166.ga49d604d --localhost-tld false --suppress-agent-init --non-interactive --source <explicit-pr-packages>Evidence:
Observation: The project was created successfully and TypeScript dependencies were installed. This scenario used a short temp Scenario 3: TypeScript empty template without explicit sourceObjective: Confirm the test setup still exposes the source-dependent failure when the explicit source is omitted. Command shape: aspire new aspire-empty --language typescript --name NoSourceTs3 --output <temp>/NoSourceTs3 --version 13.4.0-pr.17166.ga49d604d --localhost-tld false --suppress-agent-init --non-interactiveEvidence:
Observed error: Observation: This reproduces the issue signature when the explicit package source is not available to the restore path. Non-applicable attempted scenariosPython and Go were initially attempted for Summary
Overall Result✅ PR VERIFIED The downloaded PR CLI honors |
There was a problem hiding this comment.
Pull request overview
This PR fixes aspire new aspire-empty --language typescript failures when callers supply --source (e.g., a PR hive) by threading the source override through the empty-template scaffolding path into AppHost server preparation, and ensuring the prebuilt AppHost restore uses that override (including exact-version restores when an explicit source is provided) to avoid mixed-binary package sets.
Changes:
- Thread
TemplateInputs.SourcethroughScaffoldContextintoIAppHostServerProject.PrepareAsync(...)aspackageSourceOverride. - Update
PrebuiltAppHostServerrestore logic to include the explicit source for both package-only restore and project-closure restore, and restore exact versions when an explicit source is provided. - Add/adjust tests to validate the override is passed through and that restore is invoked with the expected sources/version constraints.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Cli.Tests/TestServices/FakeFailingAppHostServerProject.cs | Updates fake to match new PrepareAsync signature with source override. |
| tests/Aspire.Cli.Tests/Scaffolding/ChannelReseedTests.cs | Adds coverage that scaffolding passes PackageSourceOverride into PrepareAsync. |
| tests/Aspire.Cli.Tests/Projects/PrebuiltAppHostServerTests.cs | Adds coverage that bundled restore uses --source override and exact-version package args. |
| tests/Aspire.Cli.Tests/Projects/AppHostServerSessionTests.cs | Updates test fake to match the updated PrepareAsync signature. |
| src/Aspire.Cli/Templating/CliTemplateFactory.EmptyTemplate.cs | Passes inputs.Source into ScaffoldContext.PackageSourceOverride for empty templates. |
| src/Aspire.Cli/Scaffolding/ScaffoldingService.cs | Forwards PackageSourceOverride into IAppHostServerProject.PrepareAsync. |
| src/Aspire.Cli/Scaffolding/IScaffoldingService.cs | Extends ScaffoldContext with PackageSourceOverride. |
| src/Aspire.Cli/Projects/PrebuiltAppHostServer.cs | Applies source override to restore paths; enforces exact version restore when override is set. |
| src/Aspire.Cli/Projects/IAppHostServerProject.cs | Extends PrepareAsync contract to accept an optional packageSourceOverride. |
| src/Aspire.Cli/Projects/DotNetBasedAppHostServerProject.cs | Updates signature to satisfy the extended IAppHostServerProject contract. |
When an explicit package source is passed to guest AppHost restore, keep the exact-version pinning scoped to Aspire packages because that is the source mapping being overridden. Non-Aspire integration packages should retain normal NuGet minimum-version restore semantics. Also apply the temporary NuGet.config to the project-reference closure restore path instead of only adding sources to the synthetic project. That keeps package source mapping and channel-specific restore settings active when package and project integrations are restored together. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| /// </summary> | ||
| internal sealed class PrebuiltAppHostServer : IAppHostServerProject | ||
| { | ||
| private const string NuGetOrgSource = "https://api.nuget.org/v3/index.json"; |
Description
What broke
Creating an empty TypeScript AppHost from PR hive packages failed even when the caller explicitly pointed the CLI at that hive:
Instead of creating the project, the command failed during TypeScript code generation with a
TypeLoadExceptionforAspire.TypeSystem.AtsJsonCodeWriter.Full error from the failing run
Why it broke
aspire newparsed--source, but the empty guest-language scaffolding path dropped it before restoring the prebuilt AppHost packages.That meant the restore never searched the requested PR hive. NuGet then treated the requested PR version as a minimum version and floated to a different preview package set. The TypeScript generator from that stale package set was loaded next to the PR CLI's
Aspire.TypeSystem, and the binary mismatch surfaced as theTypeLoadException.Fix
This change threads the explicit source through the full guest-language scaffold path:
PrebuiltAppHostServernow uses that source for both package-only restore and project-reference closure restore. When an explicit source is supplied, it also restores exact package versions so a missing PR package fails clearly instead of silently resolving another Aspire prerelease.This intentionally does not change default route-local hive discovery for PR/localhive installs; that belongs with the acquisition coherence work.
Fixes #17159
Validation
dotnet test --project tests/Aspire.Cli.Tests/Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-class "*.Projects.PrebuiltAppHostServerTests" --filter-class "*.Scaffolding.ChannelReseedTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"dotnet test --project tests/Aspire.Cli.Tests/Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"Checklist
<remarks />and<code />elements on your triple slash comments?