-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Is your feature request related to a problem? Please describe.
Today folks that want to use nightly builds of the SDK (or even use the redist build here from the repo, etc) face two fundamental problems:
- getting the bits
- getting the bits configured with the correct feeds so that our long-tail of NuGet-package-delivered functionality lights up
- this is things like workloads, self-contained publishing, trimming, AOT, single-file hosts, apphosts, etc
Today, the 'get the bits' problem is at least somewhat mitigated by
- the dotnet/dotnet VMR builds table
- the dotnet-install scripts nightly feeds
- the internal release-tracker tool (for private builds, security release previews, and so on)
In the future, some people (it's me, I'm the people) would like SDK PRs to generate bundles that would be usable for testing/validation purposes - but that's just an expansion of the VMR use case for the purposes of this discussion.
Regardless of how users get the bits, they need to do additional NuGet feed configuration in order for all of our implicit PackageReferences and PackageDownloads to work. This often hits Visual Studio dogfooders when we insert an unreleased SDK into VS ahead of public release for overall alignment purposes.
Describe the solution you'd like
The actual goal is the SDK bits you download should be able to access a pre-configured feed, and that feed should be configured to only server/impact the use of the .NET SDK's implicit PackageReferences/PackageDownloads
One implementation towards this goal could be:
- expanding the compositional lookup hierarchy of the NuGet.config file today from "machine, then user, then solution/repo" to "machine, then toolchain, then user, then solution/repo"
- essentially allowing the .NET SDK layout/install a place to influence source configuration/resolution
- this would need design and agreement from the @dotnet/nuget-team, naturally, though it may provide a more 'official' or 'natural' way for concepts like the Visual Studio fallback feed to be configured.
- 'toolchain' for the dotnet CLI environment would be the SDK install root, and for the VS environment would be some other location that VS installations can control. there should be a design/agreement around this.
- making the SDK build process (in the SDK repo, and then eventually in the VMR) emit a NuGet.config file that specifies
- the correct package source(s) that serve every implicitly-used package the SDK toolchain may insert into a project's dependency hierarchy
- package source mapping entries to ensure those implicitly-used packages are only served from those preconfigured feeds
- depending on the usage of the SDK in question (SDK repo PR build, VMR nightly, final stable release, VS insertion), the generate NuGet.config may or may not be included in the actual SDK layout:
- SDK repo PR build: included
- VMR nightly build: included
- final stable release before public release: not included, but generated and easily gettable? maybe by tooling?
- final stable release (or servicing previews): not included
- VS insertion (of stable releases or servicing releases): not included in the SDK, but could potentially be included as a component?
Contents of the generated NuGet.config
An SDK manipulates the following kinds of packages that should be sourced from the non-NuGet.org feeds in this scenario
- workload packs
- workload manifests
- runtime packs
- targeting packs
- actual NuGet packages
Many of these have a well-known set of name patterns or are knowable statically, so we should be able to relatively easily know which feed(s) they should be sourced from.
Let's consider a single pack - the linux-x64 AppHosts pack Microsoft.NETCore.App.Host.linux-x64 across net8/9/10 TFMs across the scenarios above:
| scenario | TFM | feed |
|---|---|---|
| SDK PR | NET10 | dotnet-10 |
| SDK PR | NET9 | dotnet-9 |
| SDK PR | NET8 | dotnet-8 |
| VMR nightly | NET10 | dotnet-10 |
| VMR nightly | NET9 | dotnet-9 |
| VMR nightly | NET8 | dotnet-8 |
| Stable release prior to public | NET10 | release-specific dotnet-10 prep feed |
| Stable release prior to public | NET9 | release-specific dotnet-9 prep feed |
| Stable release prior to public | NET8 | release-specific dotnet-8 prep feed |
| Stable release | NET10 | N/A - defer entirely to user config |
| Stable release | NET9 | N/A - defer entirely to user config |
| Stable release | NET8 | N/A - defer entirely to user config |
| VS Insertion of unreleased | NET10 | release-specific dotnet-10 prep feed |
| VS Insertion of unreleased | NET9 | release-specific dotnet-9 prep feed |
| VS Insertion of unreleased | NET8 | release-specific dotnet-8 prep feed |
This is highly pattern-based and would be fairly easy to template out and generate during the build.
The generated NuGet.config would look something like:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="dotnet-10" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10/nuget/v3/index.json" />
<add key="dotnet-9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" />
...
</packageSources>
<packageSourceMapping>
<packageSource key="dotnet-10">
<package pattern="Microsoft.NETCore.App.Host.linux-x64" />
</packageSource>
<packageSource key="dotnet-9">
<package pattern="Microsoft.NETCore.App.Host.linux-x64" />
</packageSource>
...
</packageSourceMapping>
</configuration>By explicitly mapping the packages the SDK will automatically provide, we limit the scope of usage of these feeds in whatever end-user configurations that may exist.
The thinking here is that for the most painful use cases today we can actually know what the correct feeds are - and potentially with some release tracker work we can also make the NuGet.config for the stable-but-not-yet-released SDKs more easily usable by internal partners.
Open Questions
Template packages
Problem: @DamianEdwards brings up templates that we ship and how those often include PackageReferences that would also need to be updated.
Solution: Add mapping entries for Microsoft.* and System.* to the generated config as well. For PRs/Nightlies these would probably point to dotnet-libraries and/or dotnet-tools, and for internals we'd point to the per-release dedicated feeds. This makes it more important that we use explicit packageId mapping entries for the runtime packs, workloads, etc so that we don't reintroduce dependency confusion.
Global package directory dirtying
Problem: These nuget.configs would introduce package versions that aren't available on end-user package sources to the global package cache. That could cause confusion if users switch between preview/nightly SDKs and stable SDKs for their 'real' work.
Solution: generated nuget.configs should use a separate global packages cache to prevent this dirtying.
Drawbacks
- NuGet.config location would need expansion.
- NuGet.config allows removal of package sources (and maybe PSM data? need clarification on that), so it's possible and maybe even likely that the generated config would still conflict with user repo configurations. That's ok though - users that customize their repo NuGet configuration should be able to navigate this, and we can doc the behavior/experience.
- It would force us to reconcile with the set of packages we work with implicitly
- this is actually a benefit, though - we should know this and track it