跳到正文
DEV Community· Renato Rodrigues·· 4 小時前AI 評分59

Renato Rodrigues 如何打造 breaking-changes-analyzer AI 技能,自動化 npm 依賴升級

How I automated npm dependency upgrades with an AI skill

AI 導讀

Renato Rodrigues 把個人 Gemini 帳戶中的摘要 Gem 逐步改造成 breaking-changes-analyzer AI 技能,用來分析 npm 依賴升級中的破壞性變更及專案相容性,並在用戶同意後執行升級。

正文

Upgrading dependencies is one of those chores everyone knows they have to do and almost nobody wants to. Read the changelog, figure out what breaks, check whether it affects your project, adjust the code, run the tests. Repeat for every package.

This post tells how I turned that annoyance into a personal tool and, step by step, into an AI agent skill that now does the job end to end: breaking-changes-analyzer.

The goal here is not to teach you how to use the skill (the README does that), but to show the thought process that led to it.

Each step was born from a limitation of the previous one.

The inspiration: prompts saved as Gems

On my personal Gemini account I keep several pre-saved prompts as Gems: one to translate and help me fill in documents, another to check my grammar and adjust the tone to the context, another to summarize long articles and point out the key takeaways.

They are small tools, each built for a recurring task. And that's where the idea came from.

The motivation: breaking changes, over and over

In my day-to-day work I constantly upgrade dependency versions, and with every upgrade I have to check for breaking changes. It's repetitive work with a predictable shape: read a long text and extract only what matters.

That was exactly what my article-summarizing Gem already did.

The first tool: a Gem

Starting from the summarizer Gem, I built another one that took two versions of a dependency, read both changelogs and pointed out the breaking changes between them. The report had this structure:

  • package name and compared versions;
  • breaking changes, grouped;
  • important (non-breaking) changes;
  • new features.

At first it worked well. I got a lean report with only what was relevant. But two problems became obvious:

  1. It couldn't see my project. Without access to my files and environment, there was no way to tell whether a breaking change was actually a breaking change for me. The classic example: "dropped support for Node 18" means nothing if your project already runs on Node 24.
  2. It was an isolated web tool. It didn't run in my IDE and didn't talk to my agents.

The first skill: getting access to the project

Both problems pointed to the same solution: bring the tool into the development environment.

I started converting the Gem into a skill, and the conversion brought features the web version could never have:

  • reading the dependency's current version straight from package.json, so I don't have to provide it;
  • cross-checking the upgrade against what the project declares (engines, peer dependencies, other tools that cap the package version) and flagging real compatibility blockers;
  • saving the report to disk.

Usage ended up like this:

# From the package.json version to the latest on npm
/breaking-changes-analyzer chalk

# Between two specific versions
/breaking-changes-analyzer chalk 4.1.2 5.3.0

Monorepos: where the problem gets interesting

With access to the project's manifests, a new need showed up: handling regular repositories and monorepos.

Picture the scenario. You ask the skill to check an upgrade for a dependency, but it exists in several monorepo packages, including the root one. Which ones should it check? All of them? What's the minimum version to consider? And the maximum? Can the same maximum be used in every package, or do each package's requirements (Node version, ESM only, etc.) call for different versions? And how do you display all of that: grouped or not?

After weighing the options, I settled on a semi-grouped report: information common to all packages is grouped into a single section, and smaller sections highlight the packages whose minimum or maximum versions differ from the common ones.

It was already better, but there was still a long way to go.

The upgrade plan

If the skill already knew what the breaking changes were, and already knew my project's versions and constraints, why not ask it to write an upgrade plan?

I wrote that part and also asked it to look for migration guides and any official documentation about the migration, beyond the changelogs.

It was a good idea, but the result was still just a report (and the analysis remains strictly read-only: nothing was modified). I still had to carry everything out myself.

From analysis to execution

By then the next step seemed obvious. After showing the plan, the skill asks whether you want it to carry it out itself.

Say yes, and it updates the manifests, installs the dependencies, applies the migration plan and runs the project's typecheck, lint and tests to make sure everything still works. In a few minutes. It never commits or pushes: that stays up to you.

So there are two clearly separate stages: analysis (read-only) and upgrade (only after your "yes").

Widening the scope: the dependency's ecosystem

Execution worked well, but there was a gap. Many dependencies belong to an ecosystem (plugins, presets, companion dependencies), and the skill only upgraded the main dependency.

I taught the skill that, whenever it upgrades a dependency, it should consult its knowledge base to find out which other dependencies belong to the same ecosystem and upgrade them to the highest compatible version with the package being upgraded.

Side effect: the cooldown period

Widening the scope caused an unexpected problem. The skill started trying to install versions that were still inside the cooldown period configured in .npmrc (the minimum release age policy that protects against freshly published versions), and the install failed.

The fix was to respect that setting:

  • for related dependencies, the skill always respects the cooldown;
  • for the main dependency, if the requested version is still inside the period, it asks whether you want to continue.

The leftovers: cleaning up what's left behind

Once the plan is executed (that is, only if you answered "yes" in the previous stage), almost everything was perfect. Almost. Leftovers from the old version remained: unused config files, residual settings, dependencies that were no longer needed, references to old procedures.

On top of that, the usage of the new version didn't always take the best advantage of what it offers.

So I added one more step: a post-migration audit that looks for those leftovers (and improvement opportunities in the new version), always pointing to the file where each one was found, and asks which of them you want to apply. Only what you choose is applied, followed by another round of tests.

A report is generated at the end, regardless of your answer to the plan.

The complete cycle

Looking back, today's skill does the following, in this order.

Stage 1, analysis (read-only):

  1. finds the current version (in monorepos there can be more than one) and the target version;
  2. reads changelogs, releases and migration guides;
  3. flags the breaking changes and compatibility blockers that matter to your project;
  4. writes the upgrade plan.

Stage 2, upgrade, only if you answer "yes" to the plan:

  1. executes the plan and runs the tests;
  2. audits the leftovers and suggests improvements, applying only what you choose.

At the end, in any case, you get the report.

To install:

npx skills add rerodrigues/breaking-changes-analyzer

The future: planner and executor

The skill works far beyond what I imagined when I started, and that made me think of something else: what if I split it in two?

One would analyze and generate the report (the planner). The other would read that report as input and execute the upgrade (the executor). It would be a cleaner separation of responsibilities.

For now it remains an idea for the future, and everything stays in a single skill.

Conclusion

It all started with a prompt saved in a Gem. Each limitation I found became the next step: lack of access to the project led to the skill, the monorepo led to the semi-grouped report, the report led to the plan, the plan led to execution, and execution led to cleanup.

If there's a lesson here, it's that a very small personal tool can grow a lot if you keep asking "what if it also did X?", as long as every step solves a real problem you felt.

Your turn

Now I want to hear from you:

  • How do you manage dependency upgrades? Dependabot, Renovate, everything by hand, a fixed day of the week, or only when something breaks?
  • What's the worst breaking change you've ever faced?
  • What would you like a tool like this to do that it doesn't do yet?

Tell me in the comments. One of those answers might become the skill's next step.

And if you want to go beyond the conversation:

  • Try it. Installation takes one command, and the analysis is read-only, so there's no risk of touching your project before you approve anything:
  npx skills add rerodrigues/breaking-changes-analyzer
  • Contribute. Found a bug, a monorepo case that doesn't work, or have an idea (maybe the planner/executor split)? Open an issue or a pull request on the repository. And if the skill saved you a few hours, a star helps other people find it.

來源:DEV Community · dev.to