Problem
eng/common/core-templates/steps/enable-internal-sources.yml invokes SetupNugetSources.ps1 through the PowerShell@2 task on all platforms, including Linux and macOS agents (where PowerShell@2 runs the script under pwsh):
https://github.com/dotnet/arcade/blob/main/eng/common/core-templates/steps/enable-internal-sources.yml
- task: PowerShell@2
displayName: Setup Internal Feeds
inputs:
filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config
While PowerShell itself is cross-platform, SetupNugetSources.ps1 dot-sources eng/common/tools.ps1:
. $PSScriptRoot\tools.ps1
tools.ps1 carries a number of Windows-only expectations and code paths (VS / MSBuild discovery, vswhere.exe, .exe tool resolution, windowsdesktop runtime paths, etc.). Dot-sourcing it on Unix pulls in a large surface area of Windows-centric logic that is not intended to run cross-platform, making the behavior fragile and surprising on Linux/macOS agents.
Note that a fully equivalent shell implementation already exists: eng/common/SetupNugetSources.sh.
Options to solve
Option 1 — Invoke SetupNugetSources.sh on Unix (preferred / lowest risk)
Branch in enable-internal-sources.yml on Agent.OS and call the matching script:
PowerShell@2 → SetupNugetSources.ps1 on Windows
Bash@3 → SetupNugetSources.sh on Linux/macOS
The .sh script already accepts the same inputs (ConfigFile as $1, credential token as $2), so this is a contained YAML change and avoids running tools.ps1 on Unix entirely. This is the recommended fix.
Option 2 — Make SetupNugetSources.ps1 not depend on tools.ps1
The .ps1 only needs a small set of helpers from tools.ps1. Inlining (or extracting into a small, cross-platform-safe shared file) just the functions it actually uses would let it run cleanly under pwsh on any platform without dragging in Windows-only logic. This keeps a single script but requires identifying and isolating the real dependencies.
Option 3 — Rewrite tools.ps1 to be fully cross-platform
The user notes this is likely feasible now. tools.ps1 already has IsWindowsPlatform() guards in several places; a broader pass could make the whole file safe to dot-source on Unix. This is the largest-scope option and affects every consumer of tools.ps1, so it carries the most risk and validation cost, but would remove the underlying foot-gun entirely.
Recommendation
Start with Option 1 (invoke SetupNugetSources.sh on Unix in the template) as the immediate, low-risk fix. Options 2 and 3 can be considered as longer-term cleanups.
Notes
- Files under
eng/common are mirrored from Arcade, so the fix must be made here in dotnet/arcade to persist.
- There are existing tests under
src/Microsoft.DotNet.SetupNugetSources.Tests that exercise both the .ps1 and .sh scripts and can help validate any change.
Problem
eng/common/core-templates/steps/enable-internal-sources.ymlinvokesSetupNugetSources.ps1through thePowerShell@2task on all platforms, including Linux and macOS agents (wherePowerShell@2runs the script underpwsh):https://github.com/dotnet/arcade/blob/main/eng/common/core-templates/steps/enable-internal-sources.yml
While PowerShell itself is cross-platform,
SetupNugetSources.ps1dot-sourceseng/common/tools.ps1:tools.ps1carries a number of Windows-only expectations and code paths (VS / MSBuild discovery,vswhere.exe,.exetool resolution,windowsdesktopruntime paths, etc.). Dot-sourcing it on Unix pulls in a large surface area of Windows-centric logic that is not intended to run cross-platform, making the behavior fragile and surprising on Linux/macOS agents.Note that a fully equivalent shell implementation already exists:
eng/common/SetupNugetSources.sh.Options to solve
Option 1 — Invoke
SetupNugetSources.shon Unix (preferred / lowest risk)Branch in
enable-internal-sources.ymlonAgent.OSand call the matching script:PowerShell@2→SetupNugetSources.ps1on WindowsBash@3→SetupNugetSources.shon Linux/macOSThe
.shscript already accepts the same inputs (ConfigFileas$1, credential token as$2), so this is a contained YAML change and avoids runningtools.ps1on Unix entirely. This is the recommended fix.Option 2 — Make
SetupNugetSources.ps1not depend ontools.ps1The
.ps1only needs a small set of helpers fromtools.ps1. Inlining (or extracting into a small, cross-platform-safe shared file) just the functions it actually uses would let it run cleanly underpwshon any platform without dragging in Windows-only logic. This keeps a single script but requires identifying and isolating the real dependencies.Option 3 — Rewrite
tools.ps1to be fully cross-platformThe user notes this is likely feasible now.
tools.ps1already hasIsWindowsPlatform()guards in several places; a broader pass could make the whole file safe to dot-source on Unix. This is the largest-scope option and affects every consumer oftools.ps1, so it carries the most risk and validation cost, but would remove the underlying foot-gun entirely.Recommendation
Start with Option 1 (invoke
SetupNugetSources.shon Unix in the template) as the immediate, low-risk fix. Options 2 and 3 can be considered as longer-term cleanups.Notes
eng/commonare mirrored from Arcade, so the fix must be made here indotnet/arcadeto persist.src/Microsoft.DotNet.SetupNugetSources.Teststhat exercise both the.ps1and.shscripts and can help validate any change.