You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue was drafted with AI/Copilot assistance.
Summary
After #16814 ("Remove the Arcade msbuild logger"), the MSBuild function in eng/common/tools.sh and eng/common/tools.ps1 no longer routes through InitializeToolset. As a side effect, GetNuGetPackageCachePath is no longer invoked, which means NUGET_PACKAGES is never exported when a repo enters Arcade via eng/common/msbuild.{sh,ps1} instead of eng/common/build.{sh,ps1}.
In CI, RepoLayout.props sets the MSBuild NuGetPackageRoot to $(RepoRoot)/.packages/ based on ContinuousIntegrationBuild=true, but NuGet's RestoreTaskEx no longer sees NUGET_PACKAGES and falls back to ~/.nuget/packages/. Restore and build now resolve different package roots; any generated obj/<proj>.nuget.g.props<Import> predicated on Exists('$(NuGetPackageRoot)…') is silently skipped.
Concrete failure
dotnet/runtime CI test build fails with:
src/tests/Common/external/external.csproj(81,5): error : looks the package Microsoft.DotNet.XUnitConsoleRunner is not restored or missing xunit.console.dll.
PkgMicrosoft_DotNet_XUnitConsoleRunner (baked in at restore time) correctly points at ~/.nuget/packages/microsoft.dotnet.xunitconsolerunner/…, but the package's own build/Microsoft.DotNet.XUnitConsoleRunner.props is never imported because the Import path is evaluated against the wrong root. XunitConsoleNetCoreAppPath is never defined → <Error> fires.
Diagnosis from binlog
Property (external.csproj evaluation)
Value
NuGetPackageRoot (build-time, via RepoLayout.props)
In the pre-#16814 code, the MSBuild function in tools.sh called:
if [[ "$pipelines_log"==true ]];then
InitializeBuildTool
InitializeToolset # ← calls GetNuGetPackageCachePath → exports NUGET_PACKAGES
...
fi
pipelines_log defaulted to true when ci=true, so any caller invoking eng/common/msbuild.sh in CI got NUGET_PACKAGES exported as a side effect. #16814 deleted the entire pipelines_log branch (along with the now-defunct logger plumbing), removing the InitializeToolset call. The PR description states "The surrounding pipelines_log block (NUGET timeout env vars, Enable-Nuget-EnhancedRetry, InitializeToolset) is retained", but the diff shows InitializeToolset was dropped along with the logger.
Affected entry points
eng/common/msbuild.sh / eng/common/msbuild.ps1 (never called InitializeToolset themselves, depended on MSBuild to do it)
Any repo whose secondary build scripts enter via msbuild.{sh,ps1} rather than build.{sh,ps1}. dotnet/runtime's src/tests/build.sh is one example.
Repos that go through eng/common/build.{sh,ps1} are unaffected because those scripts call InitializeToolset directly.
Suggested fix
Lightweight: ensure NUGET_PACKAGES is exported whenever ci=true in tools.{sh,ps1}. Cleanest spot is the CI block at the bottom of tools.sh/tools.ps1 (next to the MSBUILDDEBUGPATH setup), so every entry point inherits it:
GetNuGetPackageCachePath is idempotent (no-op when NUGET_PACKAGES already set), so this is safe for callers that already invoke InitializeToolset later.
Alternative: restore the InitializeToolset call inside the MSBuild function (smaller diff, but heavier than necessary).
Workaround (already applied in dotnet/runtime)
Export NUGET_PACKAGES="$RepoRoot/.packages/" in src/tests/build.{sh,cmd} before invoking eng/common/msbuild.{sh,ps1}.
Note
This issue was drafted with AI/Copilot assistance.
Summary
After #16814 ("Remove the Arcade msbuild logger"), the
MSBuildfunction ineng/common/tools.shandeng/common/tools.ps1no longer routes throughInitializeToolset. As a side effect,GetNuGetPackageCachePathis no longer invoked, which meansNUGET_PACKAGESis never exported when a repo enters Arcade viaeng/common/msbuild.{sh,ps1}instead ofeng/common/build.{sh,ps1}.In CI,
RepoLayout.propssets the MSBuildNuGetPackageRootto$(RepoRoot)/.packages/based onContinuousIntegrationBuild=true, but NuGet'sRestoreTaskExno longer seesNUGET_PACKAGESand falls back to~/.nuget/packages/. Restore and build now resolve different package roots; any generatedobj/<proj>.nuget.g.props<Import>predicated onExists('$(NuGetPackageRoot)…')is silently skipped.Concrete failure
dotnet/runtime CI test build fails with:
PkgMicrosoft_DotNet_XUnitConsoleRunner(baked in at restore time) correctly points at~/.nuget/packages/microsoft.dotnet.xunitconsolerunner/…, but the package's ownbuild/Microsoft.DotNet.XUnitConsoleRunner.propsis never imported because the Import path is evaluated against the wrong root.XunitConsoleNetCoreAppPathis never defined →<Error>fires.Diagnosis from binlog
NuGetPackageRoot(build-time, via RepoLayout.props)/Users/runner/work/1/s/.packages/NuGetPackageFolders(from project.assets.json)/Users/runner/.nuget/packages/PkgMicrosoft_DotNet_XUnitConsoleRunner/Users/runner/.nuget/packages/microsoft.dotnet.xunitconsolerunner/2.9.3-beta.26277.104XunitConsoleNetCoreAppPathRoot cause
In the pre-#16814 code, the
MSBuildfunction intools.shcalled:pipelines_logdefaulted totruewhenci=true, so any caller invokingeng/common/msbuild.shin CI gotNUGET_PACKAGESexported as a side effect. #16814 deleted the entirepipelines_logbranch (along with the now-defunct logger plumbing), removing theInitializeToolsetcall. The PR description states "The surroundingpipelines_logblock (NUGET timeout env vars, Enable-Nuget-EnhancedRetry, InitializeToolset) is retained", but the diff showsInitializeToolsetwas dropped along with the logger.Affected entry points
eng/common/msbuild.sh/eng/common/msbuild.ps1(never calledInitializeToolsetthemselves, depended onMSBuildto do it)msbuild.{sh,ps1}rather thanbuild.{sh,ps1}. dotnet/runtime'ssrc/tests/build.shis one example.Repos that go through
eng/common/build.{sh,ps1}are unaffected because those scripts callInitializeToolsetdirectly.Suggested fix
Lightweight: ensure
NUGET_PACKAGESis exported wheneverci=trueintools.{sh,ps1}. Cleanest spot is the CI block at the bottom oftools.sh/tools.ps1(next to theMSBUILDDEBUGPATHsetup), so every entry point inherits it:GetNuGetPackageCachePathis idempotent (no-op whenNUGET_PACKAGESalready set), so this is safe for callers that already invokeInitializeToolsetlater.Alternative: restore the
InitializeToolsetcall inside theMSBuildfunction (smaller diff, but heavier than necessary).Workaround (already applied in dotnet/runtime)
Export
NUGET_PACKAGES="$RepoRoot/.packages/"insrc/tests/build.{sh,cmd}before invokingeng/common/msbuild.{sh,ps1}.