agentleFS
reddygopalkrishnareddygopalkrishna/developer-agent-skills/skills/dependency-upgrades/SKILL.md

dependency-upgrades

Skill8 starsChanged 9 days agoMITView on GitHub

Upgrades libraries, frameworks and toolchains safely - inventory outdated and vulnerable packages, read changelogs and migration guides, upgrade one major version at a time, regenerate and review lockfiles, test, and keep a one-commit rollback. Use when bumping dependencies, fixing security advisories or Dependabot and Renovate PRs, resolving version conflicts or peer dependency errors, or upgrading a framework, SDK or runtime version. Not for moving to a different framework or language (use large-scale-migrations).

  • Installs packages

3 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

6 rules. 0 are common, 4 are distinctive, and 2 are very specific to this project.

  • 0

    Common

    Most of the 3 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Not for: replacing one framework with another (large-scale-migrations) or database schema changes (database-migrations).

    line 19
  2. Distinctive:

    Not every package follows semver: Read the changelog even for minors.

    line 46
  3. Very specific:

    Python: no enforced semver. Applications pin exact versions via a lockfile.

    line 47
  4. Very specific:

    Peer dependencies and coupled packages: must move together (e.g. react and react-dom.

    line 49
  5. Distinctive:

    Prefer upgrading the parent that pulls it in.

    line 62
  6. Distinctive:

    Every override is debt: Add a comment with the reason, the advisory or issue link, and the condition for removing it.

    line 64

“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Dependency Upgrades

Upgrade in small, reversible, tested steps: one major version of one dependency (or one tightly coupled group) per change, with its changelog read and the lockfile regenerated by the package manager and committed.

When to use

  • Routine updates, or reviewing a Dependabot / Renovate PR.
  • A security advisory or audit finding needs fixing.
  • A major version upgrade of a framework or library (React, Spring Boot, Django, Angular, EF Core, ...).
  • A runtime or toolchain upgrade (Node, Python, Java, .NET SDK, Go, Rust).
  • Version conflicts, peer dependency errors, or duplicate versions in the tree.

Not for: replacing one framework with another (large-scale-migrations) or database schema changes (database-migrations).

Workflow

  1. Detect the package manager from the lockfile and use only that one: package-lock.json (npm), pnpm-lock.yaml (pnpm), yarn.lock (Yarn), uv.lock (uv), poetry.lock (Poetry), requirements*.txt (pip / pip-tools), go.sum (Go), pom.xml (Maven), build.gradle(.kts) / libs.versions.toml (Gradle), *.csproj / Directory.Packages.props / packages.lock.json (NuGet), Cargo.lock (Cargo). Never run npm in a pnpm repo or pip in a uv repo.
  2. Start from a clean, green baseline. Clean working tree, a new branch, tests passing before any change. If tests already fail, record which ones so you do not blame the upgrade.
  3. Inventory. List outdated and vulnerable packages with the commands in references/ecosystem-commands.md. Classify each: patch, minor, major, security fix, runtime/toolchain.
  4. Prioritize:

    PriorityWhatWhy
    1Security fixes for reachable, exploitable vulnerabilitiesReal risk now
    2Runtime or framework versions at or near end of lifeSecurity support is ending
    3Majors that block other upgradesUnblocks the rest
    4Minor and patch updates, batchedLow risk, keeps drift small
  5. Read before you bump. For each major, read the release notes and migration guide for every major between the current and target version. Note breaking changes, removed APIs, changed defaults, new minimum runtime versions, and peer dependency changes. Search the codebase for every removed or changed API.
  6. Upgrade one major at a time. If going from v3 to v5, do v3 to v4, build and test, then v4 to v5, unless the project's guide says to jump directly. Use official upgrade tooling when it exists (for example ng update, npx @next/codemod, OpenRewrite recipes for Spring Boot and Java).
  7. Let the package manager write the lockfile, then review the lockfile diff: unexpected new packages, unexpected major jumps in transitive dependencies, changed registry URLs or integrity hashes for packages you did not touch.
  8. Verify: build, type check, lint, run the full test suite, start the app and smoke-test the main flows. Read the build and test output for new deprecation warnings.
  9. Commit one logical upgrade per commit, with the message stating from -> to versions and linking the changelog. In the PR, list breaking changes handled, risk, and test evidence.
  10. Rollback is reverting that commit (manifest and lockfile together). For deployed services, make sure the previous build artifact can be redeployed.

Semver caveats

  • 0.x versions: any minor bump may break. ^0.2.3 allows only <0.3.0.
  • Range syntax (npm-style): ^1.2.3 allows <2.0.0; ~1.2.3 allows <1.3.0.
  • Not every package follows semver. Read the changelog even for minors.
  • Python: no enforced semver. Applications pin exact versions via a lockfile; libraries declare ranges (>=2.1,<3, or ~=2.1).
  • Go: a v2+ major changes the import path (example.com/mod/v2), so a major bump means editing imports.
  • Peer dependencies and coupled packages must move together (e.g. react and react-dom; all @angular/*; a plugin and its host).
  • BOMs and platforms: with Spring Boot, a Maven BOM, a Gradle platform, or .NET central package management, upgrade the managing version, not individual managed artifacts.
  • Applications vs libraries: applications commit lockfiles and pin; libraries keep ranges wide and test against both the lowest and highest supported versions.

Security advisories

  1. Triage each finding: Is the vulnerable code reachable from this project? Is the package used only in development or build tooling? What is the severity and is there a known exploit? govulncheck reports reachability for Go; most other scanners do not, so check usage yourself.
  2. Fix in this order: upgrade the direct dependency, then upgrade the parent of a transitive dependency, then force the patched version with an override, then patch or fork, and only as a last resort document an accepted risk with an expiry date and owner.
  3. Never run npm audit fix --force blindly. It can install breaking major versions. Use plain npm audit fix and handle the rest manually.

Transitive dependencies and overrides

  • First find why a package is in the tree (commands in the reference file: npm explain, pnpm why, yarn why, uv tree, go mod why -m, mvn dependency:tree, gradle dependencyInsight, dotnet list package --include-transitive, cargo tree -i).
  • Prefer upgrading the parent that pulls it in.
  • If you must force a version, use the ecosystem's mechanism: npm overrides, pnpm overrides, Yarn resolutions, Maven <dependencyManagement>, Gradle dependency constraints, Go require of a higher version (or replace for forks), a direct PackageReference or transitive pinning with NuGet central package management, Cargo [patch], uv override-dependencies, pip constraints files (pip install -c constraints.txt).
  • Every override is debt. Add a comment with the reason, the advisory or issue link, and the condition for removing it.

Test plan by risk

ChangeMinimum verification
Patch updatesCI green
Minor updatesCI green plus a smoke test of the app
Major library updateCI plus targeted tests of every feature using the changed APIs
Framework, ORM, auth, crypto, serialization, or HTTP client majorAbove plus staging deploy and a regression pass of critical flows
Runtime or SDK upgradeAbove plus performance check and container/base image update

Watch for changes compilers do not catch: changed defaults (timeouts, strict modes, date and time zone handling, JSON casing, null handling), different generated SQL from an ORM, and stricter TLS or certificate validation.

Runtime and toolchain versions

Update every place the version is declared, in the same change: .nvmrc / .node-version / engines in package.json, .python-version / requires-python, the go directive in go.mod, global.json for the .NET SDK, rust-toolchain.toml, Maven compiler release or Gradle toolchains, CI workflow versions, and Dockerfile base images. Never combine a runtime upgrade with library majors in one PR.

Automation

  • Configure Renovate or Dependabot to group minor and patch updates, keep each major separate, and run on a schedule.
  • Enabling auto-merge or adding a new bot configuration is a persistent change: ask the user first. Recommend auto-merge only for patch updates on repos with strong test coverage.

PR description template

Upgrade <package> <from> -> <to>

Why: <security advisory ID / end of life / unblocks X / routine>
Release notes: <links for every major crossed>

Breaking changes handled:
- <change> -> <what was done in this PR>

Not affected (checked): <APIs or features reviewed and unchanged>
Testing: <CI, smoke test steps, staging results>
Risk and rollback: <risk level>; revert this PR to roll back.

Anti-patterns

  • "Bump everything" in one PR — when something breaks, nobody knows which upgrade did it.
  • Deleting the lockfile to fix a conflict — silently upgrades hundreds of transitive packages.
  • --force or --legacy-peer-deps to silence errors without understanding the conflict.
  • Skipping intermediate migration guides — breaking changes from the skipped majors still apply.
  • Ignoring deprecation warnings — they are next year's breaking changes.
  • Overrides with no comment — nobody knows when they can be removed.
  • Mixing package managers — produces two lockfiles that disagree.
  • Trusting green CI with thin tests — add a smoke test of the changed area first.

Done when

  • The lockfile was regenerated by the package manager and its diff reviewed.
  • Build, type check, lint and tests pass; new deprecation warnings are fixed or listed in the PR.
  • Targeted advisories no longer appear in the audit output.
  • Each commit states from -> to versions and links the release notes.
  • Any override has a comment explaining why and when to remove it.
  • Rolling back is a single revert.

References

  • references/ecosystem-commands.md — read when you need the exact outdated, audit, upgrade, "why is this installed" or override command for npm, pnpm, Yarn, pip, uv, Poetry, Go, Maven, Gradle, NuGet or Cargo.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.