nx icon indicating copy to clipboard operation
nx copied to clipboard

New Versioning protocol incorrectly bumps downstream pinned versions

Open comp615 opened this issue 6 months ago • 2 comments

Current Behavior

Picture three package.jsons:

{
  "name": "@company/upstream",
  "version": "8.1.0"
}

{
  "name": "@company/downstream-pinned",
  "version": "0.0.1"
  "dependencies": {
    "@company/upstream": "7.3.4"
  }
}

{
  "name": "@company/downstream-workspace",
  "version": "0.0.1"
  "dependencies": {
    "@company/upstream": "workspace:*"
  }
}

Currently, when we make a change to upstream, it will replace the dependency in @company/downstream-pinned with 8.1.0.

Expected Behavior

In the legacy versioning implementation, bumping upstream would result in no dependencies being incremented in the example above, and pnpm would handle things via the workspace using preserveLocalDependencyProtocols.

We have a specific usage for pinning dependencies that also exist in the local workspace and need a way to control this. It helps us migrate packages from outside the repo into the repo (we use syncpack to allow exceptions and work our way through aligning them to current).

GitHub Repo

No response

Steps to Reproduce

  1. Create a repo where a package depends on the pinned version of another in-workspace package
  2. Update that package
  3. Compare results with both sets of nx.json settings (see below)

Nx Report

Node           : 20.19.1
OS             : darwin-arm64
Native Target  : aarch64-macos
pnpm           : 10.11.0

nx                     : 21.2.0-beta.1
@nx/js                 : 21.1.2
@nx/jest               : 21.2.0-beta.1
@nx/eslint             : 21.2.0-beta.1
@nx/workspace          : 21.2.0-beta.1
@nx/cypress            : 21.2.0-beta.1
@nx/devkit             : 21.2.0-beta.1
@nx/eslint-plugin      : 21.2.0-beta.1
@nx/module-federation  : 21.2.0-beta.1
@nx/plugin             : 21.2.0-beta.1
@nx/react              : 21.2.0-beta.1
@nx/storybook          : 21.2.0-beta.1
@nx/vite               : 21.2.0-beta.1
@nx/web                : 21.2.0-beta.1
typescript             : 5.5.4

---------------------------------------
Nx key licensed packages
Licensed to Block Inc..

@nx/powerpack-s3-cache  : 2.0.3

---------------------------------------
Registered Plugins:
@nx/vite/plugin
@squareup/service-dashboard-web-runtime/nx-plugin
@nx/storybook/plugin
@squareup/nx-lint-plugin
@squareup/nx-stats-plugin
@squareup/service-i18n/nx-plugin
---------------------------------------
Community plugins:
@squareup/service-i18n : 0.94.1
---------------------------------------
Local workspace plugins:
         @squareup/service-i18n
         @squareup/migrate
---------------------------------------
Cache Usage: 1.35 GB / 92.64 GB
---------------------------------------

Failure Logs


Package Manager Version

No response

Operating System

  • [ ] macOS
  • [ ] Linux
  • [ ] Windows
  • [ ] Other (Please specify)

Additional Information

nx.json

    // New generator config
    "version": {
      "specifierSource": "conventional-commits",
      "currentVersionResolver": "git-tag",
      "fallbackCurrentVersionResolver": "disk",
      "versionActionsOptions": {
        "skipLockFileUpdate": true,
      },
      "preVersionCommand": "nx run-many -t build",
    },

    // Old generator
    "version": {
      "generatorOptions": {
        "specifierSource": "conventional-commits",
        "currentVersionResolver": "git-tag",
        "skipLockFileUpdate": true,
        "fallbackCurrentVersionResolver": "disk",
        "preserveLocalDependencyProtocols": true,
      },
      "preVersionCommand": "nx run-many -t build",
      "useLegacyVersioning": true,
    },

It seems like maybe it's related to how the old version used resolveLocalPackageDependencies. Perhaps that filtered things differently...like the old one skipped it if the dep was remote, but the new one increments it if the dep exists in the local workspace (and both are true?)

comp615 avatar Jun 04 '25 14:06 comp615

Logging dependencies for @company/downstream-pinned on this line returns a list that includes the upstream dep twice:

[
  { source: '@company/downstream-pinned', target: '@company/upstream', type: 'static' },
  { source: '@company/downstream-pinned',  target: 'npm:@company/upstream', type: 'static' }
]

The first one causes the version bump.

In the legacy versioning flow, I believe this check evaluates to false for the first dependency, filtering it out of the resolveLocalPackageDependencies result.

laneysmith avatar Jun 04 '25 20:06 laneysmith

Logging dependencies for @company/downstream-pinned on this line returns a list that includes the upstream dep twice:

[ { source: '@company/downstream-pinned', target: '@company/upstream', type: 'static' }, { source: '@company/downstream-pinned', target: 'npm:@company/upstream', type: 'static' } ] The first one causes the version bump.

In the legacy versioning flow, I believe this check evaluates to false for the first dependency, filtering it out of the resolveLocalPackageDependencies result.

I tried messing around with a fix here that solves the issue in our repo, but results in some other Nx tests failing, so probably not the path forward. Since the presence of that first dependency in the project's dependency array is what appears to be causing the pinned version to get updated, I shifted to looking at the project graph.

I noticed that for any local dependency, if it is only referenced by the workspace:^ version in all downstream dependents, they'll all just have { source: '@company/downstream-pinned', target: '@company/upstream', type: 'static' } in their dependency graph. But as soon as any single project starts depending on a fixed, non-workspace version, I saw 2 unexpected (to me at least) things happen:

  1. All dependents now have the 2 instances of that dependency in their graph, one with the npm: prefix and one without. It seems really odd that changing the version of a local upstream dependency in 1 project affects the project graph dependencies for all other downstream dependents.
  2. For all of those dependents, even the ones still using workspace:^, the graph loses context of which files reference the upstream project (as in, when you open the nx graph gui and click the arrow connecting the projects, now the only file listed is package.json).

laneysmith avatar Jun 10 '25 15:06 laneysmith

Hi @comp615 @laneysmith,

Thanks for digging into this and providing the extra information, we'll get a resolution in place for this ASAP

JamesHenry avatar Jul 16 '25 09:07 JamesHenry

@comp615 I'm very sorry for the delay, we paired on this yesterday and it's really a project graph issue, which then gets inherited by release. We are just finalizing whether we want to take the time to address it directly in the project graph right now or implement a quicker workaround in release.

@Coly010 will be taking a look and will get back to you on here

JamesHenry avatar Sep 10 '25 09:09 JamesHenry

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

github-actions[bot] avatar Oct 27 '25 00:10 github-actions[bot]