Fix mismatch between GetPackOutputItemsTask and PackTask generated filenames#7137
Fix mismatch between GetPackOutputItemsTask and PackTask generated filenames#7137gekka wants to merge 21 commits into
Conversation
…put target in Nuget.Build.Tasks.Pack.targets.
The build error was caused by project dependencies defined in the solution file. Dependencies were configured at the solution level, Azure Pipelines failed to build the affected project.
|
@gekka I'm conceptually fine with what this PR claims to fix. But I see the CI failures are related to changes made by this PR, so I'm not going to do a full review until we get a green CI. No problem adding the project reference to the test project. |
| <GetPackOutputItemsTask | ||
| PackageOutputPath="$(PackageOutputAbsolutePath)" | ||
| NuspecOutputPath="$(NuspecOutputAbsolutePath)" | ||
| NuspecInputFilePath="$(NuspecFile)" |
There was a problem hiding this comment.
PackTask already takes a bunch of these properties as input.
I think for ease for maintenance, the property names should be the same.
So instead of NuspecInputFilePath, use NuspecFile.
Something else, we should use the NuspecFileAbsolutePath as https://github.com/NuGet/NuGet.Client/blob/3a2648cbab3528f4105e0dedbe60be26289379eb/src/NuGet.Core/NuGet.Build.Tasks/NuGet.Build.Tasks.Pack.targets#L265C29-L265C51 is using it.
There was a problem hiding this comment.
Change the property name from NuspecInputFilePath to NuspecFile
$(AbsolutePath) doesn’t exist when GetPackOutputItemsTask is called, I changed the logic to generate it from $(NuspecFile) and pass it in.
Ideally, for maintainability, PackTask should use the output filename produced by GetPackOutputItemsTask directly, which would avoid inconsistencies from generating filenames separately. However, that would require larger changes to PackTask, so this pull request applies the minimal fix.
|
This PR encountered a few failing tests. A portion of them were due to my code, but there were also intermittent failures that don’t seem to be related. This flakiness timeout failures seem to be coming from NuGet.Protocol.Tests.PackageUpdateResourceTests class. There’s an existing issue that appears to mention the same type of flakiness. |
There was a problem hiding this comment.
Pull request overview
This PR addresses inconsistencies in how pack output filenames are computed vs. produced when packing with a .nuspec and/or NuspecProperties, and ensures OutputFileNamesWithoutVersion is respected consistently so downstream MSBuild targets see the expected outputs.
Changes:
- Update
_GetOutputItemsFromPackto passNuspecFile,NuspecProperties, andOutputFileNamesWithoutVersionintoGetPackOutputItemsTask. - Align
PackTaskLogic/GetPackOutputItemsTaskhandling ofNuspecProperties(notablyversion) and applyexcludeVersionwhen generating filenames. - Add new tests/fixtures (including an MSBuild invocation test) to validate that computed output item names match the files actually produced.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| test/NuGet.Core.Tests/NuGet.Build.Tasks.Pack.Test/PackageNameTests.cs | Adds theory-based coverage comparing GetPackOutputItemsTask output vs. produced pack artifacts. |
| test/NuGet.Core.Tests/NuGet.Build.Tasks.Pack.Test/NuGet.Build.Tasks.Pack.Test.csproj | Adds a project reference needed for the new MSBuild-based test setup. |
| test/NuGet.Core.Tests/NuGet.Build.Tasks.Pack.Test/BuildFixture.cs | Introduces a fixture to locate patched dotnet/MSBuild and built task/targets artifacts for integration-style tests. |
| src/NuGet.Core/NuGet.Build.Tasks/NuGet.Build.Tasks.Pack.targets | Passes nuspec inputs and versionless-output option into _GetOutputItemsFromPack’s GetPackOutputItemsTask. |
| src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs | Factors nuspec property parsing into a helper and normalizes/validates version. |
| src/NuGet.Core/NuGet.Build.Tasks.Pack/GetPackOutputItemsTask.cs | Uses nuspec inputs to compute output names consistently and respects OutputFileNamesWithoutVersion. |
|
@nkolev92 |
|
Sorry for the delay @gekka. I'll take another look. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
nkolev92
left a comment
There was a problem hiding this comment.
Apologies for the delay.
I have some suggestions that improve the readiability of the test cases and simplify the actual bootstrapping logic.
| { | ||
|
|
||
| //// without nuspec input | ||
| new PackageFileNameTestCase("000",["proj.1.9.0.nupkg" ], "proj", "nusp", "1.9", "", "", false), |
There was a problem hiding this comment.
I appreciated the depth of a bunch of these tests.
They were a bit hard to read though, so I have a simplified version that I have on a separate branch. I didn't want to push it on your branch without permission.
Check-out https://github.com/NuGet/NuGet.Client/tree/gekka/fix-nuget-package-file-name.
Another important thing was we actually never really need the csproj, so a bunch of that code is simpler because of that.
There was a lot of good stuff in your tests though, such as case number, so I evolved that into a test case name, and effectively added a named parameter for everything.
| var csprojPath = Path.Combine(testDirectory, FILENAME_PROJECT_FILE); | ||
| var nuspecPath = Path.Combine(testDirectory, FILENAME_NUSPEC_FILE); | ||
|
|
||
| var csprojContent = $""" |
There was a problem hiding this comment.
We never actually needed the csproj, so it can be removed.
It very much simplifies the code.
| </PropertyGroup> | ||
|
|
||
| <PropertyGroup> | ||
| <DefineConstants>$(DefineConstants);TEST_FOR_UNIT</DefineConstants> |
There was a problem hiding this comment.
We don't need this anymore either.
That simplification is part of my branch too.
| [MemberData(nameof(PackageFileNameTestCases))] | ||
| public void GetPackOutputItemsTaskTests_Execute_CheckPackageFileName(PackageFileNameTestCase testCase) | ||
| { | ||
| var outputItemTask = new NuGet.Build.Tasks.Pack.GetPackOutputItemsTask(); |
There was a problem hiding this comment.
You probably don't need the namespace qualifier here.
There's a bunch of that used, but it's unnecessary.
| <GetPackOutputItemsTask | ||
| PackageOutputPath="$(PackageOutputAbsolutePath)" | ||
| NuspecOutputPath="$(NuspecOutputAbsolutePath)" | ||
| NuspecFile="$(NuspecFileAbsolutePath)" |
There was a problem hiding this comment.
So _CleanPackageFiles dependeds on this target here.
This task now unconditionally opens the nuspec. When that happens, then we don't generate the pack output right?
I think this can in theory mess with clean, but not 100% sure.
There was a problem hiding this comment.
I agree that this behavior is not ideal.
The main purpose of _CleanPackageFiles is simply to prevent old output files from being left behind, but it isn’t strictly required.
If the version number is updated dynamically, the file names change as well, so this task cannot delete the old files in the first place.
| } | ||
|
|
||
| var nuspecReader = new NuGet.Packaging.NuspecReader(source.NuspecFile); | ||
| if (!hasIdInNuspecProperties) |
There was a problem hiding this comment.
This may be a regression.
In particular, I think nuspecProperties are supposed to be used for substitution but not authoritatively override.
There was a problem hiding this comment.
PackTask and GetPackOutputItemsTask were producing different outputs, so this change updates GetPackOutputItemsTask to match file names from PackTask .
PackTask is the authoritative behavior and is too large to modify.
There is also an existing test that has meta name for id and version in nuspec file, and to keep that test unchanged while aligning the outputs.
The processing order in this PR is required.
NuGet.Client/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs
Lines 1480 to 1505 in 4b68681
|
This PR has been automatically marked as stale because it has no activity for 7 days. It will be closed if no further activity occurs within another 30 days of this comment. If it is closed, you may reopen it anytime when you're ready again, as long as you don't delete the branch. |
|
I'll look again. |

Bug
Fixes: Nuget/Home#14711
Fixes: Nuget/Home#12644
Description
This pull request fixes a mismatch between the file name that GetPackOutputItemsTask expects for a generated .nupkg and the actual file name produced by PackTask when a project uses NuspecFile or NuspecProperties (including dynamically generated versions).
This PR also fixes an issue with the OutputFileNamesWithoutVersion property, ensuring Pack respects that setting when computing and emitting the final .nupkg file name so downstream targets receive the expected version‑less output.
PR Checklist
Note
One of this tests invoke msbuild to compare the file name computed by GetPackOutputItemsTask with the actual file produced by PackTask. As a result, the NuGet.Build.Tasks.Pack.Test project acquires a new dependency.
I’m not certain whether this test implementation and approach align with the repository’s conventions, so feedback or guidance would be appreciated, especially if anything is incorrect.