Fix NuGet restore on managed devices that cannot reach nuget.org directly - #623
Draft
Nikola Metulev (nmetulev) wants to merge 4 commits into
Draft
Fix NuGet restore on managed devices that cannot reach nuget.org directly#623Nikola Metulev (nmetulev) wants to merge 4 commits into
Nikola Metulev (nmetulev) wants to merge 4 commits into
Conversation
The EnsureNuGetConfig target auto-copied nuget.config.template to a local nuget.config on every build. On managed devices where direct access to nuget.org is blocked, this local nuget.config (with <clear/> and a direct nuget.org source) overrode the machine/user-level NuGet.Config that already redirects to the org's internal proxy feed, breaking restore. Removing the auto-generated local nuget.config lets NuGet fall back to the normal config hierarchy instead: managed devices inherit the org's proxy feed from user-level config, and unmanaged devices fall back to NuGet's built-in nuget.org default. Both resolve fine, including the Microsoft.ML.OnnxRuntime.Foundry transitive dependency (nuget.org publishes it as 1.23.2.3 rather than the exact 1.23.2 requested, which NuGet accepts as a compatible minimum-version match with a NU1603 warning). nuget.config.template is left in place since CI workflows (.github/workflows/*.yml) still generate an ephemeral config from it explicitly via --configfile. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR removes an MSBuild target that auto-generated a repo-local nuget.config during build/restore, which could override machine/user NuGet configuration and break restore on managed devices that require an internal proxy feed.
Changes:
- Deleted the
EnsureNuGetConfigMSBuild target fromDirectory.Build.targetsso builds no longer create a localnuget.config. - Leaves
nuget.config.templateto continue supporting CI scenarios that explicitly pass--configfile.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The previous EnsureNuGetConfig target blindly copied nuget.config.template (direct nuget.org + ORT) to a local nuget.config. On managed devices where direct access to nuget.org is blocked by network policy, this broke restore with NU1301 TLS handshake errors, since the local config's <clear/> shadowed the machine/user-level NuGet.Config that already redirects through the org's internal proxy feed. A prior commit on this branch just deleted the target outright, relying on NuGet's config-hierarchy fallback instead. That works for plain 'dotnet restore' but breaks CI's pr-unit-test job: without the ORT feed's exact Microsoft.ML.OnnxRuntime.Foundry match, NuGet falls back to nuget.org's 1.23.2.3 build and emits NU1603, which this repo's TreatWarningsAsErrors=true setting (Directory.Build.props) turns into a hard build failure. Fix: keep the ORT feed mapping (needed on every network), but make the '*' source network-aware. .github/scripts/resolve-nuget-config.ps1 probes api.nuget.org and picks nuget.config.template (direct nuget.org) if reachable, or the new nuget.config.managed.template (org proxy feed) if not. Both keep the same ORT mapping for *Foundry* packages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Nikola Metulev (nmetulev)
marked this pull request as draft
August 14, 2026 04:35
…feed Microsoft.AI.Foundry.Local.Core.WinML 0.8.2.2 (pulled in transitively by Microsoft.AI.Foundry.Local.WinML 0.8.2.1) declares a dependency on Microsoft.ML.OnnxRuntime.Foundry 1.23.2 -- a version that was only ever published to the internal ORT feed, never to nuget.org, which publishes 1.23.2.3 instead. Because the dependency is an unbracketed (minimum-version) constraint, restore silently resolves 1.23.2.3 and emits NU1603. Directory.Build.props sets TreatWarningsAsErrors for Release, so that warning fails the build. The ORT feed existed solely to paper over this single bad nuspec. Pinning Microsoft.ML.OnnxRuntime.Foundry to 1.23.2.3 with an explicit PackageReference makes resolution exact, so NU1603 never fires and every package now comes from nuget.org. That lets us drop the whole workaround: - Remove the ORT feed from nuget.config.template. - Remove the EnsureNuGetConfig target from Directory.Build.targets, along with nuget.config.managed.template and resolve-nuget-config.ps1. With no repo-level nuget.config, a fresh clone now inherits whatever NuGet config the machine already has. That fixes local restore on managed devices that cannot reach api.nuget.org directly and are transparently redirected to an internal mirror, while remaining unchanged for everyone else. The pin can be removed once Microsoft.AI.Foundry.Local.WinML is upgraded to 1.0.0 or later, which reference versions that exist on nuget.org. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Removing the ORT feed and pinning Microsoft.ML.OnnxRuntime.Foundry to the
nuget.org build (1.23.2.3) restored cleanly but broke MSIX packaging on both
architectures. The two feeds do not publish equivalent packages:
ORT feed 1.23.2 -> Microsoft.ML.OnnxRuntime.Managed
nuget.org 1.23.2.3 -> Microsoft.ML.OnnxRuntime.Managed
+ Microsoft.ML.OnnxRuntime.Gpu.Linux
That extra dependency, plus the native onnxruntime.dll the nuget.org build
ships itself, produce two failures that restore alone never surfaces:
MSB3030 copying runtimes/win-arm64/native/onnxruntime.dll out of the
Linux-only Gpu.Linux package
APPX1101 duplicate payload path onnxruntime.dll, colliding with the copy
from Microsoft.Windows.AI.MachineLearning
Newer versions on nuget.org (through at least 1.26.0) still carry the
Gpu.Linux dependency, so this is not fixed by upgrading alone.
This restores the network-aware nuget.config generation and records the full
reasoning in nuget.config.template so the feed is not dropped again.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Restore fails on machines that cannot reach
api.nuget.orgdirectly. Many managed/corporate devices block direct TLS to nuget.org and transparently redirect NuGet to an internal mirror via a machine-levelNuGet.Config.This repo defeated that redirect.
Directory.Build.targetsauto-generated a repo-rootnuget.configby copyingnuget.config.template, which begins with<clear />and hardcodesapi.nuget.org. The machine-level configuration was discarded and restore failed withNU1301/ TLS handshake errors, so a fresh clone could not be built at all on such a device.Fix
Make the auto-generation network-aware instead of unconditional:
.github/scripts/resolve-nuget-config.ps1probeshttps://api.nuget.org/v3/index.json(5s timeout) and copies eithernuget.config.template(reachable) or the newnuget.config.managed.template(unreachable, uses the organization proxy for the*mapping).Directory.Build.targetsinvokes that script rather than blindly copying the public template.ORTfeed mapping, so package resolution is byte-for-byte the same either way.nuget.configalready exists, so manual overrides are respected.CI is unaffected: those jobs build their own ephemeral config from
nuget.config.templateand pass--configfile.Why a single static config cannot work
Mapping
*to bothnuget.organd the proxy does not fall back gracefully. NuGet only falls back for "package not found"; a hard TLS/connectivity failure on any mapped source aborts the entire restore withNU1301. The choice has to be made per-machine, which is why this probes.Why the ORT feed is still required
This PR originally went further and tried to delete the
ORTfeed entirely, on the theory that it only existed to silence aNU1603warning. That turned out to be wrong, and the investigation is worth recording — the reasoning is now captured in a comment innuget.config.template.Microsoft.AI.Foundry.Local.Core.WinMLrequiresMicrosoft.ML.OnnxRuntime.Foundry1.23.2, published only to the ORT feed. nuget.org publishes 1.23.2.3, which NuGet accepts as a compatible minimum-version match. But the two builds are not equivalent packages:1.23.21.23.2.3Microsoft.ML.OnnxRuntime.ManagedMicrosoft.ML.OnnxRuntime.Gpu.LinuxRestoring against nuget.org therefore breaks the build in three ways:
NU1603(requested version not found) — fatal, sinceDirectory.Build.propssetsTreatWarningsAsErrorsforRelease.MSB3030— MSIX packaging tries to copyruntimes/win-arm64/native/onnxruntime.dllout of the Linux-onlyGpu.Linuxpackage.APPX1101— duplicate payload pathonnxruntime.dll, colliding with the copy fromMicrosoft.Windows.AI.MachineLearning.Pinning
1.23.2.3explicitly fixes only (1); (2) and (3) still fail, which is exactly what CI caught. Versions on nuget.org through at least1.26.0still carry theGpu.Linuxdependency, so this is not fixed by upgrading either.Verification
dotnet restore+dotnet buildof the solution succeed on a managed device that cannot reach nuget.org directly.Follow-ups (not in this PR)
Microsoft.AI.Foundry.Local.WinMLis pinned to0.8.2.1;1.2.4is available. A spike showed the upgrade is small on the C# side — 8 compile errors across 3 files, fromFoundryLocalManager.EnsureEpsDownloadedAsync()→DownloadAndRegisterEpsAsync()and the removal ofIModel.SelectedVariant— but it also requires aligningMicrosoft.ML.OnnxRuntimeGenAI.*to0.14.1and reworkingAIDevGallery/ExcludeExtraLibs.propsfor theGpu.Linuxnative assets.pr-unit-testjob inbuild.ymlis the only job that does not create an ephemeral NuGet config, so it silently depends on repo-root auto-generation. Making it consistent with the other jobs would remove that coupling.