-
Notifications
You must be signed in to change notification settings - Fork 138
Description
The changes to update to a newer SDK version for the VMR revealed issues with how NuGet is loading packages from the local feeds defined by source build. The results of builds with those changes yielded builds that would sometimes succeed and sometimes fail. The ones which failed showed a lot of poison leaks.
Let's take a look at just one of those leaks:
<File Path="artifacts/assets/Release/dotnet-sdk-x.y.z/sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools/netx.y/any/BuildHost-netcore/Humanizer.dll">
<Type>AssemblyAttribute</Type>
</File>This comes from Roslyn which has a dependency on Humanizer. Humanizer is originally defined in source-build-externals but it also exists in the previously source built artifacts with the same version since the version hasn't been updated in quite a while.
Here's what the source-built-modified NuGet.config file looks like:
<add key="source-built-transport-runtime" value="/vmr/artifacts/packages/Release/NonShipping//runtime/" />
<add key="source-built-transport-emsdk" value="/vmr/artifacts/packages/Release/NonShipping//emsdk/" />
<add key="source-built-transport-cecil" value="/vmr/artifacts/packages/Release/NonShipping//cecil/" />
<add key="source-built-transport-arcade" value="/vmr/artifacts/packages/Release/NonShipping//arcade/" />
<add key="source-built-runtime" value="/vmr/artifacts/packages/Release/Shipping//runtime/" />
<add key="source-built-source-build-externals" value="/vmr/artifacts/packages/Release/Shipping//source-build-externals/" />
<add key="source-built-emsdk" value="/vmr/artifacts/packages/Release/Shipping//emsdk/" />
<add key="source-built-command-line-api" value="/vmr/artifacts/packages/Release/Shipping//command-line-api/" />
<add key="reference-packages" value="/vmr/prereqs/packages/reference/" />
<add key="previously-source-built" value="/vmr/prereqs/packages/previously-source-built/" />
<add key="prebuilt" value="/vmr/prereqs/packages/prebuilt/" />Prior to bootstrapping onto this newer SDK version, the behavior of source build would always load the Humanizer package from the source-built-source-build-externals feed since that is the first feed listed containing this package. But with newer SDK version, there is likely some NuGet change which no longer is consistent wrt the ordering of these local feeds. This non-determinism has always been true and has been documented. Before the implementation seemed to be that local feeds were sequentially processed in order. That no longer seems to be the case. So in some builds we now load Humanizer from the previously-source-built feed. This leads to the poison leak.
The theory is that this can be fixed with the use of package source mappings. The tricky thing with package source mappings is that they operate at the package ID (e.g. name) level which doesn't include the version. So you can't say I want to get this specific package with this specific version from this specific feed. Instead, we'll need to define some rules of which package IDs are defined for which feeds based on the N-1 and current packages.
The good news is that we already have some infrastructure to update package source mappings. That would need to be extended to be more comprehensive. The current logic is meant to integrate with those repos which have NuGet.config files that use package source mappings. So it's necessary to also account for those.
The important part of this logic is that we need to avoid situations where a package source mapping is defined more than once such that nondeterminism would be introduced. Its not inherently bad to have more than package source mapping for a given package ID. But that's only true if you explicitly know that there is no version conflict between those two feeds.
Some rules:
- If a package exists in the currently built package list, add a package source mapping for it that targets its source-built feed.
- If a package exists in the N-1 package list, add a package source mapping for it that targets the previously-source-built feed. Only do this if a package source mapping doesn't already exist for current.
- For those packages that come from SBRP, these are guaranteed to not have conflicting versions between current and N-1 so these can always be added.
- For any of the above cases where a package source mapping is added for a package ID, remove any existing package source mapping with that package ID from the originally defined NuGet.config. In other words, a product repo may have defined a package source mapping for a package. But if we also define that package in SBRP, for example, we want SBRP to be used instead.
Here's an example build (internal only) demonstrating the poison leaks.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status