Fix: InitializeStandardNuspecProperties must run before _CalculateInputsOutputsForPack - #17227
Conversation
|
@copilot I think |
…rgets for _CalculateInputsOutputsForPack
Done in the latest commit. Replaced |
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)
src/Microsoft.DotNet.Arcade.Sdk/tools/Workarounds.targets:60
InitializeStandardNuspecPropertiesis no longer scheduled to run before_CalculateInputsOutputsForPack. Adding it toGenerateNuspecDependsOnonly orders it relative toGenerateNuspec, but_CalculateInputsOutputsForPackcan run earlier (and is the target that now consumesNuspecPropertiesas an incremental input). Re-addBeforeTargets(as described in the PR) soNuspecPropertiesis populated before both targets execute.
<Target Name="InitializeStandardNuspecProperties"
DependsOnTargets="_InitializeNuspecRepositoryInformationPropertiesWorkaround"
Condition="'$(IsPackable)' == 'true'">
|
dotnet/aspnetcore#68086 (comment) seems like this PR would only fix part of the problem. But I assume the remaining part of the fix will be on NuGet side so that the ID is read from the NuspecProperties. |
Evangelink
left a comment
There was a problem hiding this comment.
I verified this empirically rather than by inspection, and the fix is correct. Notes below — none of them blocking.
Verification
The diagnosis is right. MSBuild runs DependsOnTargets before BeforeTargets. Minimal repro:
== Dep1 → == Dep2 → == Before1 (BeforeTargets) → == Main
So BeforeTargets="GenerateNuspec" scheduled the target after the entire GenerateNuspec dependency chain, including _CalculateInputsOutputsForPack → _GetOutputItemsFromPack.
The fix works. I simulated the real pack target graph (GenerateNuspecDependsOn as built at lines 32/55/59 of NuGet.Build.Tasks.Pack.targets, plus GenerateNuspec DependsOnTargets="$(GenerateNuspecDependsOn);_CalculateInputsOutputsForPack;…"):
what _GetOutputItemsFromPack sees |
|
|---|---|
before (BeforeTargets="GenerateNuspec") |
NuspecProperties='' ❌ |
after (GenerateNuspecDependsOn) |
NuspecProperties='PackageId=Foo;Version=1.2.3' ✅ |
Import-order robust. NuGet appends $(GenerateNuspecDependsOn) at the tail of its own list and prepends Build;, so this lands last in the list but still strictly before _CalculateInputsOutputsForPack — regardless of whether Workarounds.targets is imported before or after the pack targets.
Moving the target earlier is safe within Arcade. Everything it reads (PackageDescription, PackageLicenseFullPath, PackageIconFullPath, PackageVersion, …) is set at evaluation time in ProjectDefaults.props/.targets; the only target-produced values (RepositoryUrl/RepositoryCommit) come from its own DependsOnTargets. It also matches Pack.targets:5, which already uses this pattern — final chain ends …;InitializeStandardNuspecProperties;_ValidationSymbolPackageFormat, both still ahead of _CalculateInputsOutputsForPack.
Two things not covered by the inline comments
Necessary but not sufficient — worth saying so in the PR body. Per the aspnetcore investigation, GetPackOutputItemsTask unconditionally overwrites packageId with nuspecReader.GetId() whenever NuspecFile != ''. Arcade's $CommonMetadataElements$ composite token means the .nuspec has no literal <id> element, so GetId() returns empty and you get an output path like .11.0.0-dev.nupkg. This PR fixes only the version half. Please state that here and link a NuGet.Client issue so nobody assumes this unblocks aspnetcore on its own.
No regression coverage. There is no project in this repo using NuspecFile or NuspecPackageId, so green CI proves nothing about this code path and it can silently regress again. A scenario test that packs with a NuspecFile + $CommonMetadataElements$ and asserts the emitted nupkg name would be worth it — the "right tests are in" checkbox is still unchecked.
| To ensure we have set the NuspecProperties early enough, we need to include InitializeStandardNuspecProperties in GenerateNuspecDependsOn. | ||
| The GenerateNuspecDependsOn targets are guaranteed to run before _CalculateInputsOutputsForPack. | ||
| This was preferred over BeforeTargets="_CalculateInputsOutputsForPack;GenerateNuspec" to avoid depending on a private target name. | ||
| --> |
There was a problem hiding this comment.
Nit: 3-space indent here, the file uses 2 everywhere else.
Also worth splitting the comment block: the original "Workarounds for insufficient support for tools packages…" text describes the <Target>, but it's now separated from it by the new <PropertyGroup>. Keeping that paragraph adjacent to the target and putting the new NuGet-ordering rationale directly above the PropertyGroup would read better.
There was a problem hiding this comment.
Line 39 has the 3-space indent. I wouldn't care that much here honestly to make everything in this file consistent.
NuGet's
GetPackOutputItemsTaskaddedNuspecFileandNuspecPropertiesas inputs to_GetOutputItemsFromPack, which runs inside_CalculateInputsOutputsForPack— beforeGenerateNuspec. Arcade'sInitializeStandardNuspecPropertiesonly declaredBeforeTargets="GenerateNuspec", soNuspecPropertieswas unset when_CalculateInputsOutputsForPackran, breaking.nuspec-based projects (e.g. aspnetcore).Changes
src/Microsoft.DotNet.Arcade.Sdk/tools/Workarounds.targets: Add_CalculateInputsOutputsForPacktoBeforeTargetsonInitializeStandardNuspecPropertiessoNuspecPropertiesis populated before either pack target reads it.To double check:
InitializeStandardNuspecPropertiesshould run before_CalculateInputsOutputsForPack#17226