Skip to content

packages migrate-cpm silently upgrades per-target-framework package versions to the highest one #250

Open

Description

@matt-edmondson

What's wrong

migrate-cpm collapses every PackageReference for a package down to one version, which is the maximum, and ignores conditions:

  • KtsuTools.Packages/PackagesService.cs:367 (packages[name] = version) keeps one version per package per project and ignores the item's Condition.
  • Line 261 keeps the maximum version across all projects.
  • Line 592 strips every Version attribute, including the conditional ones.

Reproduction (verified with dotnet restore)

A project targeting net8.0;net9.0 declares two references:

<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" Condition="'$(TargetFramework)'=='net8.0'" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" Condition="'$(TargetFramework)'=='net9.0'" />

After running ktools packages migrate-cpm --path .:

  • Directory.Packages.props contains only 9.0.0.
  • Both versions are removed from the csproj.
  • dotnet restore succeeds, and project.assets.json shows net8.0 now resolving 9.0.0.

Nothing in the output reports the change. Two projects that pin different versions are also collapsed to the maximum, with the same silence.

Why it matters

Giving each target framework its own version is the standard multi-targeting pattern. The migration silently upgrades the dependency on the lower target framework. That can pull in packages the framework doesn't support, or ones that require a newer runtime.

Suggested fix / acceptance criteria

  • Detect packages declared with more than one version, whether per condition or per project.
  • Preserve those versions, either as VersionOverride on the non-default ones or as conditional PackageVersion items. At minimum, print a warning table of every version that was collapsed.
  • Add a test: after migrating the conditional example above, net8.0 still resolves 8.0.1.

Activity

  1. matt-edmondson commented on Oct 6, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions