D

Dependency Upgrade Planner

Plans safe dependency upgrades by checking changelogs, breaking changes, peer dependency conflicts, and suggesting an upgrade order.

SkillClipticsdevelopmentv1.0.0MIT
0 views0 copies

Dependency Upgrade Planner

Plan and execute safe dependency upgrades with risk assessment, breaking change analysis, compatibility verification, and rollback strategies for Node.js, Python, and other ecosystems.

When to Use This Template

Choose Dependency Upgrade Planner when:

  • You have outdated dependencies and need a prioritized upgrade plan
  • A major version upgrade requires breaking change analysis and code modifications
  • Security vulnerabilities require immediate but safe dependency updates
  • You want to batch compatible upgrades to minimize CI runs and risk

Consider alternatives when:

  • You need automated PR creation for dependency updates (use Dependabot or Renovate)
  • You need to audit dependencies for license compliance (use license-checker)
  • You are evaluating new dependencies to add (use bundlephobia or npm-compare)

Quick Start

# .claude/skills/dependency-upgrade-planner.yml name: dependency-upgrade-planner description: Plan safe dependency upgrades with risk analysis prompt: | Analyze the project's dependencies and create an upgrade plan. For each dependency: 1. Current version vs latest version 2. Changelog analysis for breaking changes 3. Risk assessment (low/medium/high) 4. Required code changes 5. Upgrade order (respect peer dependencies) 6. Rollback strategy Group upgrades into safe batches that can be tested independently.

Example invocation:

claude "Create an upgrade plan for all outdated dependencies"

Sample upgrade plan:

Dependency Upgrade Plan
━━━━━━━━━━━━━━━━━━━━━━

Outdated: 23 packages (5 major, 11 minor, 7 patch)
Security: 2 critical, 1 high

Batch 1 — Security Fixes (deploy ASAP)
  axios: 0.21.1 → 1.7.4 [CRITICAL: SSRF vulnerability]
    Breaking: Response.data typing changed
    Code changes: Update 3 files (type imports)
  lodash: 4.17.19 → 4.17.21 [HIGH: Prototype pollution]
    Breaking: None
    Code changes: None required

Batch 2 — Patch Updates (safe, no breaking changes)
  typescript: 5.3.2 → 5.3.3
  eslint: 8.56.0 → 8.57.0
  prettier: 3.2.1 → 3.2.5
  ... (4 more)

Batch 3 — Minor Updates (new features, backwards compatible)
  next: 14.1.0 → 14.2.15
    Note: New caching behavior — test SSR pages
  react-query: 5.17.0 → 5.62.0
    Note: New devtools features

Batch 4 — Major Updates (breaking changes, needs code mods)
  next: 14.2.15 → 15.1.0 [MAJOR]
    Breaking: App Router changes, new Image component API
    Code changes: ~15 files need updating
    Risk: HIGH — thorough testing required

Core Concepts

Risk Assessment Matrix

FactorLow RiskMedium RiskHigh Risk
Version jumpPatch (x.x.1→2)Minor (x.1→2.x)Major (1→2.x.x)
Dependents0-2 files use it3-10 files10+ files or core
Breaking changesNone listedAPI additionsAPI removals/changes
Test coverage> 80% covered50-80% covered< 50% covered
Ecosystem maturity1M+ weekly downloads100K+ downloads< 100K downloads

Upgrade Analysis Script

// analyze-upgrades.js const { execSync } = require('child_process'); function analyzeUpgrades() { // Get outdated packages const outdated = JSON.parse( execSync('npm outdated --json 2>/dev/null || echo "{}"').toString() ); const plan = { security: [], patch: [], minor: [], major: [] }; for (const [name, info] of Object.entries(outdated)) { const current = info.current; const latest = info.latest; const wanted = info.wanted; // Check for security vulnerabilities const auditOutput = execSync( `npm audit --json 2>/dev/null || echo "{}"` ).toString(); const audit = JSON.parse(auditOutput); const hasVulnerability = audit.vulnerabilities?.[name]; // Determine upgrade type const [curMajor, curMinor] = current.split('.').map(Number); const [latMajor, latMinor] = latest.split('.').map(Number); const upgrade = { name, current, latest, wanted, vulnerability: hasVulnerability?.severity || null, type: latMajor > curMajor ? 'major' : latMinor > curMinor ? 'minor' : 'patch' }; if (hasVulnerability) { plan.security.push(upgrade); } else { plan[upgrade.type].push(upgrade); } } return plan; } // Count files that import each dependency function countDependents(packageName) { try { const result = execSync( `grep -rl "from '${packageName}\\|require('${packageName}" src/ --include='*.ts' --include='*.tsx' --include='*.js' | wc -l` ).toString().trim(); return parseInt(result) || 0; } catch { return 0; } }

Safe Upgrade Workflow

# Step 1: Create upgrade branch git checkout -b deps/batch-1-security-fixes # Step 2: Upgrade specific package npm install axios@latest # Step 3: Check for breaking changes npx npm-check-updates --filter axios --format repo # Opens the changelog in the browser # Step 4: Run type check npx tsc --noEmit # Step 5: Run tests npm test # Step 6: If everything passes, commit git add package.json package-lock.json git commit -m "fix: upgrade axios to 1.7.4 (SSRF vulnerability fix)" # Step 7: If something breaks, rollback git checkout -- package.json package-lock.json npm install

Peer Dependency Resolution

// Build upgrade order respecting peer dependencies function buildUpgradeOrder(packages: Package[]): Package[][] { const batches: Package[][] = []; const upgraded = new Set<string>(); while (upgraded.size < packages.length) { const batch: Package[] = []; for (const pkg of packages) { if (upgraded.has(pkg.name)) continue; // Check if all peer dependencies are already upgraded const peersSatisfied = (pkg.peerDependencies || []) .every(peer => upgraded.has(peer) || !packages.find(p => p.name === peer)); if (peersSatisfied) { batch.push(pkg); } } if (batch.length === 0) { // Circular dependency — upgrade remaining together batch.push(...packages.filter(p => !upgraded.has(p.name))); } batch.forEach(p => upgraded.add(p.name)); batches.push(batch); } return batches; }

Configuration

OptionTypeDefaultDescription
includeDevDepsbooleantrueInclude devDependencies in analysis
securityOnlybooleanfalseOnly plan security-related upgrades
maxBatchSizenumber5Maximum packages per upgrade batch
riskThresholdstring"medium"Maximum risk level for auto-upgrade: low, medium, high
lockfileUpdatebooleantrueUpdate lockfile after each batch
testCommandstring"npm test"Command to verify after upgrade

Best Practices

  1. Upgrade security vulnerabilities first and separately — Security patches have the highest urgency and usually the lowest risk (patch versions). Create a dedicated PR for security fixes so they can be reviewed, approved, and deployed quickly without being blocked by unrelated upgrade work.

  2. Batch compatible upgrades together — Group patch updates into a single PR, minor updates into another, and handle each major update individually. This keeps PRs reviewable and makes it easy to identify which upgrade caused a regression if tests fail.

  3. Read changelogs for major upgrades, not just release notes — The npm page shows the latest version's notes, but the migration guide (usually in the repo's MIGRATION.md or UPGRADING.md) covers all breaking changes between your current version and the target. Skipping intermediate breaking changes causes subtle bugs.

  4. Lock exact versions for production dependencies — Use npm install --save-exact or set save-exact=true in .npmrc to prevent unexpected updates when colleagues run npm install. Controlled upgrades are always safer than implicit ones through semver ranges.

  5. Keep a dependency decision log — Document why specific versions are pinned, why certain upgrades are deferred, and what workarounds exist for known issues. This prevents future developers from upgrading a pinned dependency without understanding the constraint, and helps onboarding.

Common Issues

Peer dependency conflicts block installation — Package A requires react@^17 while package B requires react@^18, making both uninstallable. Use npm install --legacy-peer-deps temporarily, then check if package A has a newer version compatible with React 18. If not, file an issue upstream and document the pin in your dependency decision log.

Lockfile conflicts after upgrade — Two developers upgrade different packages on separate branches, causing massive lockfile merge conflicts. Never manually resolve lockfile conflicts. Delete the lockfile, run npm install to regenerate it, then verify the installed versions match expectations. Alternatively, use npm install on the merged branch and commit the regenerated lockfile.

Tests pass locally but fail in CI after upgrade — The CI environment may have a different Node.js version, different OS (Linux vs macOS), or cached node_modules from a previous run. Ensure CI clears caches after dependency upgrades, uses the same Node version specified in .nvmrc or engines, and runs npm ci (clean install) instead of npm install.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates