Restore with command: custom so nuget.config is not rewritten - #792
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes NuGet restore failures in Azure Pipelines when using DotNetCoreCLI@2/NuGetCommand tasks with feedsToUse: config and PackageSourceMapping enabled. Those tasks rewrite the config and prefix feed keys with feed-, which breaks key-based package source mapping unless the prefixed key is also mapped.
Changes:
- Add a
feed-upstream-publicentry under<packageSourceMapping>to match the Azure Pipelines task–rewritten source key. - Document the Azure Pipelines task behavior and link the upstream tracking issue for context.
YunchuWang
force-pushed
the
yunchuwang/fix-cfs-package-source-mapping
branch
from
August 3, 2026 18:34
d571c49 to
5588164
Compare
DotNetCoreCLI@2's restore command copies nuget.config into a generated temp config and prefixes every package source key with "feed-". The packageSourceMapping entries the Central Feed Service requires are not rewritten and match on the source key, so after the rewrite the mapping covers no declared source. NuGet excludes the only feed for every package, including the Microsoft.Build.Traversal MSBuild SDK, so evaluating src/dirs.proj fails before any package is fetched: error : Unable to resolve 'Microsoft.Build.Traversal (= 4.1.82)'. PackageSourceMapping is enabled, the following source(s) were not considered: feed-upstream-public. error MSB4236: The SDK 'Microsoft.Build.Traversal' could not be found. Every official build has failed this way since the Central Feed Service change. No nuget.config can work around this. The rewrite prepends "feed-" unconditionally, so a source key never equals its own mapping key under the task, while outside the task they must be equal. Renaming the source, adding the prefixed key to the mapping, or declaring both were each tried and each fails. feedsToUse and nugetConfigPath only apply to the restore and push commands. Using command: custom skips the rewriting entirely and passes nuget.config straight to the CLI, matching how the Pack step already invokes the task. See microsoft/azure-pipelines-tasks#15542 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3697a867-8972-4cde-81fd-b3dd94c55066
YunchuWang
force-pushed
the
yunchuwang/fix-cfs-package-source-mapping
branch
from
August 3, 2026 18:54
5588164 to
840dde7
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
eng/templates/build.yml:54
- The explanatory comment says the DotNetCoreCLI task rewrites package source keys but that the
packageSourceMappingentries are “not rewritten”. That contradicts the PR description (and the linked failure mode) where the task also rewrites mapping keys, causing collisions/duplicate-key errors. Please adjust the comment to reflect the actual behavior so future maintainers don’t apply the wrong workaround.
# Restore uses command: custom rather than command: restore. The restore command's
# feedsToUse/nugetConfigPath inputs make the task copy nuget.config into a generated temp
# config and prefix every package source key with "feed-". Package source mapping matches on
# the source key and those entries are not rewritten, so the mapping the Central Feed Service
# requires stops applying and NuGet excludes the only feed. See
kaibocai
approved these changes
Aug 3, 2026
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.
Summary
What changed?
eng/templates/build.yml: the Restore step now usescommand: custom/custom: restoreinstead ofcommand: restorewithfeedsToUse: config.NuGetAuthenticate@1andnuget.configare unchanged.Why is this change needed?
Every official build (
durabletask-dotnet.official, definition 657) has failed at Restore since #789 routed restores through the Central Feed Service.mainis red and no signed packages can be produced, which blocks publishing v1.25.0.Root cause.
DotNetCoreCLI@2'srestorecommand does not passnuget.configto the CLI. It copies the file into a generated temp config (D:\a\_work\1\Nuget\tempNuGet_<buildId>.config) and prefixes every<packageSources>key withfeed-. The<packageSourceMapping>entries are not rewritten, and mapping matches on the source key — so after the rewrite the mapping covers no declared source. NuGet then excludes the only feed for every package, including theMicrosoft.Build.TraversalMSBuild SDK thatsrc/dirs.projneeds, so evaluation dies before a single package is fetched:Why this isn't fixed in
nuget.config. It can't be. The rewrite prependsfeed-unconditionally and non-idempotently. LetSbe the source key andMthe mapping key in the singlenuget.configevery environment shares. NuGet matches only when the two are equal, so:S == Mfeed-S == MBoth must hold for the same file, which requires
S == feed-S. There is no such string, so no naming scheme satisfies both environments. Confirmed empirically across the entire permutation space for one feed:<packageSources>key<packageSourceMapping>keyupstream-publicupstream-publicfeed-upstream-publicupstream-publicfeed-feed-upstream-publicfeed-upstream-publicfeed-upstream-publicfeed-feed-upstream-publicThe double
feed-feed-prefix in the last two is direct evidence the rewrite is unconditional.Why
command: customfixes it.feedsToUseandnugetConfigPathare inputs that only exist for therestoreandpushcommands. Withcommand: customthe task shells out todotnet restore <arguments>and never enters the config-rewriting path, sonuget.configis used verbatim and the source keys match the mapping by construction. This is also how the Pack step in this same file already invokes the task.Tracked upstream by azure-pipelines-tasks#15542.
Issues / work items
Project checklist
AI-assisted code disclosure (required)
Was an AI tool used? (select one)
If AI was used:
eng/templates/build.ymlAI verification (required if AI was used):
Testing
Automated tests
Manual validation (only if runtime/behavior changed)
Validated on the real pipeline (definition 657), one variable per run, all from base
c3d5d87a.mainas-is)nuget.configmapping workaroundnuget.configboth source keysfeed-feed-double prefixnuget.configprefixed source keyfeed-feed-double prefixpwsh: dotnet restorecommand: custom)Build 295504 completed every stage — Restore → Build → Sign assemblies → Pack → Sign NugetPackages → Component Governance → SBOM → artifact publish — and produced all 17 signed packages at the expected versions:
The YAML in this PR was verified to parse to a structure identical to the one build 295504 ran; the only textual difference is an added explanatory comment.
Notes for reviewers
nuget.configis deliberately untouched. The mapping there was already correct — the task was corrupting it.feedsToUse: config. Build and Pack pass--no-restoreand never resolve packages, so they are unaffected.NuGetAuthenticate@1is retained and still succeeds; it exports the credential provider environment for the following step.dotnet restore --configfile nuget.config.azure-pipelines-release.ymlhas the same pattern but is not referenced by any enabled definition (657 →eng/ci/official-build.yml, 1100 →eng/publish/publish.yml, 520 →eng/ci/code-mirror.yml), so it is left alone.pwsh: dotnet restorestep also works (build 295451).command: customwas chosen because it keeps the task wrapper and matches the adjacent Pack step.