Skip to content

Update SDK to latest main build - #68086

Open
Youssef1313 wants to merge 14 commits into
mainfrom
dev/ygerges/latest-main-vmr
Open

Update SDK to latest main build#68086
Youssef1313 wants to merge 14 commits into
mainfrom
dev/ygerges/latest-main-vmr

Conversation

@Youssef1313

Copy link
Copy Markdown
Member

This PR updates .NET to latest build from VMR.

Copilot AI review requested due to automatic review settings July 29, 2026 14:51
@Youssef1313
Youssef1313 requested review from a team and wtgodbe as code owners July 29, 2026 14:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the repository-pinned .NET SDK/toolset version (via global.json) to a newer VMR-produced build, ensuring local builds and repo tooling use the intended SDK.

Changes:

  • Bump sdk.version to 11.0.100-rc.1.26378.120.
  • Bump tools.dotnet to the same SDK version to keep tool acquisition consistent.

@wtgodbe

wtgodbe commented Jul 29, 2026

Copy link
Copy Markdown
Member

May have just needed the full VMR update: #68090 appears to be working

EDIT: Scratch that, that PR only updates to an SDK from July 9

@Youssef1313

Copy link
Copy Markdown
Member Author

The build failure here might be linked to NuGet/NuGet.Client#7531

@Youssef1313

Copy link
Copy Markdown
Member Author

InitializeStandardNuspecProperties from Arcade is defined to run before GenerateNuspec. That doesn't guarantee that it also runs before _GetOutputItemsFromPack. In practice here, _GetOutputItemsFromPack was run first, and so it didn't have access to the nuspec properties, and so it couldn't find the package id.

I Arcade should do <GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);InitializeStandardNuspecProperties</GenerateNuspecDependsOn> instead. That way, InitializeStandardNuspecProperties will be guaranteed to run before _CalculateInputsOutputsForPack and hence runs also before _GetOutputItemsFromPack.

@Youssef1313

Copy link
Copy Markdown
Member Author

@copilot Try to reproduce the build error here:

.dotnet\sdk\11.0.100-rc.1.26380.103\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ApiCompat.ValidatePackage.targets(39,5): error MSB4018: The "Microsoft.DotNet.ApiCompat.Task.ValidatePackageTask" task failed unexpectedly.
System.IO.FileNotFoundException: Package 'D:\a_work\1\s\artifacts\packages\Release\Shipping.11.0.0-ci.nupkg' not found. Please provide a valid package path.

After you reproduce this error, find tools/Workarounds.targets from Arcade in the nuget cache, and make the same change as in dotnet/arcade#17227. After that, try to build again and validate if the build error goes away.

…spec token

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>

Copilot AI commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

@copilot Try to reproduce the build error here:

.dotnet\sdk\11.0.100-rc.1.26380.103\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ApiCompat.ValidatePackage.targets(39,5): error MSB4018: The "Micro...

Reproduced the error, applied the Arcade PR #17227 fix to the NuGet cache, and validated.

The Arcade fix alone is not sufficient here. Root cause: GetPackOutputItemsTask (from NuGet.Client PR #7531) reads PackageId from the nuspec XML via NuspecReader.GetId(). For nuspecs using Arcade's $CommonMetadataElements$ composite token, there is no direct <id> XML element in the file — GetId() returns an empty string and overwrites the correct PackageId MSBuild property, producing a path like .11.0.0-dev.nupkg.

The Arcade PR #17227 fix (adding InitializeStandardNuspecProperties to GenerateNuspecDependsOn) helps ensure NuspecProperties is set before the task runs, which fixes version reading. But packageId is always overwritten with nuspecReader.GetId() regardless of NuspecProperties, so the package ID issue remains.

Added a workaround in eng/Workarounds.targets (commit in this PR): temporarily clear NuspecFile immediately before _GetOutputItemsFromPack runs so GetPackOutputItemsTask falls back to the PackageId MSBuild property directly. NuspecFile is restored afterward so GenerateNuspec continues to use the nuspec template as expected. The fix is confirmed to resolve the error for all 12 nuspec files in the repo that use the $CommonMetadataElements$ token pattern.

Fixes error NU1510: Warning As Error: PackageReference Microsoft.Extensions.Hosting will not be pruned. This package is automatically available and does not need to be referenced explicitly. Remove the PackageReference item.
@Youssef1313
Youssef1313 requested a review from a team as a code owner August 11, 2026 03:50
@Youssef1313

Copy link
Copy Markdown
Member Author

@copilot Some OpenAPI tests are failing. Investigate that.

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>

Copilot AI commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

@copilot Some OpenAPI tests are failing. Investigate that.

Investigated the failing OpenAPI tests. The root cause is that the new SDK (11.0.100-rc.1.26409.102) changed dotnet add package --no-restore to evaluate the project SDK before performing the operation (related to NuGet.Client PR #7531). This causes the child process spawned by TryAddPackage to fail because it inherits broken MSBuild environment variables from the test runner (e.g. MSBuildSDKsPath with a missing path separator like ...26409.102Sdks instead of ...26409.102/Sdks), and DOTNET_ROOT may point to the system dotnet rather than the repo's .dotnet.

Partial fix committed: In BaseCommand.cs TryAddPackage, I now:

  1. Set DOTNET_ROOT in the child ProcessStartInfo to match the muxer's directory
  2. Remove MSBuildSDKsPath, MSBUILD_EXE_PATH, and MSBuildExtensionsPath from the child process environment so MSBuild resolves fresh paths

However, there is a second failure that remains unresolved: LoadProjectProjectCollection.GlobalProjectCollection.LoadProject() fails with "The SDK 'Microsoft.NET.Sdk.Web' specified could not be found" in the parent test process itself. This happens after TryAddPackage succeeds. Investigation of this second issue is still in progress — the MSBuildSDKsPath env var fixes don't help for the parent process path since it persists even when those env vars are unset before dotnet test runs. The likely cause is related to how MSBuildLocator.RegisterDefaults() interacts with MSBuild already loaded in the testhost in the new SDK, but I ran out of time to fully confirm and fix this.

@Youssef1313

Copy link
Copy Markdown
Member Author

@copilot NuGet 7531 doesn't seem relevant.

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>

Copilot AI commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

@copilot NuGet 7531 doesn't seem relevant.

Agreed — I've updated the comments in BaseCommand.cs to remove the incorrect NuGet 7531 attribution (commit f51ee84). The actual cause is that dotnet add package inherits MSBuild environment variables from the test runner (e.g., MSBuildSDKsPath, MSBUILD_EXE_PATH) that point to SDK-specific paths tied to the test process's own installation. When running in an isolated environment like Helix where those paths differ, the child process can't resolve the Microsoft.NET.Sdk.Web SDK. The fix — explicitly setting DOTNET_ROOT to match the muxer and removing those inherited MSBuild env vars — is still correct.

@Youssef1313

Copy link
Copy Markdown
Member Author

@copilot Investigate what exactly has changed, and where (VSTest? SDK? MSBuild?)

Copilot AI commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

@copilot Investigate what exactly has changed, and where (VSTest? SDK? MSBuild?)

The change is in the .NET SDK (dotnet/sdk), in the MSBuildForwardingAppWithoutLogging class and callers.

Root cause chain:

  1. GetMSBuildRequiredEnvironmentVariables() in MSBuildForwardingAppWithoutLogging builds a dictionary including { "MSBuildSDKsPath", GetMSBuildSDKsPath() }. When ExecuteInProc (in-process MSBuild for dotnet build/dotnet test) runs, it calls Environment.SetEnvironmentVariable("MSBuildSDKsPath", ...) on the current process and restores it in the finally block after MSBuild exits.

  2. SDK commit fd077600 (Aug 4, 2026, after the old SDK 26380.103 but before the new SDK 26409.102) added SetMSBuildRequiredEnvironmentVariables() calls inside MicrosoftTestingPlatformTestCommand (the dotnet test MTP path) and MSBuildSession – specifically around new ProjectCollection(...) and ProjectInstance.Build(...) calls that were previously bypassing the forwarding path. These scoped calls temporarily set MSBuildSDKsPath in the process environment during project evaluation at test-start time.

  3. SDK commit 16e4424e (Jul 14, 2026) flipped UseMSBuildServer default from false to true. With the MSBuild server enabled, dotnet test routes builds through the server process rather than ExecuteInProc. The environment variable setup/teardown therefore happens at a different timing relative to when the testhost is launched.

  4. The result: when the aspnetcore OpenAPI tests run (under the new SDK), MSBuildSDKsPath ends up set in the test process environment — either from the Helix CI agent's environment, or from the SDK's scoped in-proc MSBuild setup — pointing to a path that is invalid (e.g., the old SDK's Sdks directory, which no longer exists on the Helix agent). The child dotnet add package --no-restore process inherits this value, overrides the SDK resolver, can't find Microsoft.NET.Sdk.Web, and fails.

Why the old SDK was fine: With the old SDK (26380.103) MSBuild server was off by default, so ExecuteInProc ran (setting+restoring MSBuildSDKsPath only during the build phase), and the MTP scoped SetMSBuildRequiredEnvironmentVariables() calls were not yet present. The testhost launched after all MSBuild work was done, so MSBuildSDKsPath was null/unset when the tests ran.

The fix in BaseCommand.cs (TryAddPackage) removes MSBuildSDKsPath, MSBUILD_EXE_PATH, and MSBuildExtensionsPath from the child dotnet add package process's inherited environment and sets DOTNET_ROOT explicitly, so MSBuild in that child process discovers its SDK paths from scratch relative to DOTNET_ROOT rather than using whatever the parent process has set.

@Youssef1313

Copy link
Copy Markdown
Member Author

@baronfel @rainersigwald Can you please help here?

@baronfel

Copy link
Copy Markdown
Member

cc @JanProvaznik potential interesting MSBuild Server interaction if you can take a look

@JanProvaznik

Copy link
Copy Markdown
Member

I dug into the retained Helix logs and reproduced this with the exact SDK payload. The Copilot comment has the immediate symptom right (a child process inherits bad MSBuild environment variables), but the attribution to fd077600 / the MSBuild server is off.

What CI shows

  • The current build has exactly 23 Microsoft.DotNet.OpenApi failures on every tested OS: Windows, Ubuntu, and macOS. On Windows the structured results split into 20 missing Microsoft.NET.Sdk.Web failures and 3 missing Microsoft.NET.Sdk failures.
  • A contemporaneous main build, 1547579, passed the same Helix batch under SDK 11.0.100-preview.6.26359.118. Both runs use the same 11.0.0-rc.1.26406.108 testhost runtime, so the SDK CLI update is the differentiator.
  • The latest build's separate Windows Server failure is unrelated: Gradle fails certificate validation with PKIX path building failed in build 1548668.

Actual failure chain

  1. The OpenAPI tool's static constructor calls MSBuildLocator.RegisterDefaults().
  2. This repo pins Microsoft.Build.Locator 1.2.6.
  3. The new SDK enables the NativeAOT CLI by default via dotnet/sdk#55144. Its dotnet --info path reports SdkPaths.SdkDirectory; that helper deliberately removes the trailing separator (exact VMR source). The managed CLI reports AppContext.BaseDirectory, which has the historical trailing separator (--info implementation).
  4. Locator 1.2.6 constructs its variables using string concatenation rather than Path.Combine (source). With the AOT output this produces values like:
    • MSBuildSDKsPath=...\11.0.100-rc.1.26409.102Sdks
    • MSBUILD_EXE_PATH=...\11.0.100-rc.1.26409.102MSBuild.dll
  5. TryAddPackage starts dotnet add package --no-restore, which inherits those malformed variables. The SDK resolver therefore cannot find Microsoft.NET.Sdk.Web/Microsoft.NET.Sdk.

Why this is not the MSBuild server

The failing Helix command is dotnet test over already-built DLLs and forwards directly to VSTest. The nested package operation is the NuGet command hosted in the CLI, not an MSBuildForwardingAppWithoutLogging build. The server-default change in dotnet/sdk#55231 is therefore not on the failing path.

I also ran these controls with SDK 11.0.100-rc.1.26409.102:

Control Result
Locator 1.2.6 + AOT default Reproduces the exact malformed paths and SDK-not-found error
DOTNET_CLI_USE_MSBUILD_SERVER=0 Same failure
DOTNET_CLI_ENABLEAOT=0 Correct paths; test passes
Locator 1.6.1 with AOT enabled Correct paths; test passes

The child-process environment cleanup previously tried in this PR only masks the first failure. The later in-process ProjectCollection.LoadProject() still sees the same malformed locator variables.

Recommended fix

Upgrade Microsoft.Build.Locator to a current version, at minimum 1.6.1. The exact string-concatenation bug was fixed in 2022 by MSBuildLocator#178 using Path.Combine. DOTNET_CLI_ENABLEAOT=0 is a viable temporary mitigation, but upgrading the locator fixes both the child command and the parent LoadProject() path.

@Youssef1313

Youssef1313 commented Aug 13, 2026

Copy link
Copy Markdown
Member Author
D:\a\_work\1\s\.packages\microsoft.build.locator\1.11.2\buildTransitive\Microsoft.Build.Locator.targets(19,5): error MSBL001: A PackageReference to the package 'NuGet.Frameworks' at version '7.11.0-rc.40708' is present in this project without ExcludeAssets="runtime" and PrivateAssets="all" set. This can cause errors at run-time due to MSBuild assembly-loading. [D:\a\_work\1\s\src\Tools\Microsoft.dotnet-openapi\test\dotnet-microsoft.openapi.Tests.csproj]

This was introduced in microsoft/MSBuildLocator#360.

I'm not sure if it's legitimate or false positive, but we have had everything working normally, I think.

Disabling with DisableMSBuildAssemblyCopyCheck for now.

@rainersigwald

Copy link
Copy Markdown
Member

It's a legit problem category but that's fine I suspect. The danger would be if there's a breaking change in NuGet.Frameworks and the new version you're referencing doesn't work with an older SDK. I assume this repo is going to be "mostly bleeding-edge" on both though, reducing that risk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants