Skip to content

Local hive channel does not surface its packages directory as a NuGet --source during restore #16804

@davidfowl

Description

@davidfowl

Summary

When the CLI resolves the local channel (or any PR/local hive channel created in PackagingService.cs:42-61), the channel correctly maps Aspire* packages to the hive's packages/ directory in code, but BundleNuGetService invokes nuget restore without that path as a --source. Restore then falls through to the public feeds and picks up whichever public preview happens to satisfy the version constraint, completely bypassing the locally built nupkgs.

Repro

  1. Build the repo: ./build.sh --pack /p:SkipNativeBuild=true (produces Aspire.Hosting.JavaScript.13.4.0-dev.nupkg etc. in artifacts/packages).
  2. Stage them into a hive directory: <repo>/.aspire/hives/local/packages/*.nupkg.
  3. Use the aspire-managed from the same build, with aspire.config.json pinning channel: "local" and Aspire.Hosting.JavaScript: 13.4.0-dev.
  4. Run aspire restore --debug from a TypeScript apphost.

Observed

[dbug] PrebuiltAppHostServer: Resolved channel: local
[dbug] BundleNuGetService: NuGet restore args: nuget restore ... \
       --package Aspire.Hosting.JavaScript,13.4.0-dev ... \
       --source https://api.nuget.org/v3/index.json \
       --source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json

The local hive directory is never passed as a --source. NuGet then reaches out to the public feeds and resolves 13.4.0-preview.1.26229.5 (because 13.4.0-dev < 13.4.0-preview.* and --package X,Y means "min version Y"). The extracted DLLs come from the wrong build, so any new APIs in the local hive (e.g. WithWorkspaceRoot) are silently absent from the generated TypeScript SDK / loaded assemblies.

Expected

The resolved channel's PackageMapping set should be reflected verbatim in the nuget restore --source arguments. For local/PR hives, that means including the on-disk <hive>/packages path. With it, restore correctly resolves 13.4.0-dev from the hive (verified by adding a NuGet.config containing <add key="local-hive" value="/workspace/.aspire/hives/local/packages" /> as a workaround — restore then pulls Aspire.Hosting.JavaScript/13.4.0-dev and codegen produces the expected withWorkspaceRoot binding).

Workaround

Drop a NuGet.config in the apphost directory (or any ancestor) that adds the hive packages path as a feed:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="local-hive" value="/path/to/.aspire/hives/local/packages" />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>

Impact

  • Inner-loop dogfooding of CLI changes is broken: even with a freshly packed local hive, restore silently pulls the public preview, masking any newly added APIs.
  • PR-build channels likely have the same issue: the prHive.Name channel is created with a packages mapping, but if BundleNuGetService doesn't propagate that mapping into the restore command, PR validation runs against whatever is on the public feeds.

Pointers

  • src/Aspire.Cli/Packaging/PackagingService.cs:42-61 — channel mapping construction
  • src/Aspire.Cli/Projects/PrebuiltAppHostServer.cs — channel resolution & restore wiring
  • BundleNuGetService — emits the actual nuget restore command with --source args (this is where the mappings need to land)

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-engineering-systemsinfrastructure helix infra engineering repo stuff

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions