Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Introduce safe option #1034

Closed
Primajin opened this issue Jan 21, 2022 · 7 comments · Fixed by #1052
Closed

[FR] Introduce safe option #1034

Primajin opened this issue Jan 21, 2022 · 7 comments · Fixed by #1052

Comments

@Primajin
Copy link
Contributor

Primajin commented Jan 21, 2022

I am currently using the --filterVersion option in order to run the checks only on non-pinned versions.
However I need to run it twice since

> npm-check-updates --filterVersion "/^[~^]/" -t minor

Checking C:\mypath\package.json
[====================] 130/130 100%

 @types/node                       ^17.0.9  →  ^17.0.10
 @types/react-router               ^5.1.17  →   ^5.1.18
 @typescript-eslint/eslint-plugin   ~5.9.0  →   ~5.10.0
 @typescript-eslint/parser          ~5.9.0  →   ~5.10.0
 eslint-plugin-jest                ~25.3.4  →   ~25.7.0
 npm-check-updates                 ^12.1.0  →   ^12.2.0
 typescript                         ^4.5.4  →    ^4.5.5

gives me not exactly want I want.
I actually don't want to bump a minor (^) on @typescript-eslint/parser but only a patch (~)

So instead I changed that to

> npm-check-updates --filterVersion "/^[\^]/" -t minor && npm-check-updates --filterVersion "/^[~]/" -t patch

Checking C:\mypath\package.json
[====================] 127/127 100%

 @types/node          ^17.0.9  →  ^17.0.10
 @types/react-router  ^5.1.17  →   ^5.1.18
 npm-check-updates    ^12.1.0  →   ^12.2.0
 typescript            ^4.5.4  →    ^4.5.5

Run ncu -u to upgrade package.json

Checking C:\mypath\package.json
[====================] 3/3 100%

 @typescript-eslint/eslint-plugin  ~5.9.0  →  ~5.9.1
 @typescript-eslint/parser         ~5.9.0  →  ~5.9.1

Run ncu -u to upgrade package.json

Which gives me the "correct" minor and patches for the ones I want and skips pinned versions.

Though I wonder if we could introduce a new target version like safe (naming is hard, maybe you have a better one) that does that automatically:

  1. Skips all pinned versions
  2. Checks for minor on caret Option to bump existing ranges to reflect latest semver version #581 / feature request: target that respects range grammar in package.json (~1.0.0, ^1.0.0, etc) #950
  3. Checks for patch on tilde Option to bump existing ranges to reflect latest semver version #581 / feature request: target that respects range grammar in package.json (~1.0.0, ^1.0.0, etc) #950
  4. maybe even skips versions that start with 0 [FR] --target minor or patch should exclude 0.x.x release #958

What do you think?

EDIT: Apparently I missed #581 / #950 - however if you like I can try to take a stab at it 👍🏻

Originally posted by @Primajin in #958 (comment)

@raineorshine
Copy link
Owner

raineorshine commented Jan 21, 2022

Thanks for the idea!

--target semver seems like the simplest solution, and others have requested it.

I will say that npm-check-updates --filterVersion "/^[\^]/" -t minor && npm-check-updates --filterVersion "/^[~]/" -t patch is also a good solution. Behavior that can easily be handled in the shell should be done that way if it means npm-check-updates can avoid unnecessary complexity. (There are exceptions to this, for example the --deep option which was possible to do in the shell but highly inefficient.)

As for specific options like --target safe, I would prefer to provide low-level primitives that would allow users to easily configure more complex filters and targets. I'd like to add support for specifying a target function in your .ncurc.js file:

module.exports = {
  target: (name, version) => 
    version.startsWith('^') ? 'minor' 
    : version.startsWith('~') ? 'patch' 
    : 'latest'
}

This would be the most flexible option for users with more complex upgrade policies.

@Primajin
Copy link
Contributor Author

Ohh cool, just learned about the ncurc file 🎉! Maybe we should then be more generic in deferring the options of the parameters to what a function in that file returns? 🤔

The downside to running multiple commands apart from time etc is that if you want to upgrade with -u as it is suggested one needs to add the param to every command - while that is of course nicer if you only have one command that runs different checks based on semver.
And yes semver is a way way better name than safe 😅 Naming is hard.

@Primajin
Copy link
Contributor Author

Primajin commented Jan 23, 2022

OK cool, I can try to look into this in the coming week.
Just so that I didn't misunderstand it: The plan is to allow a function in the .ncurc.js to provide the resolutions for the parameter.
Is it ok to focus only on target for now or shall I look into making all parameters overridable? 🤔

@raineorshine
Copy link
Owner

Yes, you can just add function support to target.

You don't need to change .ncurc.js itself. Just add support (and unit tests) for ncu's programmatic usage and .ncurc.js will work as-is. I would convert non-function target values to functions in initOptions so they can all be handled the same way. Then change all the code that uses options.target to expect a function.

I recommend that the target callback is invoked on each dependency and has the following signature:

target: (name: string, versionRange: SemVer) => string
  • name - The name of the package.
  • versionRange - The result of semverutils.parseRange(versionRange) on the current version range specified in the package file. This parses major, minor, patch, build so users don't have to.
  • returns latest, greatest, newest, minor, or patch.

The biggest change is that you will need to call a different getPackageVersion for each package. Currently it uses a single target function for all packages:

const getPackageVersion = packageManager[target as keyof typeof packageManager] as GetVersion

These are then mapped across the package list:

const versions = await pMap(packageList, getPackageVersionProtected, { concurrency: options.concurrency })

You should be able to map a factory function that creates the correct getPackageVersion for the given package.

Let me know if I can help in any way :).

@Primajin
Copy link
Contributor Author

Sorry was swamped with meetings before my upcoming time off - so I wont be able to provide a PR until in two weeks, if anyone else is up for it, please go ahead, otherwise I'll come back to this then 😃

@Primajin
Copy link
Contributor Author

OK finally had a bit of time to get into it. Though target seems way more complicated to wrap my head around than filter.

Drafted #1050 in case you are interested to also allow functions for filter 😄

@Primajin
Copy link
Contributor Author

Mhh ok - started of with the first initial commit but am not very happy yet how far I got before hitting a wall - need your help / hand holding a bit to continue from here 🤔

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

Successfully merging a pull request may close this issue.

2 participants