Prevent SFX restores from overwriting assets for another RID - #68254
Conversation
Detect incompatible target framework and runtime identifier assets before ResolvePackageAssets and report the exact forced restore command. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 782d99e1-0c46-4561-8dd4-1a780f28794d
Keep the validation target aligned with the RepoTasks design-time import guard. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 782d99e1-0c46-4561-8dd4-1a780f28794d
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds an early, more actionable diagnostic for stale SFX restore assets by validating that project.assets.json contains the requested TargetFramework/RuntimeIdentifier target before NuGet asset resolution.
Changes:
- Registers a new RepoTasks MSBuild task to inspect
project.assets.jsonfor a specific runtime target. - Introduces an MSBuild target in
Sfx.Common.targetsthat fails fast with an OS/arch-specific forced-restore command. - Adds the C# implementation of the JSON-aware assets target check.
Show a summary per file
| File | Description |
|---|---|
| eng/tools/RepoTasks/RepoTasks.tasks | Registers the new MSBuild task so it can be used from targets. |
| eng/tools/RepoTasks/CheckProjectAssetsRuntimeTarget.cs | Implements JSON parsing to detect missing TFM/RID targets in assets files. |
| eng/targets/Sfx.Common.targets | Runs the check before ResolvePackageAssets and reports a repo-specific restore command when stale assets are detected. |
Copilot's findings
- Files reviewed: 3/3 changed files
- Comments generated: 2
Do we have use-case where we use different arch in subsequent builds? I don't understand scenario that we are trying to fix. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 782d99e1-0c46-4561-8dd4-1a780f28794d
Include the concrete exception type while preserving the assets file path and existing remediation context. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 782d99e1-0c46-4561-8dd4-1a780f28794d
|
Yes. There are two concrete paths here:
I reproduced the mismatch deterministically with an explicit x64 SFX restore followed by the arm64 no-restore build. Before this change it reaches NETSDK1047. With this change it stops earlier and tells you to run I still don't know the exact command that created the original x64 assets, so I'm not claiming the IDE was definitely the source. This PR also isn't trying to make a cross-architecture no-restore build valid. It makes that stale restore state explain itself and gives the exact recovery command. |
Keep RID-specific NuGet assets side by side so architecture switches can build with --no-restore without replacing another RID's restore state. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 782d99e1-0c46-4561-8dd4-1a780f28794d
Prevent SFX restores from overwriting assets for another RID
Keep each SFX runtime identifier's NuGet restore state in its own directory.
Description
During local Components bring-up on an Apple Silicon Mac, restoring the framework SFX projects for
osx-x64replaced the restore state needed byosx-arm64. A later./eng/build.sh --arch arm64 --no-restorethen failed withNETSDK1047becauseproject.assets.jsonno longer contained the requested arm64 target.This surfaced locally rather than as a CI failure. CI legs restore clean state and do not exercise switching runtime identifiers in the same working tree.
Root cause
The Runtime, Ref, and Runtime Composite SFX projects each used one shared NuGet project-extensions directory for every runtime identifier. Restoring any RID could therefore overwrite the assets for a previously restored RID. The same problem applies to architecture and OS changes, not only
osx-x64andosx-arm64.The exact command that created the originally observed
osx-x64assets is not recoverable. However, a supported producer path is verified: baredotnetand IDE/design-time evaluation leaveTargetArchitectureunset, soeng/Common.propsdefaults to x64. In contrast,eng/build.shdetects and passes the arm64 host architecture.Fix
For
.sfxprojprojects in the Runtime and Ref directories, this change scopesMSBuildProjectExtensionsPathby the fullTargetRuntimeIdentifier. Each RID now keeps its ownproject.assets.json, generated NuGet props and targets, dependency graph, and cache files.The condition deliberately applies only to
.sfxprojfiles. It covers Runtime, Ref, and Runtime Composite while leaving the RID-independent traversal and base projects unchanged. Configuration is intentionally not included because Debug and Release already share restore state per RID by design.This fixes the producer layout instead of adding a diagnostic after the assets have already been overwritten.
Validation
osx-x64andosx-arm64; all six RID-scoped assets files coexisted with the correct targets.NETSDK1047.Full arm64 no-restore builds progressed past restore-assets resolution and reached the existing missing Web.JS build-output prerequisite. The same prerequisite is present without this change, so it is unrelated to RID scoping.
Tradeoffs