question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow multiple versions of a particular dependency

See original GitHub issue

Description

This request pertains to the list-mismatches and fix-mismatches commands.

In some cases, it’s necessary to temporarily have different versions of a particular dependency present in the same repo, for example when experimenting with new things or moving code into a monorepo.

Example:

  • foo is a package within the monorepo
  • Several packages in the monorepo (including foo) depend on typescript and react
  • For most packages, their typescript and react versions must match, but foo is experimental and needs newer versions (it may also need newer versions of other packages)
  • Variant: foo could have a few related packages (like foo-utilities) which should share these different dependency versions

Existing solutions

  • Ignore all dependencies of foo by using a custom --source glob which excludes it: e.g. --source "{apps/*,packages/!(foo),packages/sub-group/*,scripts,.}/package.json" (from the real monorepo where I want this feature)
    • Disadvantages: allows accidental variation of other deps
  • Ignore all dependencies on typescript with --filter "^(?!^typescript$).*$"
    • Disadvantages: removes all restrictions on typescript

These options also share the following disadvantages:

  • Not terribly intuitive, at least in the exclusion/negation case
  • Awkward to type on the command line and/or must be duplicated across multiple package.json scripts
  • Doesn’t scale well if there are related packages which share alternate versions

Suggested Solutions

There are multiple possible ways to solve this, most simply by adding another command line option, but a package.json and/or config file option would be easier to use and more capable.

1. Command line option

Simplest implementation would be to add a command line option listing packages for which dependencies don’t need to match, something like --ignore <package-name-regex>.

This is not my preference (at least as the only solution) because:

  • It’s too permissive:
    • Allows any deps to vary, not just the (probably) one or two that you care about
    • If ignoring multiple package names, there’s no enforcement that the deps match within them, which is likely what would be desired
  • Typing potentially-complicated regexes on the command line (or duplicating them across multiple scripts in package.json) is annoying.

2. package.json (and/or config file) options

A better approach would be to add support for reading configuration from the monorepo root package.json (and/or a config file, but only using package.json would be easier). This allows easily specifying alternates xin the form of key/value mappings, which I think is the most logical form but would be very awkward to specify on the command line.

There are various ways the option could be set up. Alternatives can be found in the collapsed section below, but here’s what I’d suggest (though I’m not at all set on the names).

Using the same example from above, this would allow foo and foo-utilities to depend on any version of typescript and react, but all other packages must still depend on a matching version. variationGroups takes an array in case there are multiple groups of packages which should share alternate versions.

{
  "syncpack": {
    "variationGroups": [
      {
        "packages": ["foo", "foo-utilities"],
        "dependencies": ["typescript", "react"]
      }
    ]
  }
}

Other solutions considered

Click to expand

These were other options I considered but discarded for various reasons. (Again in all these cases, naming is not final.)

2a. List groups of monorepo packages to consider separately

Essentially, do two sub-runs: against foo plus foo-utilities, and against everything else.

{
  "syncpack": {
    "variationGroups": [
      ["foo", "foo-utilities"]
    ]
  }
}

Pros: Probably the simplest to set up and to implement. (Could potentially even be set up as a command line option.)

Cons: It’s likely that the variation group and the main group should still share versions of some dependencies, and this does nothing to enforce that.

2b. Mapping between monorepo package and deps which may vary

foo and foo-utilities may depend on any version of typescript and react, but all other packages must still depend on a matching version.

{
  "syncpack": {
    // Mapping from monorepo package to dep list
    "allowedVariations": {
      "foo": ["typescript", "react"],
      "foo-utilities": ["typescript", "react"]
    },
    // OR the inverse:
    // Mapping from dep to monorepo package list
    "allowedVariations": {
      "typescript": ["foo", "foo-utilities"],
      "react": ["foo", "foo-utilities"]
    }
  }
}

Pros: Simple to set up in some ways.

Cons: Requires duplication if there are additional packages which are related to foo; no notion of groups which should share dep versions

2c. Mapping from monorepo package to allowed semver specs

For particular packages, list the semver specs which are allowed. This is similar to allowedAlternateVersions from rush (which my team’s monorepo previously used).

{
  "syncpack": {
    "allowedVersions": {
      "typescript": ["3.7.2", "^3.9.0"]
    }
  }
}

Pros: No duplication required for multiple packages to share an alternate version; very specific

Cons: Additional place to manually change when upgrading versions; no notion of grouping; seems a bit incongruous with syncpack’s other options (which don’t rely on explicitly set semver specs)

Note for any package.json/config file-based solution

If any file-based config support is added for version alternates, it would probably make sense to also add support for overrideable defaults for the other options. For example, instead of having to specify --prod --dev --source "{apps/*,packages/!(foo),packages/sub-group/*,scripts,.}/package.json" for every syncpack command, you could do this:

{
  "syncpack": {
    "prod": true,
    "dev": true,
    "source": "{apps/*,packages/!(foo),packages/sub-group/*,scripts,.}/package.json"
  }
}

(Granted the long source glob would not be needed once this new config setting is added, but it would still be nice to have the other common options specified in a single place.)

Help Needed

I can probably help implement this.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
JamieMasoncommented, Aug 23, 2020

The config file work is released as of 5.2.5, which unblocks this issue.

1reaction
ecraig12345commented, Aug 6, 2020

I’m not sure about the name mismatchContexts since it could be misinterpreted to mean that mismatches are allowed among versions of dependencies within packages. Maybe alternateContexts or alternateGroups?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Multiple versions of the same dependency in Maven
No. Maven will only resolve one dependency in your module and will omit the other versions to avoid any conflict. Even if multiple...
Read more >
Is there a way to use multiple versions of the same ... - Quora
There is no way to use multiple versions of same dependency. In fact some times multiple modules bring different versions of a same...
Read more >
Overriding Dependency Versions and Using Version Ranges ...
Get step-by-step guidance on managing dependencies in Maven: declare dependencies, overriding dependency versions, and using version ranges.
Read more >
How to Resolve a Version Collision of Artifacts in Maven
Each dependency that we include in our project might link to other artifacts. Maven can automatically bring in these artifacts, also called ...
Read more >
Can Maven handle different dependency versions in ... - Reddit
Maven can do this, but your application might not be able to handle it. If you app is just a simple, single classloader...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found