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

feat: script to check major dependency updates #837

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

scscgit
Copy link
Contributor

@scscgit scscgit commented Aug 1, 2021

Developers currently don't have any recommended means of updating major versions of dependencies, because the "official" commands like npm update only function with varying limitations and within the scope of semantic versioning. I'm currently aware of https://www.npmjs.com/package/npm-check-updates being a de-facto standard to perform this kind of routine maintenance, so I'd suggest for Nuxt to make a consensus decision if this is a correct default approach for new Nuxt developers or not, because we need to acknowledge how developers are currently forced to accept a workaround like this. In the best case scenario, we'd be able to suggest a better alternative without resorting to a third party library.

As with everything, there are definite reasons why we shouldn't ambiguously leave this setup to be arbitrarily done by the developers, including but not limited to enforcing best practices; for example:

  • they may often install it globally, and then lose a track of which version of updater is installed while forgetting to update it,
  • each project will document these steps for maintainers in their own way, choosing between installing it in devDependencies, suggesting a global installation, naively using npx without --no-install without knowing which version is being used, or not documenting it at all, assuming that everyone will figure out some way on their own (which usually means just using npm update or manually checking registries, and then having projects get outdated with a lack of any automation),
  • when developers use different environments/OSes, they may not predict the issues that others will suffer from; for example the --packageFile package.json based on Incorrectly waits for stdin raineorshine/npm-check-updates#136 (comment) (https://github.com/raineorshine/npm-check-updates#known-issues) may be required depending on the used terminal (Git Bash on Windows); and it's easier to keep track of which workarounds are still needed if a generator tracks them,
  • it improves developer experience if the yarn | npm install is included as part of the command in a correct order, so that we don't have to double-check anything.

There is one more unintuitive matter regarding the lock file, as I couldn't find a way to force npm to update all the transitive dependencies without literally deleting the entire node_modues with around 100k files together with the package-lock.json before running npm install, otherwise it just found and re-used the obsolete dependencies as a successful semver match. Not only have users no way of figuring out that this is the default behavior, but there is also no direct solution, because deleting this directory takes an enormous amount of time (even on SSD), and it's also cumbersome to define a deletion script as portable between OSes. There's even a suggested hack of actually moving the directory to some other (temp) directory first before attempting to delete it, so that you don't have to wait so long before you start the re-installation.

As a postfix, I've included another script that updates browserslist, which seems to be a best practice based on browserslist/browserslist#492. In addition, this place may be useful in the future for other libraries that also include their own update scripts; for example, && openapi-generator-cli version-manager set latest

One of advantages for keeping the update:check as a separate script, on top of CI automation, is that users can also use it as a source of truth for any exclusions. For example, -x vue-trumbowyg would be required because this wrapper uses Vue 3 on the latest version. Because it may not be obvious at a first glance that this -x is even supported, it'd be preferable if we could document it as part of best practices for updating libraries; or if we could at least put there some placeholder. For now I'm omitting this until everyone agrees.

Also note that npx is extremely slow and always re-installs the dependency (though it may not be an issue in latest versions), so it'd be reasonable to instead suggest installing & locking this as part of devDependencies. At the moment I think it's worth the cost, because we don't run these scripts on a daily basis.

@pi0
Copy link
Member

pi0 commented Aug 3, 2021

Thanks for PR and explanation @scscgit. I think it is nice to use npm-check-updates for npm users. For yarn, we have a built-in yarn outdated command and yarn upgrade-interactive which is probably safer when it comes to updating major version of several dependencies.

Also as a best practice, users should use a system like https://dependabot.com/ or https://github.com/renovatebot/renovate that can handle most of these challenges for lock-file maintenance, separating major dependency upgrades from the rest with a nice interface.

PS: I will also make sure new nuxt3 CLI (usable for nuxt2) will have some built-ins too so we don't need to make use of several packages and having a robust upgrade syustem.

@scscgit
Copy link
Contributor Author

scscgit commented Aug 4, 2021

Thanks @pi0, yeah I don't have experience with yarn's upgrade-interactive, so it may be a better option for projects that select yarn if it satisfies all the updating needs. I'm looking forward to the new Nuxt CLI options; hopefully they'll even replace npm-check-updates as a standalone tool that'll become a top recommendation in all search results, becoming a new de-facto standard :)

When it comes to dependabot and renovatebot, sadly these can't be used standalone, for example if we work on private / company projects that can't integrate with receiving public PRs. There may be also a few opinionated reasons why someone wouldn't agree with their workflow, preferring to have more control over their infrastructure; so even though the trend looks nice, we're still very dependent on these specific companies matching our needs, and needless to say, it steepens our learning curve.

@pi0
Copy link
Member

pi0 commented Aug 9, 2021

When it comes to dependabot and renovatebot, sadly these can't be used standalone, for example if we work on private / company projects that can't integrate with receiving public PRs.

Renovate bot is opensource and can be self-hosted in your own infra: https://docs.renovatebot.com/self-hosting/ and also have a standalone npm cli that we can potentially use as a unified option.

BTW I agree there might be opinionated reasons to use npm or yarn directly for managing dependencies and doing something like this PR. Maybe we can add an option in devtools prompt to enable?

/cc @rarkins Kindly if you have some thoughts to add :)

@scscgit
Copy link
Contributor Author

scscgit commented Aug 9, 2021

Yeah it'd be a good idea to move these scripts under a devTools option unless they match a use-case that's preferred for all projects (e.g. if a workaround is needed for any contributor to easily check or test new versions locally). Feel free to choose the specific string message contents, together with the yarn or renovate CLI variants, and I'll update the PR for a first iteration. There are too many options with various downsides, so it'll be great to converge on a consensus that matches everyone's intentions in the form of a standalone tool. (We don't want to put users in impossible situations like how npm often does it by default.)

@rarkins
Copy link

rarkins commented Aug 10, 2021

Something very simple you can do is install Renovate with dependencyDashboardApproval: true in settings. It will then do nothing but create a "Dependency Dashboard" issue which lists all the available updates, with a checkbox next to each. No PRs will be created by default. Example of how it looks: renovatebot/renovate#2958

From experience I'd say that in general:

  • If it isn't automated then it gets forgotten
  • If it's out of sight (including Dependency Dashboard for some) then it can become "out of mind" and forgotten too
  • Scripts without automation may be more out of sight than sight than a pinned dashboard issue

Something else we do is address upgrade hesitancy by providing "Merge Confidence" with PRs. We're looking at how to incorporate those into the Dashboard too, so that you can see if the upgrade is unlikely to break anything before you tick the checkbox to request the PR be created.

@clarkdo
Copy link
Member

clarkdo commented Nov 18, 2021

Close this as we're using Dependency Dashboard now

@clarkdo clarkdo closed this Nov 18, 2021
@scscgit
Copy link
Contributor Author

scscgit commented Nov 26, 2021

@clarkdo Are you sure we don't want to provide users with the option of standalone updates, at least for npm (e.g. as a devTools option if not automatically) where it requires a hacky solution that Nuxt users have absolutely no way of figuring out by themselves? I think you're referring to PR #848 with the Dependency Dashboard, but that is a PR against create-nuxt-app's own configuration, whereas my PR is for a code generated for new projects. Also as far as I know, the Dependency Dashboard isn't set up for generated projects by default either.

@clarkdo
Copy link
Member

clarkdo commented Nov 26, 2021

Sorry for the misunderstanding.

I’ve reopened the pr, but I still want to hear more thoughts from other team members @nuxt/framework, this change looks good, but I’m not sure if it’s far away from the original intention of the generated project, it’s a useful script, but it’s kind of out of nuxt scope, we may avoid introducing too many nuxt irrelevant features. Actually I’m thinking if current crate-nuxt-app is having too many options, maybe we should refactor and focus on nuxt core functionality and ecosystem in future.

@clarkdo clarkdo reopened this Nov 26, 2021
@scscgit
Copy link
Contributor Author

scscgit commented Apr 10, 2022

we may avoid introducing too many nuxt irrelevant features

I understand the sentiment, but to reinforce some motivation anyway, I'm still hoping we'll continue on the same trajectory and focus on DX in general in a near future rather than closing our eyes in front of some blatantly obvious problems that everyone experiences, because there don't seem to be any other projects with a more holistic focus. Nuxt's approach of offering a opinionated zero-config setup that "just works" is a dream come true, so with a growing technological complexity (and laziness of library maintainers), it's vital for the sake of our efficiency that someone keeps taking on this responsibility (even if only for a subset of combinations, e.g. I'd understand if we explicitly deprecated npm fixes at some point) :) It goes a long way if we at least keep a neutral stance and accept features that have "negligible risks of supporting effort", its mindset will have consequences in the following years. One of our sins as devs is that we often feel like a problem is just temporary, yet in the end never solve it despite users eagerly waiting every day. (It especially means not documenting the scope of what will be added.) For example, it's worth adding update scripts even if we plan to introduce a new CLI tool later, because even then we may find excuses to postpone adding it for different reasons.

Some additional optional reading

In my opinion, this opinionated approach should be driven by Nuxt core developers who embody these (library-transitive) concerns and likely already relate to them as part of their own workflow (they would crystallize their own paths of least resistance as a default for others who lack a contrary opinion). I assume you all have a lot more opinions than what has been documented & automated. In other words, it feels like they just don't create and maintain any Nuxt projects themselves if they don't recognize this as an annoyance. (After all, as a simple repro, you just create a private project using npm outside GitHub and try to check if there are any updates.) I'd suggest to redefine the scope of this project to generally cover best practices of an expected workflow of Nuxt developers, and to subsequently enforce the coverage (at least in docs) of at least one hot-path (instead of claiming something is common sense when it isn't). I doubt there is any disagreement between core devs about whether the maintenance of dependencies is an absolute necessity from a security perspective, yet we expect everyone to learn [the npm workarounds of] how to do it by themselves. I completely understand when someone believes that the scenario never occurs if we use a "correct" combination of dependencies, it's just that this doesn't seem to be that case. We're prone to a choice paralysis if there are too many options, so maybe we'd save the effort by just suggesting to use yarn for correct reasons (instead of just because "it is the development tool which tests have been written against."). Since its inception, npm has always been infamous for being difficult to use "correctly" until getting used to its workarounds, so we just all eventually ended up on the same StackOverflow pages.

Looking forward in time, I primarily argue that it's unsustainable to expect developers to "never get behind" and always preemptively & periodically research whether their workflow is "still acceptable". In my case, for example, I've painstakingly caught up with the information gathered here, which is more than what a typical user will have time to find, yet even I lack both the confidence and time to cross-check everything again in future, resulting in being forced to make my workarounds a permanent part of projects I work on, without any feedback.

  • For me, integrating any workflow automation lessens my cognitive load by a great margin, as it's possible to "inherit" any changes whenever Nuxt decides that something else is a new best practice, and I don't have to worry about forgetting the workaround either. From a security or stability perspective, it makes a difference if a large framework "certifies" that it has been tested for years. When a compatibility issue occurs, instead of fixing projects ad-hoc, there is always a place to integrate the change upstream and have it reviewed collectively. (Also it may not be completely out of scope for a generator to specify Nuxt compatibility whitelist or blacklist).
  • After spending hundreds of hours on workarounds and testing them for months, one should be able to empathize with new frontend developers who decide to start with Nuxt. Not only will they have to reinvent the wheel, with a guarantee that it will take them even longer time (concurrent workarounds compound, increasing debugging effort exponentially), but because they'll make mistakes, after a growth of confidence, they may even spread inferior solutions, harming both their projects, peers, and subsequently frameworks that build around their use-cases. It's better to systematically track these routines somewhere.
  • Last but not least, if other frameworks neglect to take an "all-inclusive" care of their users, it gives more space for Nuxt to fill this void and become even more beginner-friendly. (I'd really like to see the generated code become a self-documenting source of truth even for other Vue-related features/libraries.)

That said, the responsibility to setup any tools and scripts unrelated to Nuxt could be definitely delegated to a separate scaffolding project and used as a dependency instead.

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.

None yet

4 participants