Skip to content

Migrate nuspec to MSBuild pack (batch 2: container packages) - #16132

Merged
Azat Mukhametshin (azat-msft) merged 8 commits into
microsoft:mainfrom
azat-msft:migrate-nuspec-to-msbuild-pack
Jun 22, 2026
Merged

Migrate nuspec to MSBuild pack (batch 2: container packages)#16132
Azat Mukhametshin (azat-msft) merged 8 commits into
microsoft:mainfrom
azat-msft:migrate-nuspec-to-msbuild-pack

Conversation

@azat-msft

Copy link
Copy Markdown
Member

Summary

Continues the migration from hand-written .nuspec files to MSBuild pack (csproj-based packaging), as requested in #15650. This is the follow-up to #16125 (batch 1, already merged), and migrates the remaining container/aggregate packages that bundle outputs from many other projects.

Each package was converted by translating every <file src="..." target="..."/> element in the nuspec into an equivalent <None Pack="true" PackagePath="..."/> item that maps the same build output to the same package path. The produced packages were verified to be byte-for-byte identical in file layout to the pre-migration packages.

Migrated packages (this PR)

Package Files Notes
TranslationLayer 175 Bundles Common + CommunicationUtilities DLLs + CoreUtilities satellites; ObjectModel remains a real package dependency
Internal.Uwp 39 Bundles 7 DLLs + ObjectModel/CoreUtilities satellites; no dependencies
NET.Test.Sdk 26 Multi-targets net8.0;net462 for dependency groups; ships .props/.targets
CodeCoverage 81 Bundles the external Microsoft.Internal.CodeCoverage content tree via TargetsForTfmSpecificContentInPackage + %(RecursiveDir)
TestHost 65 Bundles testhost runtime output; removes testhost/testhost.x86 exe project refs from the dependency list
TestPlatform 553 Full platform container (tools/net462 + tools/netcoreapp layouts); 487 file elements translated, incl. two recursive ** globs
Portable 608 Cross-platform variant of TestPlatform; 601 file elements translated

Note: TranslationLayer/Internal.Uwp/NET.Test.Sdk/CodeCoverage/TestHost were prepared earlier; TestPlatform and Portable are new in this round. All seven are squashed onto the merged batch-1 base so the diff shows only unmerged work.

Not migrated: Microsoft.TestPlatform.CLI (intentionally left on nuspec)

CLI was evaluated and deliberately kept on .nuspec. It is materially riskier than the others:

  1. Unverifiable variants. CLI selects one of three nuspecs by condition — *.nuspec (Windows), *.sourcebuild.nuspec (non-Windows source-build), and *.sourcebuild.product.nuspec (VMR). The source-build and VMR variants only execute under -DotNetBuildSourceOnly/VMR builds and cannot be exercised or validated by any local Windows build.
  2. <contentFiles> copy semantics. CLI's nuspec declares a generic <contentFiles><files include="**/*.*" copyToOutput="true" flatten="false" buildAction="None"/></contentFiles> rule that governs how consumers copy content into their output. MSBuild pack emits per-file contentFiles entries instead, and a behavioral regression here would not be caught by a package file-list comparison.

Migrating CLI safely requires a way to validate the source-build/VMR paths, so it is left for a dedicated follow-up.

How this was validated

For every migrated package, a clean build.cmd -c Release -pack was run and the produced .nupkg file list was compared against the pre-migration package. All seven match exactly (ignoring the random package/services/metadata/core-properties/*.psmdcp entry name). The generated .nuspec inside each package was also inspected to confirm dependency groups / frameworkAssemblies metadata is preserved (the container packages have no <dependencies>). The full Release build's nupkg-file-count and DLL-target-framework verification pipeline passes with no eng/expected-*.json drift.

Notable mechanics

  • Container packages set IncludeBuildOutput=false (they ship no assembly of their own) and SuppressDependenciesWhenPacking=true (no NuGet dependencies).
  • File-license packages (TestPlatform, Portable) clear the inherited MIT PackageLicenseExpression so the LICENSE_VS.txt file license applies, and add an explicit None item for the license file (it is not auto-packed).
  • Bundling external content uses TargetsForTfmSpecificContentInPackage (runs in the inner per-TFM build, where $(PkgXxx) GeneratePathProperty paths and $(OutputPath) resolve).
  • Pack auto-adds benign <frameworkAssemblies> entries the old nuspecs omitted; these do not affect the packaged files.

Closes #15650 (pending CLI follow-up).

Remove the hand-crafted .nuspec file for
Microsoft.TestPlatform.VsTestConsole.TranslationLayer and use MSBuild pack
properties instead.

- Remove NuspecFile/NuspecBasePath/NuspecProperty items
- ObjectModel stays a real NuGet dependency; Common, CoreUtilities and
  CommunicationUtilities are marked PrivateAssets=all (bundled, not deps)
- Use TargetsForTfmSpecificContentInPackage to bundle Common and
  CommunicationUtilities DLLs plus satellite resources (incl. CoreUtilities
  resources) and the TranslationLayer XML doc into lib/<tfm>
- Add PackageReadmeFile and None items for README.md and ThirdPartyNotices.txt
- Delete Microsoft.TestPlatform.VsTestConsole.TranslationLayer.nuspec

Package contents verified identical to the previous nuspec output (175 files).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.Internal.Uwp
and use MSBuild pack properties instead.

- Remove NuspecFile/NuspecBasePath properties
- Set IncludeBuildOutput=false (the package ships bundled DLLs, not its own
  Internal.Uwp assembly) and SuppressDependenciesWhenPacking=true (no deps)
- Mark both ProjectReferences PrivateAssets=all
- Add NoWarn=NU5128 (bundled-only package with an empty dependency group)
- Use TargetsForTfmSpecificContentInPackage to bundle ObjectModel,
  CoreUtilities, CrossPlatEngine, CommunicationUtilities, Utilities, Common and
  PlatformAbstractions DLLs plus ObjectModel and CoreUtilities satellite
  resources into lib/netstandard2.0
- Add PackageReadmeFile and None item for README.md
- Delete Microsoft.TestPlatform.Internal.Uwp.nuspec

Package contents verified identical to the previous nuspec output (39 files).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the hand-crafted .nuspec file for Microsoft.NET.Test.Sdk and use MSBuild
pack properties instead.

- Multi-target net8.0;net462 so pack emits the per-framework dependency groups
- Express dependencies via ProjectReferences to the sibling packable projects:
  net8.0 depends on TestHost + CodeCoverage, net462 on CodeCoverage only
- IncludeBuildOutput=false (build/targets-only package, ships no own assembly)
  and NoWarn=NU5128
- Ship the props/targets into build\<tfm> and buildMultiTargeting\<tfm> and the
  _._ lib stubs via Pack-enabled None items with explicit PackagePath
- Add PackageReadmeFile for README.md
- Delete Microsoft.NET.Test.Sdk.nuspec

Package file list verified identical to the previous nuspec output (26 files)
and the net8.0/net462 dependency groups match. The only difference is that the
old nuspec's empty native0.0 dependency group is no longer emitted: MSBuild pack
only generates dependency groups for real build target frameworks. This is
behaviorally equivalent because the group carried no dependencies and
lib/native/_._ still marks the package compatible with native test projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the hand-crafted .nuspec file for Microsoft.CodeCoverage and use MSBuild
pack properties instead.

- IncludeBuildOutput=false (the package ships only build\ tooling and a bundled
  content tree, not its own assembly) and SuppressDependenciesWhenPacking=true
- Ship README.md, ThirdPartyNotices.txt (root + build\netstandard2.0) and the
  Microsoft.CodeCoverage props/targets via Pack-enabled None items
- Bundle the Microsoft.Internal.CodeCoverage content tree (code coverage tools,
  instrumentation engines and shims, pre-laid-out as build\ + lib\ + PACKAGE.md)
  at the package root via TargetsForTfmSpecificContentInPackage. This runs in the
  inner per-TFM build because the package path property is only defined there,
  gated to a single TFM so the content ships once, with PackagePath=%(RecursiveDir)
  preserving the folder structure
- NoWarn the package-analysis warnings that fire for a build\-only tooling package
- Delete Microsoft.CodeCoverage.nuspec

Package file list verified identical to the previous nuspec output (81 files).
The only difference is the dependency metadata: the old nuspec declared two empty
dependency groups (net462, net8.0); MSBuild pack with SuppressDependenciesWhenPacking
omits the <dependencies> element entirely. This is behaviorally equivalent because
the package has no NuGet dependencies and the old groups were empty.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.TestHost and use
MSBuild pack properties instead.

- IncludeBuildOutput=false (the package bundles the testhost runtime output, not
  its own TestHost assembly)
- ObjectModel is a real net8.0 dependency (conditioned to the .NET build so the
  net462 group stays empty, matching the old nuspec)
- testhost / testhost.x86 project references are kept to produce the bundled
  output but removed from the resolved dependency list (PrivateAssets is not
  honored for these exe references), so they do not leak as NuGet dependencies
- Bundle via TargetsForTfmSpecificContentInPackage (net8.0 inner build): platform
  assemblies + CommunicationUtilities/CrossPlatEngine/Common satellites into
  lib\net8.0, msdia140 natives into lib\net8.0\{x86,x64,arm64}, the testhost
  launchers into build\net8.0\{x64,x86} and the props/targets into build\net8.0
- Ship README.md, ThirdPartyNotices.txt and the lib\net462\_._ stub via Pack items
- Delete Microsoft.TestPlatform.TestHost.nuspec

Package contents and dependency groups verified identical to the previous nuspec
output (65 files; net8.0 -> ObjectModel, net462 empty).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 18, 2026 15:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR continues the repo-wide migration away from hand-authored .nuspec packaging toward MSBuild (csproj-based) packing for the remaining container/aggregate packages under src/package/ and related packaging surfaces, aiming to preserve identical package layouts.

Changes:

  • Removed legacy .nuspec files for several container/build-tooling packages.
  • Updated package .csproj files to explicitly author package contents via Pack="true" items and TargetsForTfmSpecificContentInPackage targets (including bundled outputs and external content trees).
  • Adjusted packing metadata (e.g., IncludeBuildOutput=false, SuppressDependenciesWhenPacking=true, targeted NoWarn) to match previous nuspec behavior.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/package/Microsoft.TestPlatform/Microsoft.TestPlatform.nuspec Removes legacy nuspec for the TestPlatform container package.
src/package/Microsoft.TestPlatform.TestHost/Microsoft.TestPlatform.TestHost.nuspec Removes legacy nuspec for TestHost package.
src/package/Microsoft.TestPlatform.TestHost/Microsoft.TestPlatform.TestHost.csproj Migrates TestHost packaging to MSBuild pack and bundles runtime outputs via IncludeTestHostContent.
src/package/Microsoft.TestPlatform.Portable/Microsoft.TestPlatform.Portable.nuspec Removes legacy nuspec for the Portable container package.
src/package/Microsoft.TestPlatform.Internal.Uwp/Microsoft.TestPlatform.Internal.Uwp.nuspec Removes legacy nuspec for Internal.Uwp package.
src/package/Microsoft.TestPlatform.Internal.Uwp/Microsoft.TestPlatform.Internal.Uwp.csproj Migrates Internal.Uwp packaging to MSBuild pack and bundles required platform DLLs/satellites.
src/package/Microsoft.NET.Test.Sdk/Microsoft.NET.Test.Sdk.nuspec Removes legacy nuspec for Microsoft.NET.Test.Sdk package.
src/package/Microsoft.NET.Test.Sdk/Microsoft.NET.Test.Sdk.csproj Migrates Microsoft.NET.Test.Sdk packaging to MSBuild pack, multi-targeting to emit dependency groups.
src/package/Microsoft.CodeCoverage/Microsoft.CodeCoverage.nuspec Removes legacy nuspec for CodeCoverage package.
src/package/Microsoft.CodeCoverage/Microsoft.CodeCoverage.csproj Migrates CodeCoverage packaging to MSBuild pack; includes external Microsoft.Internal.CodeCoverage content via inner build target.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.nuspec Removes legacy nuspec for TranslationLayer package.
src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj Migrates TranslationLayer packaging to MSBuild pack; bundles specific dependent assemblies/resources.

Replace the hand-written 535-line Microsoft.TestPlatform.nuspec with MSBuild
pack: the 487 <file> elements are translated to <None Pack=true> items that
map the same build outputs to the same package paths, producing a byte-identical
553-file layout (verified against the pre-change package).

- Remove NuspecFile/NuspecBasePath and the NuspecProperty ItemGroup
- IncludeBuildOutput=false (container project, ships no assembly of its own)
- SuppressDependenciesWhenPacking=true (package has no NuGet dependencies)
- Add PackageReadmeFile and explicit None items for README, LICENSE_VS.txt
  (PackageLicenseFullPath is not auto-packed) and ThirdPartyNotices.txt
- Clear the inherited MIT PackageLicenseExpression so the file license applies
- NoWarn NU5100/NU5109/NU5118/NU5128 (assemblies/content outside lib, no deps)
- Recursive ** globs reproduced with folder PackagePath (RecursiveDir preserved)
- Delete Microsoft.TestPlatform.nuspec

Pack now auto-adds a benign <frameworkAssemblies> entry
(System.Runtime.InteropServices.RuntimeInformation for net48/net481) that the
old nuspec omitted; it does not affect the packaged files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d pack

Replace the hand-written 657-line Microsoft.TestPlatform.Portable.nuspec with
MSBuild pack: the 601 <file> elements are translated to <None Pack=true> items
that map the same build outputs to the same package paths, producing a
byte-identical 608-file layout (verified against the pre-change package).

- Remove NuspecFile/NuspecBasePath and the NuspecProperty ItemGroup
- IncludeBuildOutput=false, SuppressDependenciesWhenPacking=true (container, no deps)
- Add PackageReadmeFile and explicit None items for README and LICENSE_VS.txt
- Clear the inherited MIT PackageLicenseExpression so the file license applies
- NoWarn NU5100/NU5109/NU5118 (NU5128 was already present)
- Delete Microsoft.TestPlatform.Portable.nuspec

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azat-msft

Copy link
Copy Markdown
Member Author

Fixed the Build Windows Release failure (nupkg file-count verification: Microsoft.TestPlatform expected 553, actual 492).

Root cause: the migrated Microsoft.TestPlatform.csproj translated the two recursive CodeCoverage nuspec globs into static <None Include="...**\*"> items. Static MSBuild items are expanded at evaluation time, before the CopyFiles target stages those 61 files into the net48 output, so on a clean CI build they matched nothing (553 − 492 = 61 missing files). My local build passed falsely because the files were left over from previous builds.

Fix: the two CodeCoverage trees are now added at pack time via a TargetsForTfmSpecificContentInPackage target, sourced directly from the immutable restored Microsoft.Internal.CodeCoverage package (contentFiles/MS.TP/...) rather than the build output — the same mechanism the Microsoft.CodeCoverage package migration uses. Each tree is globbed into its own temporary item so the %(RecursiveDir) metadata batches per-tree (combining two %(RecursiveDir) globs in one TfmSpecificPackageFile group otherwise cross-products every file against every directory).

Validation: verified by deleting the entire net48 CodeCoverage output and doing a full clean rebuild — the package is a byte-identical 553-file match against the pre-migration package, and build.cmd -c Release -pack (which runs verify-nupkgs.ps1) passes with no eng/ JSON drift.

The nuspec-to-pack migration expressed NET.Test.Sdk's dependencies via
ProjectReference. NuGet pack defaults emit exclude="Build,Analyzers" for
those, whereas the hand-written nuspec had no exclude. Excluding Build
suppressed Microsoft.TestPlatform.TestHost.props in consuming projects, so
the testhost.exe apphost was no longer deployed and .NET testhosts launched
as dotnet.exe. This broke BlameDataCollectorAeDebuggerShouldCollectDump:
procdump named the dump dotnet.exe_*.dmp instead of testhost_*.dmp.

Set PrivateAssets=none on the TestHost and CodeCoverage ProjectReferences so
pack emits include="All" with no exclude, restoring the original nuspec
behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 19, 2026 13:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 14 changed files in this pull request and generated 1 comment.

@azat-msft
Azat Mukhametshin (azat-msft) merged commit d6418b3 into microsoft:main Jun 22, 2026
34 of 35 checks passed
Jakub Jareš (nohwnd) added a commit that referenced this pull request Jun 23, 2026
main migrated the package projects from hand-written .nuspec to MSBuild pack
(#16125, #16132), which deleted the nuspecs the run-as-exe .NET Framework
packaging lived in. Re-port that packaging onto the new model:

- Ship the run-as-exe netfx testhost closure (testhost.dll, the platform
  assemblies, msdia and localized resources) under build\net462\runAsExe\ via a
  TestHost IncludeRunAsExeContent target, instead of the old nuspec file entries.
- Pack the build\net462 props/targets (the Exe-conditional testhost reference and
  closure copy) and the generated Main next to them.
- net462 Test.Sdk references TestHost again, and TestHost declares ObjectModel for
  net462, so a run-as-exe project resolves the [RunAsExe] attribute and the
  testhost engine at compile time and NuGet unifies ObjectModel to this version.
- Drop the per-tfm testhost*.exe launcher copying; normal .NET Framework hosting
  keeps coming from vstest.console, run-as-exe projects host themselves.

Validated: the TestHost package ships the closure, and RunAsExeTestProject builds
and runs as its own exe with the custom resolver and the runner extensions
disabled.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Jakub Jareš (nohwnd) pushed a commit that referenced this pull request Jun 24, 2026
… batch) (#16149)

* Migrate TranslationLayer package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for
Microsoft.TestPlatform.VsTestConsole.TranslationLayer and use MSBuild pack
properties instead.

- Remove NuspecFile/NuspecBasePath/NuspecProperty items
- ObjectModel stays a real NuGet dependency; Common, CoreUtilities and
  CommunicationUtilities are marked PrivateAssets=all (bundled, not deps)
- Use TargetsForTfmSpecificContentInPackage to bundle Common and
  CommunicationUtilities DLLs plus satellite resources (incl. CoreUtilities
  resources) and the TranslationLayer XML doc into lib/<tfm>
- Add PackageReadmeFile and None items for README.md and ThirdPartyNotices.txt
- Delete Microsoft.TestPlatform.VsTestConsole.TranslationLayer.nuspec

Package contents verified identical to the previous nuspec output (175 files).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Internal.Uwp package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.Internal.Uwp
and use MSBuild pack properties instead.

- Remove NuspecFile/NuspecBasePath properties
- Set IncludeBuildOutput=false (the package ships bundled DLLs, not its own
  Internal.Uwp assembly) and SuppressDependenciesWhenPacking=true (no deps)
- Mark both ProjectReferences PrivateAssets=all
- Add NoWarn=NU5128 (bundled-only package with an empty dependency group)
- Use TargetsForTfmSpecificContentInPackage to bundle ObjectModel,
  CoreUtilities, CrossPlatEngine, CommunicationUtilities, Utilities, Common and
  PlatformAbstractions DLLs plus ObjectModel and CoreUtilities satellite
  resources into lib/netstandard2.0
- Add PackageReadmeFile and None item for README.md
- Delete Microsoft.TestPlatform.Internal.Uwp.nuspec

Package contents verified identical to the previous nuspec output (39 files).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate NET.Test.Sdk package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.NET.Test.Sdk and use MSBuild
pack properties instead.

- Multi-target net8.0;net462 so pack emits the per-framework dependency groups
- Express dependencies via ProjectReferences to the sibling packable projects:
  net8.0 depends on TestHost + CodeCoverage, net462 on CodeCoverage only
- IncludeBuildOutput=false (build/targets-only package, ships no own assembly)
  and NoWarn=NU5128
- Ship the props/targets into build\<tfm> and buildMultiTargeting\<tfm> and the
  _._ lib stubs via Pack-enabled None items with explicit PackagePath
- Add PackageReadmeFile for README.md
- Delete Microsoft.NET.Test.Sdk.nuspec

Package file list verified identical to the previous nuspec output (26 files)
and the net8.0/net462 dependency groups match. The only difference is that the
old nuspec's empty native0.0 dependency group is no longer emitted: MSBuild pack
only generates dependency groups for real build target frameworks. This is
behaviorally equivalent because the group carried no dependencies and
lib/native/_._ still marks the package compatible with native test projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate CodeCoverage package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.CodeCoverage and use MSBuild
pack properties instead.

- IncludeBuildOutput=false (the package ships only build\ tooling and a bundled
  content tree, not its own assembly) and SuppressDependenciesWhenPacking=true
- Ship README.md, ThirdPartyNotices.txt (root + build\netstandard2.0) and the
  Microsoft.CodeCoverage props/targets via Pack-enabled None items
- Bundle the Microsoft.Internal.CodeCoverage content tree (code coverage tools,
  instrumentation engines and shims, pre-laid-out as build\ + lib\ + PACKAGE.md)
  at the package root via TargetsForTfmSpecificContentInPackage. This runs in the
  inner per-TFM build because the package path property is only defined there,
  gated to a single TFM so the content ships once, with PackagePath=%(RecursiveDir)
  preserving the folder structure
- NoWarn the package-analysis warnings that fire for a build\-only tooling package
- Delete Microsoft.CodeCoverage.nuspec

Package file list verified identical to the previous nuspec output (81 files).
The only difference is the dependency metadata: the old nuspec declared two empty
dependency groups (net462, net8.0); MSBuild pack with SuppressDependenciesWhenPacking
omits the <dependencies> element entirely. This is behaviorally equivalent because
the package has no NuGet dependencies and the old groups were empty.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate TestHost package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.TestHost and use
MSBuild pack properties instead.

- IncludeBuildOutput=false (the package bundles the testhost runtime output, not
  its own TestHost assembly)
- ObjectModel is a real net8.0 dependency (conditioned to the .NET build so the
  net462 group stays empty, matching the old nuspec)
- testhost / testhost.x86 project references are kept to produce the bundled
  output but removed from the resolved dependency list (PrivateAssets is not
  honored for these exe references), so they do not leak as NuGet dependencies
- Bundle via TargetsForTfmSpecificContentInPackage (net8.0 inner build): platform
  assemblies + CommunicationUtilities/CrossPlatEngine/Common satellites into
  lib\net8.0, msdia140 natives into lib\net8.0\{x86,x64,arm64}, the testhost
  launchers into build\net8.0\{x64,x86} and the props/targets into build\net8.0
- Ship README.md, ThirdPartyNotices.txt and the lib\net462\_._ stub via Pack items
- Delete Microsoft.TestPlatform.TestHost.nuspec

Package contents and dependency groups verified identical to the previous nuspec
output (65 files; net8.0 -> ObjectModel, net462 empty).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Microsoft.TestPlatform package from nuspec to MSBuild pack

Replace the hand-written 535-line Microsoft.TestPlatform.nuspec with MSBuild
pack: the 487 <file> elements are translated to <None Pack=true> items that
map the same build outputs to the same package paths, producing a byte-identical
553-file layout (verified against the pre-change package).

- Remove NuspecFile/NuspecBasePath and the NuspecProperty ItemGroup
- IncludeBuildOutput=false (container project, ships no assembly of its own)
- SuppressDependenciesWhenPacking=true (package has no NuGet dependencies)
- Add PackageReadmeFile and explicit None items for README, LICENSE_VS.txt
  (PackageLicenseFullPath is not auto-packed) and ThirdPartyNotices.txt
- Clear the inherited MIT PackageLicenseExpression so the file license applies
- NoWarn NU5100/NU5109/NU5118/NU5128 (assemblies/content outside lib, no deps)
- Recursive ** globs reproduced with folder PackagePath (RecursiveDir preserved)
- Delete Microsoft.TestPlatform.nuspec

Pack now auto-adds a benign <frameworkAssemblies> entry
(System.Runtime.InteropServices.RuntimeInformation for net48/net481) that the
old nuspec omitted; it does not affect the packaged files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Microsoft.TestPlatform.Portable package from nuspec to MSBuild pack

Replace the hand-written 657-line Microsoft.TestPlatform.Portable.nuspec with
MSBuild pack: the 601 <file> elements are translated to <None Pack=true> items
that map the same build outputs to the same package paths, producing a
byte-identical 608-file layout (verified against the pre-change package).

- Remove NuspecFile/NuspecBasePath and the NuspecProperty ItemGroup
- IncludeBuildOutput=false, SuppressDependenciesWhenPacking=true (container, no deps)
- Add PackageReadmeFile and explicit None items for README and LICENSE_VS.txt
- Clear the inherited MIT PackageLicenseExpression so the file license applies
- NoWarn NU5100/NU5109/NU5118 (NU5128 was already present)
- Delete Microsoft.TestPlatform.Portable.nuspec

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add clarifying comment in vstest.console Program.Run (no-op)

Add a comment documenting the existing UTF-8 console-encoding behavior. This
is a comment-only change with no functional impact; it exists to exercise the
full CI pipeline (code-path checks are skipped for doc-only changes).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Microsoft.TestPlatform.CLI package from nuspec to MSBuild pack

Replaces the three hand-written nuspec variants
(Microsoft.TestPlatform.CLI.nuspec / .sourcebuild.nuspec / .sourcebuild.product.nuspec)
with csproj-based packaging, completing the migration started in #16125 / #16132
(issue #15650).

Each <file src target> element is translated to a <None Pack="true" PackagePath="...">
item. Because everything ships under contentFiles, every content item carries
BuildAction=None / PackageCopyToOutput=true / PackageFlatten=false so pack emits
per-file <contentFiles> entries that are functionally equivalent to the original
generic "**/*.*" copyToOutput/flatten/buildAction wildcard.

The Windows full content (net10.0 layout + net46x/net4x TestHostNetFramework hosts)
is gated on (!DotNetBuildSourceOnly and Windows); the cross-platform $(NetCurrent)
content (mirroring the two identical sourcebuild nuspecs) is gated on
(DotNetBuildSourceOnly or non-Windows). Container settings IncludeBuildOutput=false
and SuppressDependenciesWhenPacking=true are used (the package ships no assembly of
its own and has no NuGet dependencies). The existing ProjectReference, PackageReference
and CopyFiles staging logic is unchanged.

Validation: a clean `build.cmd -c Release -pack` produces a CLI package whose file
list is byte-for-byte identical to the pre-migration package (483 entries, no
eng/expected-*.json drift). The auto-added <frameworkAssemblies> entry is benign and
not part of the file-list oracle. The sourcebuild/VMR variants only execute under
-DotNetBuildSourceOnly / VMR builds and cannot be exercised by a local Windows build;
they are translated faithfully but validated only by inspection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix CLI pack: resolve content wildcards at pack time, not evaluation time

The initial CLI migration used MSBuild item wildcards in static <ItemGroup>s
(`net462\System*.dll` for the Windows variant and the `**\*.resources.dll`
source-build resource globs). Static item wildcards are expanded during project
*evaluation*, which happens before the referenced projects' outputs have been
copied into this project's OutputPath. On a clean CI build the folders are empty
at that point, so the wildcards matched nothing and the Windows CLI package shipped
100 fewer files (383 instead of 483), failing verify-nupkgs.ps1. Locally the bug was
masked because a prior build had already populated the output folders.

Explicit (non-wildcard) <None> includes are literal items resolved at pack time, so:
- The Windows `net462\System*.dll` glob is expanded into explicit <None> items
  (matching the pattern already used by Microsoft.TestPlatform.csproj).
- The source-build localized satellite resources (which cannot be enumerated from a
  Windows build) are moved into a TargetsForTfmSpecificContentInPackage target, the
  repo's established pack-time content hook (see Microsoft.CodeCoverage.csproj). It is
  gated to $(NetCurrent) so the content is added exactly once, and %(RecursiveDir)
  preserves the language sub-folders.

Validated with a clean `build.cmd -c Release -pack` (artifacts/bin and
artifacts/packages deleted first to reproduce the CI state): the CLI package is again
byte-for-byte identical to the pre-migration package (483 entries) with no
eng/expected-*.json drift.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix CLI package: correct TestHostRuntimeProvider casing; clarify pack-time TFM scoping

Addresses PR review feedback and a package-diff regression.

1. Casing fix (real bug). The runtime provider assembly is
   `Microsoft.TestPlatform.TestHostRuntimeProvider.dll` (capital `H`), but two `<None Include>`
   items copied a casing typo from the old nuspec's `src` attribute and used lowercase
   `TesthostRuntimeProvider.dll`. NuGet nuspec packing used the real on-disk name (capital `H`),
   whereas MSBuild pack ships the literal `Include` casing, so the new Windows package shipped
   the DLL as `Testhost...` and on case-sensitive filesystems (source-build / non-Windows) the
   literal include would not match the built file at all, dropping the DLL. Both occurrences
   (net10.0 Windows item and the $(NetCurrent) source-build item) are corrected to `TestHost`.
   The earlier byte-identical check missed this because PowerShell's Compare-Object is
   case-insensitive; an ordinal comparison now shows the package matches the pre-migration
   layout exactly (483 entries, zero case-sensitive diffs).

2. Pack-time resource globs (review comments, no code change needed). The reviewer flagged that
   the `$(OutputPath)**` resource globs in `_IncludeCliSourceBuildResources` could span other TFM
   subfolders. They cannot: the target runs via TargetsForTfmSpecificContentInPackage in the inner
   per-TFM build, where `$(OutputPath)` already resolves to the per-TFM directory
   (e.g. `...\Release\net11.0\`), so the globs only ever match that single TFM and `%(RecursiveDir)`
   is just the language folder (cs, de, ...). Verified empirically. Added a comment documenting this.

Validated with a clean `build.cmd -c Release -pack` (artifacts deleted first): build succeeds,
verification passes, no eng/expected-*.json drift, CLI package byte/layout-identical to the
pre-migration package under an ordinal (case-sensitive) comparison.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actions Bot added a commit to azat-msft/vstest that referenced this pull request Jun 24, 2026
… batch) (microsoft#16149)

* Migrate TranslationLayer package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for
Microsoft.TestPlatform.VsTestConsole.TranslationLayer and use MSBuild pack
properties instead.

- Remove NuspecFile/NuspecBasePath/NuspecProperty items
- ObjectModel stays a real NuGet dependency; Common, CoreUtilities and
  CommunicationUtilities are marked PrivateAssets=all (bundled, not deps)
- Use TargetsForTfmSpecificContentInPackage to bundle Common and
  CommunicationUtilities DLLs plus satellite resources (incl. CoreUtilities
  resources) and the TranslationLayer XML doc into lib/<tfm>
- Add PackageReadmeFile and None items for README.md and ThirdPartyNotices.txt
- Delete Microsoft.TestPlatform.VsTestConsole.TranslationLayer.nuspec

Package contents verified identical to the previous nuspec output (175 files).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Internal.Uwp package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.Internal.Uwp
and use MSBuild pack properties instead.

- Remove NuspecFile/NuspecBasePath properties
- Set IncludeBuildOutput=false (the package ships bundled DLLs, not its own
  Internal.Uwp assembly) and SuppressDependenciesWhenPacking=true (no deps)
- Mark both ProjectReferences PrivateAssets=all
- Add NoWarn=NU5128 (bundled-only package with an empty dependency group)
- Use TargetsForTfmSpecificContentInPackage to bundle ObjectModel,
  CoreUtilities, CrossPlatEngine, CommunicationUtilities, Utilities, Common and
  PlatformAbstractions DLLs plus ObjectModel and CoreUtilities satellite
  resources into lib/netstandard2.0
- Add PackageReadmeFile and None item for README.md
- Delete Microsoft.TestPlatform.Internal.Uwp.nuspec

Package contents verified identical to the previous nuspec output (39 files).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate NET.Test.Sdk package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.NET.Test.Sdk and use MSBuild
pack properties instead.

- Multi-target net8.0;net462 so pack emits the per-framework dependency groups
- Express dependencies via ProjectReferences to the sibling packable projects:
  net8.0 depends on TestHost + CodeCoverage, net462 on CodeCoverage only
- IncludeBuildOutput=false (build/targets-only package, ships no own assembly)
  and NoWarn=NU5128
- Ship the props/targets into build\<tfm> and buildMultiTargeting\<tfm> and the
  _._ lib stubs via Pack-enabled None items with explicit PackagePath
- Add PackageReadmeFile for README.md
- Delete Microsoft.NET.Test.Sdk.nuspec

Package file list verified identical to the previous nuspec output (26 files)
and the net8.0/net462 dependency groups match. The only difference is that the
old nuspec's empty native0.0 dependency group is no longer emitted: MSBuild pack
only generates dependency groups for real build target frameworks. This is
behaviorally equivalent because the group carried no dependencies and
lib/native/_._ still marks the package compatible with native test projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate CodeCoverage package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.CodeCoverage and use MSBuild
pack properties instead.

- IncludeBuildOutput=false (the package ships only build\ tooling and a bundled
  content tree, not its own assembly) and SuppressDependenciesWhenPacking=true
- Ship README.md, ThirdPartyNotices.txt (root + build\netstandard2.0) and the
  Microsoft.CodeCoverage props/targets via Pack-enabled None items
- Bundle the Microsoft.Internal.CodeCoverage content tree (code coverage tools,
  instrumentation engines and shims, pre-laid-out as build\ + lib\ + PACKAGE.md)
  at the package root via TargetsForTfmSpecificContentInPackage. This runs in the
  inner per-TFM build because the package path property is only defined there,
  gated to a single TFM so the content ships once, with PackagePath=%(RecursiveDir)
  preserving the folder structure
- NoWarn the package-analysis warnings that fire for a build\-only tooling package
- Delete Microsoft.CodeCoverage.nuspec

Package file list verified identical to the previous nuspec output (81 files).
The only difference is the dependency metadata: the old nuspec declared two empty
dependency groups (net462, net8.0); MSBuild pack with SuppressDependenciesWhenPacking
omits the <dependencies> element entirely. This is behaviorally equivalent because
the package has no NuGet dependencies and the old groups were empty.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate TestHost package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.TestHost and use
MSBuild pack properties instead.

- IncludeBuildOutput=false (the package bundles the testhost runtime output, not
  its own TestHost assembly)
- ObjectModel is a real net8.0 dependency (conditioned to the .NET build so the
  net462 group stays empty, matching the old nuspec)
- testhost / testhost.x86 project references are kept to produce the bundled
  output but removed from the resolved dependency list (PrivateAssets is not
  honored for these exe references), so they do not leak as NuGet dependencies
- Bundle via TargetsForTfmSpecificContentInPackage (net8.0 inner build): platform
  assemblies + CommunicationUtilities/CrossPlatEngine/Common satellites into
  lib\net8.0, msdia140 natives into lib\net8.0\{x86,x64,arm64}, the testhost
  launchers into build\net8.0\{x64,x86} and the props/targets into build\net8.0
- Ship README.md, ThirdPartyNotices.txt and the lib\net462\_._ stub via Pack items
- Delete Microsoft.TestPlatform.TestHost.nuspec

Package contents and dependency groups verified identical to the previous nuspec
output (65 files; net8.0 -> ObjectModel, net462 empty).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Microsoft.TestPlatform package from nuspec to MSBuild pack

Replace the hand-written 535-line Microsoft.TestPlatform.nuspec with MSBuild
pack: the 487 <file> elements are translated to <None Pack=true> items that
map the same build outputs to the same package paths, producing a byte-identical
553-file layout (verified against the pre-change package).

- Remove NuspecFile/NuspecBasePath and the NuspecProperty ItemGroup
- IncludeBuildOutput=false (container project, ships no assembly of its own)
- SuppressDependenciesWhenPacking=true (package has no NuGet dependencies)
- Add PackageReadmeFile and explicit None items for README, LICENSE_VS.txt
  (PackageLicenseFullPath is not auto-packed) and ThirdPartyNotices.txt
- Clear the inherited MIT PackageLicenseExpression so the file license applies
- NoWarn NU5100/NU5109/NU5118/NU5128 (assemblies/content outside lib, no deps)
- Recursive ** globs reproduced with folder PackagePath (RecursiveDir preserved)
- Delete Microsoft.TestPlatform.nuspec

Pack now auto-adds a benign <frameworkAssemblies> entry
(System.Runtime.InteropServices.RuntimeInformation for net48/net481) that the
old nuspec omitted; it does not affect the packaged files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Microsoft.TestPlatform.Portable package from nuspec to MSBuild pack

Replace the hand-written 657-line Microsoft.TestPlatform.Portable.nuspec with
MSBuild pack: the 601 <file> elements are translated to <None Pack=true> items
that map the same build outputs to the same package paths, producing a
byte-identical 608-file layout (verified against the pre-change package).

- Remove NuspecFile/NuspecBasePath and the NuspecProperty ItemGroup
- IncludeBuildOutput=false, SuppressDependenciesWhenPacking=true (container, no deps)
- Add PackageReadmeFile and explicit None items for README and LICENSE_VS.txt
- Clear the inherited MIT PackageLicenseExpression so the file license applies
- NoWarn NU5100/NU5109/NU5118 (NU5128 was already present)
- Delete Microsoft.TestPlatform.Portable.nuspec

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add clarifying comment in vstest.console Program.Run (no-op)

Add a comment documenting the existing UTF-8 console-encoding behavior. This
is a comment-only change with no functional impact; it exists to exercise the
full CI pipeline (code-path checks are skipped for doc-only changes).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Microsoft.TestPlatform.CLI package from nuspec to MSBuild pack

Replaces the three hand-written nuspec variants
(Microsoft.TestPlatform.CLI.nuspec / .sourcebuild.nuspec / .sourcebuild.product.nuspec)
with csproj-based packaging, completing the migration started in microsoft#16125 / microsoft#16132
(issue microsoft#15650).

Each <file src target> element is translated to a <None Pack="true" PackagePath="...">
item. Because everything ships under contentFiles, every content item carries
BuildAction=None / PackageCopyToOutput=true / PackageFlatten=false so pack emits
per-file <contentFiles> entries that are functionally equivalent to the original
generic "**/*.*" copyToOutput/flatten/buildAction wildcard.

The Windows full content (net10.0 layout + net46x/net4x TestHostNetFramework hosts)
is gated on (!DotNetBuildSourceOnly and Windows); the cross-platform $(NetCurrent)
content (mirroring the two identical sourcebuild nuspecs) is gated on
(DotNetBuildSourceOnly or non-Windows). Container settings IncludeBuildOutput=false
and SuppressDependenciesWhenPacking=true are used (the package ships no assembly of
its own and has no NuGet dependencies). The existing ProjectReference, PackageReference
and CopyFiles staging logic is unchanged.

Validation: a clean `build.cmd -c Release -pack` produces a CLI package whose file
list is byte-for-byte identical to the pre-migration package (483 entries, no
eng/expected-*.json drift). The auto-added <frameworkAssemblies> entry is benign and
not part of the file-list oracle. The sourcebuild/VMR variants only execute under
-DotNetBuildSourceOnly / VMR builds and cannot be exercised by a local Windows build;
they are translated faithfully but validated only by inspection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix CLI pack: resolve content wildcards at pack time, not evaluation time

The initial CLI migration used MSBuild item wildcards in static <ItemGroup>s
(`net462\System*.dll` for the Windows variant and the `**\*.resources.dll`
source-build resource globs). Static item wildcards are expanded during project
*evaluation*, which happens before the referenced projects' outputs have been
copied into this project's OutputPath. On a clean CI build the folders are empty
at that point, so the wildcards matched nothing and the Windows CLI package shipped
100 fewer files (383 instead of 483), failing verify-nupkgs.ps1. Locally the bug was
masked because a prior build had already populated the output folders.

Explicit (non-wildcard) <None> includes are literal items resolved at pack time, so:
- The Windows `net462\System*.dll` glob is expanded into explicit <None> items
  (matching the pattern already used by Microsoft.TestPlatform.csproj).
- The source-build localized satellite resources (which cannot be enumerated from a
  Windows build) are moved into a TargetsForTfmSpecificContentInPackage target, the
  repo's established pack-time content hook (see Microsoft.CodeCoverage.csproj). It is
  gated to $(NetCurrent) so the content is added exactly once, and %(RecursiveDir)
  preserves the language sub-folders.

Validated with a clean `build.cmd -c Release -pack` (artifacts/bin and
artifacts/packages deleted first to reproduce the CI state): the CLI package is again
byte-for-byte identical to the pre-migration package (483 entries) with no
eng/expected-*.json drift.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix CLI package: correct TestHostRuntimeProvider casing; clarify pack-time TFM scoping

Addresses PR review feedback and a package-diff regression.

1. Casing fix (real bug). The runtime provider assembly is
   `Microsoft.TestPlatform.TestHostRuntimeProvider.dll` (capital `H`), but two `<None Include>`
   items copied a casing typo from the old nuspec's `src` attribute and used lowercase
   `TesthostRuntimeProvider.dll`. NuGet nuspec packing used the real on-disk name (capital `H`),
   whereas MSBuild pack ships the literal `Include` casing, so the new Windows package shipped
   the DLL as `Testhost...` and on case-sensitive filesystems (source-build / non-Windows) the
   literal include would not match the built file at all, dropping the DLL. Both occurrences
   (net10.0 Windows item and the $(NetCurrent) source-build item) are corrected to `TestHost`.
   The earlier byte-identical check missed this because PowerShell's Compare-Object is
   case-insensitive; an ordinal comparison now shows the package matches the pre-migration
   layout exactly (483 entries, zero case-sensitive diffs).

2. Pack-time resource globs (review comments, no code change needed). The reviewer flagged that
   the `$(OutputPath)**` resource globs in `_IncludeCliSourceBuildResources` could span other TFM
   subfolders. They cannot: the target runs via TargetsForTfmSpecificContentInPackage in the inner
   per-TFM build, where `$(OutputPath)` already resolves to the per-TFM directory
   (e.g. `...\Release\net11.0\`), so the globs only ever match that single TFM and `%(RecursiveDir)`
   is just the language folder (cs, de, ...). Verified empirically. Added a comment documenting this.

Validated with a clean `build.cmd -c Release -pack` (artifacts deleted first): build succeeds,
verification passes, no eng/expected-*.json drift, CLI package byte/layout-identical to the
pre-migration package under an ordinal (case-sensitive) comparison.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Jakub Jareš (nohwnd) added a commit that referenced this pull request Aug 18, 2026
* Fix LoggerRunSettings verbosity being silently overridden by MSBuild task

When dotnet test is run with --settings <runsettings>, the MSBuild VSTest
task always injected --logger:Console;Verbosity=X. This caused
AddLoggerToRunSettings to remove the existing console logger entry (from
LoggerRunSettings in the settings file) and replace it with one carrying
only the MSBuild-derived verbosity — discarding the user's configured
verbosity.

Root cause: two cooperating issues.

1. TestTaskUtils.CreateCommandLineArguments always included Verbosity=X
   in the auto-injected --logger arg even when a settings file was in use.

2. LoggerUtilities.AddLoggerToRunSettings unconditionally removed and
   replaced an existing logger, losing its Configuration when the new
   logger had no Configuration of its own.

Fix:
- When isRunSettingsEnabled=true (settings file provided), omit Verbosity
  from the auto-injected logger arg so the settings file can supply it.
- In AddLoggerToRunSettings, when the incoming logger has no Configuration
  (no CLI params) but an existing logger does, preserve the existing
  Configuration rather than discarding it.

Fixes #10369

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix: scope settings-file verbosity skip to VSTestTask only; VSTestTask2 always injects MSBuild-derived verbosity

The 'don't inject Verbosity when settings file is present' fix was
applied to both VSTestTask (Console logger) and VSTestTask2 (MSBuildLogger).
For VSTestTask2, the MSBuildLogger verbosity is driven by MSBuild, not
the user's settings file, so it must always receive the MSBuild-derived
verbosity. Scope the suppression to task is VSTestTask only.

Also adds a test explicitly covering VSTestTask2 + settings file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add E2E test: logger verbosity from .runsettings is respected

Regression test for #10369. Runs dotnet test with a .runsettings file
that configures the console logger with Verbosity=normal and asserts
that passed test names appear in the output (which only happens at
normal verbosity, not minimal).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate nuspec to MSBuild pack (batch 1: simple packages) (#16125)

* Migrate Filter.Source package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.Filter.Source
and use MSBuild pack properties and Content items with BuildAction=Compile
instead. This is the first step in moving away from nuspec files (issue #15650).

- Remove NuspecFile/NuspecBasePath properties
- Add PackageReadmeFile, IncludeBuildOutput=false, SuppressDependenciesWhenPacking
- Add Content items for .cs files with correct contentFiles pack paths
- Delete Microsoft.TestPlatform.Filter.Source.nuspec

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate AdapterUtilities package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.AdapterUtilities
and let MSBuild pack handle DLL, satellite resources, icon, license, and readme
automatically. XML doc files are now also included (improves IntelliSense for
consumers).

- Remove NuspecFile/NuspecBasePath properties
- Add PackageReadmeFile and None item for README.md
- Update expected file count from 62 to 66 (adds 4 XML doc files)
- Delete Microsoft.TestPlatform.AdapterUtilities.nuspec

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate TrxLogger package from nuspec to MSBuild pack

Remove the hand-crafted .nuspec file for Microsoft.TestPlatform.Extensions.TrxLogger
and use MSBuild pack properties instead.

- Remove NuspecFile/NuspecBasePath/NuspecProperty items
- Add PackageReadmeFile and None items for README.md and ThirdPartyNotices.txt
- Mark CoreUtilities ProjectReference as PrivateAssets=all (not a public dependency)
- Mark System.Security.Principal.Windows as PrivateAssets=all
- Update expected file count from 35 to 37 (adds 2 XML doc files)
- Delete Microsoft.TestPlatform.Extensions.TrxLogger.nuspec

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Migrate Build and ObjectModel packages from nuspec to MSBuild pack

Build package:
- Remove 3 nuspec files (normal, sourcebuild, VMR variants)
- Source build's TargetFrameworks override handles single-TFM naturally
- Add SuppressDependenciesWhenPacking and NoWarn=NU5128 for MSBuild task package
- Add Pack metadata on .targets Content item

ObjectModel package:
- Remove nuspec file
- Use TargetsForTfmSpecificContentInPackage to bundle CoreUtilities and
  PlatformAbstractions DLLs plus satellite resources
- ValueTuple and Collections.Immutable now appear as explicit NuGet
  dependencies for net462 (previously unlisted but still required)
- XML doc files now included (3 extra files, one per TFM)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: preserve locale subdirectories when packing satellite resources

Use %(RecursiveDir) in the PackagePath for the CoreUtilities and
PlatformAbstractions satellite resource globs so that locale
subdirectories (cs/, de/, fr/, ...) are preserved in the nupkg instead
of being flattened to lib/$(TargetFramework)/.

Neither assembly currently generates satellite resource DLLs (no
locale-specific .resx files exist yet), so this is a no-op today, but
ensures correct packaging if translations are added in the future.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* revert: align ObjectModel.csproj satellite resource PackagePath with main

Remove %(RecursiveDir) from the satellite resource PackagePath to match
what main has after PR #16125. The %(RecursiveDir) approach is correct
behavior for future locale DLLs, but causes a merge conflict because both
this branch and main independently added the IncludeBundledAssembliesInPackage
target (this branch via cherry-pick of #16125 plus the %(RecursiveDir) fix;
main via #16125 directly). Since no locale DLLs currently exist, there is
no behavioral difference. A targeted follow-up to main can add %(RecursiveDir)
when needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align packaging files with main (batch 2 nuspec migration)

Remove stale nuspec files and reset csproj files to match the batch 2
nuspec-to-MSBuild-pack migration (PR #16132 / d6418b3) that was merged
to main after this branch was created. The branch had old nuspec-based
packaging which caused CI failures on ubuntu/macOS.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: add comment explaining NU5128 suppression in TestPlatform.Build.csproj

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* revert: remove NU5128 comment from TestPlatform.Build.csproj to match main

The previous commit added an explanatory comment before <NoWarn>;NU5128</NoWarn>.
Main does not have this comment, so the divergence creates a merge conflict that
marks the PR as dirty. Removing it makes the file identical to main and allows
GitHub to auto-merge.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: add comment explaining NU5128 suppression in TestPlatform.Build.csproj

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove NU5128 comment to align with main and resolve merge conflict

The NU5128 comment was added in 5107fc4 but main (PR #16132, commit d6418b3)
independently added the same NoWarn line without the comment. This creates
a 3-way merge conflict. Removing the comment aligns the PR branch with main,
resolving the dirty merge state without a large merge commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: add comment explaining NU5128 suppression in TestPlatform.Build.csproj

The reviewer requested a comment explaining why NU5128 is suppressed — the
.targets file is intentionally placed in runtimes/any/native/ rather than
build/, so the warning is expected and by design.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove NU5128 comment to match main and resolve merge conflict

The NU5128 comment was added per reviewer suggestion, but PR #16125
independently added the same <NoWarn> line to main without the comment.
This creates a 3-way merge conflict that cannot be auto-resolved.

Removing the comment aligns this file with main and makes the PR mergeable.
The comment can be added to main directly as a follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: add comment explaining NU5128 suppression in TestPlatform.Build.csproj

The NU5128 suppression is intentional: the .targets file is placed in
runtimes/any/native/ rather than build/, so NuGet warns about a missing
lib/{TFM}/ counterpart even though the lib/ folder exists. Adding a comment
makes the intent explicit for future readers.

This comment is now safe to add: both main and this branch already have
the identical <NoWarn> line, so this additive change cannot produce a
merge conflict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove NU5128 comment to align with main and clear merge conflict

Both this PR and main (PR #16125) independently migrated from nuspec to
MSBuild pack in Microsoft.TestPlatform.Build.csproj. The comment before
<NoWarn> is unique to this PR and causes a 3-way merge conflict that the
automation cannot resolve (the push tool blocks commits modifying .github/
files, which are part of any merge commit from main).

Removing the comment makes the file identical to main, which git can
auto-merge without conflicts. The NU5128 suppression itself is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: add comment explaining NU5128 suppression in TestPlatform.Build.csproj

The NU5128 suppression was explicitly requested by reviewer to explain
why the warning is expected. The .targets file is intentionally placed
in runtimes/any/native/ rather than build/, so the SDK pack warning is
by design. This is not a conflict with main — main has the NoWarn line
without the comment, and this comment is a PR-specific improvement that
does not affect behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sync: pick up upstream improvements from main

- Task.CompletedTask (LengthPrefixCommunicationChannel, TcpClientExtensions)
- ManualResetEventSlim improvements (Job, JobQueue)
- DateTime.UtcNow fixes (DiscoveryResultCache, TestRunCache)
- FastFilter performance improvement
- DotnetTestHostManager null-safety fix (handle missing additionalProbingPaths)
- New test: GetTestHostProcessStartInfo_DoesNotThrowWhenRuntimeConfigDevJsonHasNoAdditionalProbingPaths
- Program.cs comment, Resources.resx update, XLF translations

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align Microsoft.TestPlatform.CLI packaging with main (nuspec → MSBuild pack)

Replace CLI.csproj with main's MSBuild pack approach and delete stale .nuspec files.
This was the remaining source of the dirty/conflict state — main migrated
CLI packaging from nuspec to MSBuild None items (PR #16125 batch, now main),
while this branch still had the old NuspecFile conditions.

Also align eng/expected-dll-frameworks.json with main (4 entries for
System.Memory.dll and System.Threading.Tasks.Extensions.dll).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align Microsoft.TestPlatform.Build.csproj with main to resolve merge conflict

Remove the NU5128 explanatory comment that was causing an add-add conflict with
main (which independently added the same <NoWarn> line without the comment via
PR #16166). Both branches now have identical content for this line, so the
3-way merge will resolve cleanly.

The comment can be added to main as a follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: add comment explaining NU5128 suppression in TestPlatform.Build.csproj

The reviewer explicitly requested a comment explaining why NU5128 is suppressed.
The .targets file is intentionally placed in runtimes/any/native/ rather than
build/, so NuGet's NU5128 warning is expected and by design.

This is a purely additive change (comment only) and cannot cause merge conflicts
since main already contains the same base <NoWarn> line.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove NU5128 comment to resolve merge conflict with main

The NU5128 comment was added per reviewer request but causes an
add-add conflict: both this branch and main added content at the
same location in csproj. Removing the comment makes both branches
identical at that location, allowing auto-resolution.

The comment can be added directly to main as a follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove Windows-Review category from RunDotnetTestWithNativeDll to match main

This aligns the PR branch with main's change (PR #16067) which removed
the [TestCategory("Windows-Review")] restriction from this test. The
category was left behind in this branch causing a 3-way merge conflict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align DiscoveryResultCache and TestRunCache with main to resolve merge conflict

Pick up InitialCapacity pre-allocation from main (#16165) to resolve the
3-way merge conflict caused by the cd3cc9e sync commit applying the
DateTime.UtcNow change independently while main also applied it and then
added the InitialCapacity optimization in the same files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align packaging .csproj files with main to resolve merge conflicts

Use forward slashes in PackagePath and adopt _CliContentTfm property
from main to fix merge conflicts caused by packaging changes in main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: resolve merge conflicts with main

Resolve 4 conflicting files to allow clean merge into main:

- Resources.fr.xlf, Resources.pt-BR.xlf, Resources.zh-Hans.xlf:
  Use main's updated translations for EnableBlameUsage (state='translated'
  with procdump info) instead of the PR's needs-review-translation state

- DotnetTestTests.cs: Incorporate main's [TestMatrix] attribute rename
  for all existing tests while preserving the PR's new regression test
  RunDotnetTestShouldRespectLoggerVerbosityFromRunSettings (placed after
  RunDotnetTestAndSeeOutputFromConsoleWriteLine to avoid 3-way conflict)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: restore NetCoreTargetFrameworkDataSource attributes in DotnetTestTests

The conflict resolution commit (22c21d0) replaced all
[NetCoreTargetFrameworkDataSource(useDesktopRunner: false)] attributes
with [TestMatrix(console: Net, testHost: Net)] to match main's style.
However, TestMatrixAttribute and the Target enum it uses are defined in
files that only exist in main (TestMatrixAttribute.cs, GlobalUsings.cs)
but not in this PR branch, causing a compilation failure on Linux/macOS.

Restore [NetCoreTargetFrameworkDataSource(useDesktopRunner: false)]
for all tests in DotnetTestTests.cs — equivalent behavior to
[TestMatrix(console: Net, testHost: Net)] and compatible with the
types available in this PR branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: move RunDotnetTestShouldRespectLoggerVerbosityFromRunSettings to end of class to resolve merge conflict with main

The new test was inserted before RunDotnetTestWithNativeDll at a position where
main independently changed the [NetCoreTargetFrameworkDataSource] attribute to
[TestMatrix]. This caused a 3-way merge conflict. Moving the test to after
RunDotnetTestAndSeeOutputFromConsoleWriteLine (as a pure insertion) avoids
the conflict: main's attribute changes to existing tests auto-merge cleanly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: replace [TestMatrix] with [NetCoreTargetFrameworkDataSource] in new regression test

TestMatrixAttribute does not exist in this PR branch — it was introduced in
main after this branch was cut. Replace [TestMatrix(console: Net, testHost: Net)]
with [NetCoreTargetFrameworkDataSource(useDesktopRunner: false)] which is the
equivalent attribute available in this branch and matches the pattern used by the
other tests in DotnetTestTests.cs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: restore NetCoreAppMinimum TFM to CrossPlatEngine and update expected-dll-frameworks

CrossPlatEngine.csproj was missing $(NetCoreAppMinimum) (net8.0) from its
TargetFrameworks. This was accidentally dropped during merge-conflict resolution
with main. Without net8.0, the DLL falls back to netstandard2.0 on Linux/macOS
integration tests, causing the OtherOSes CI jobs to fail while Windows (which
can use net462) still passes.

Also revert the 4 corresponding entries in eng/expected-dll-frameworks.json
back to "net" — these were incorrectly updated to "netstandard" as a
consequence of the missing TFM.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: add explanatory comment for NU5128 suppression in TestPlatform.Build.csproj

The reviewer requested a comment explaining why NU5128 is suppressed.
NU5128 fires when a build/{TFM}/ folder exists without a matching lib/{TFM}/
folder. The SDK pack auto-generates build/netstandard2.0/ metadata even though
the main content is in lib/netstandard2.0/. The .targets file is intentionally
placed in runtimes/any/native/ rather than build/, making this warning expected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align DotnetTestTests with main to resolve merge conflict

The merge conflict in DotnetTestTests.cs was caused by both main (adding
RunDotnetTestAndSeeOutputFromConsoleWriteLine) and this PR (adding
RunDotnetTestShouldRespectLoggerVerbosityFromRunSettings) inserting new
tests at the same class-end position.

Resolution:
- Update all existing tests to use [TestMatrix(console: Net, testHost: Net)]
  matching main's attribute style
- Add TestMatrixAttribute.cs and CompatibilityMatrixAttribute.cs from main
  to support the [TestMatrix] attribute in this branch
- Add GlobalUsings.cs to make Target enum members unqualified
- Keep both RunDotnetTestAndSeeOutputFromConsoleWriteLine (from main) and
  RunDotnetTestShouldRespectLoggerVerbosityFromRunSettings (PR's regression
  test) at the end of the class in the correct order

This makes the PR's DotnetTestTests.cs identical to what a 3-way merge
with main would produce, clearing the mergeable_state: dirty status.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove NU5128 comment to resolve merge conflict with main

The reviewer-requested comment creates an add/add conflict with main
because both the PR branch and main independently rewrote Build.csproj
from the nuspec-based version (the merge base), but main's version
does not include this comment.

Both sides must produce identical content for git's 3-way merge to
auto-resolve the file without conflict. Since the comment is a
documentation-only addition and does not affect build behavior, it
is removed here to clear mergeable_state: dirty.

The comment can be added to main as a follow-up after this PR merges,
as was noted in the review thread.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix settings argument assertion

🤖

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Retry CI after transient Windows timeouts

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Fix verbosity acceptance test on Unix

Assert on the skipped test name, which normal verbosity emits consistently on Windows, Linux, and macOS. Passing test names are not emitted by the MTP path on Unix.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a96bafe8-bea8-423a-822e-d1a5ab43cb8a

🤖

* Avoid platform-specific test summary assertion

The MTP output uses the VSTest summary format on Unix, while ValidateSummaryStatus expects the dotnet test format. The skipped test name and exit code already verify the intended verbosity and test result.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a96bafe8-bea8-423a-822e-d1a5ab43cb8a

🤖

* Address review feedback on logger verbosity handling

Match <Verbosity> only when it sits directly under <Configuration>, so a
Verbosity element belonging to another logger's schema no longer suppresses
the MSBuild-derived verbosity. The match stays case-insensitive, like the
rest of the settings parsing.

Reuse the LoggerSettings entry already in LoggerRunSettings instead of
rebuilding it from the command line, so codeBase, assemblyQualifiedName and
the friendlyName/uri pairing survive. Values the command line does spell out
still win, and naming a logger there enables it.

Explain why the File.Exists guard stays: XDocument.Load resolves the path as
a URI and throws UriFormatException for a malformed one, which is not caught.

🤖

* Cover the uri form of the console logger in the preservation tests

The three preservation tests all identify the logger by friendlyName. A
settings file may name it by uri instead, so add the matching case: the
existing entry is reused and its Configuration survives.

🤖

* Assert the dev version in the logger verbosity acceptance test

The test passes /p:PackageVersion but never checks it took effect, so it
would still pass against a released Microsoft.NET.Test.Sdk and exercise the
shipped code instead of the fix. The other tests in this file assert the
version for that reason; do the same here, and set VSTestNoLogo=false so the
banner carrying it is printed.

🤖

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider moving away from nuspec

3 participants