|
| 1 | +--- |
| 2 | +description: Perform non-breaking (patch and minor) devDependency updates as a single batched group, then build, test, and create one signed commit |
| 3 | +args: `[scope: all | <package-name>]` |
| 4 | +--- |
| 5 | + |
| 6 | +You are performing **non-breaking** version updates of devDependencies in this monorepo — everything below the next major (patch and minor). Because semver promises these are backward-compatible, you apply them **together as a single batch**, build, test, and — only when green — create **one** signed commit. You **never push**; the user pushes themselves. |
| 7 | + |
| 8 | +For **major** (breaking) updates, use `/update-major-deps` instead — that skill isolates each group with its own risk assessment and commit. |
| 9 | + |
| 10 | +**Input** |
| 11 | + |
| 12 | +- No args, or `all` → update every devDependency to its latest patch/minor. |
| 13 | +- `<package-name>` → update only that package to its latest patch/minor. |
| 14 | + |
| 15 | +**Core principles** |
| 16 | + |
| 17 | +- **One batch, one commit.** Non-breaking updates don't need bisect isolation; a single commit keeps history clean. |
| 18 | +- **Tests are the gate.** Semver-minor is _supposed_ to be safe, but deprecations and bugs slip through — never commit a batch whose build or tests fail. |
| 19 | +- **Commit-only.** Never `git push`. Never use `--no-verify` or otherwise bypass hooks. |
| 20 | +- **Lock-preserving.** Never clean-nuke the lockfile to work around an install problem. |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +**Process** |
| 25 | + |
| 26 | +**1. Preflight** |
| 27 | + |
| 28 | +- Confirm the working tree is clean (`git status --short`). If not, stop and report — do not mix unrelated changes into the dependency commit. |
| 29 | +- Confirm Node/npm are available (`node -v`, `npm -v`). This repo uses Node 22 via nvm; if `npm` is missing, the terminal likely hasn't loaded nvm (`source ~/.zshrc`). |
| 30 | +- Note the current branch. |
| 31 | + |
| 32 | +**2. Detect available patch/minor updates** |
| 33 | + |
| 34 | +Run a dry check scoped to non-breaking versions: |
| 35 | + |
| 36 | +``` |
| 37 | +npx --yes npm-check-updates --dep dev --target minor |
| 38 | +``` |
| 39 | + |
| 40 | +`--target minor` reports the highest patch/minor for each dependency while holding the major fixed. List what will move so the user can see the batch. |
| 41 | + |
| 42 | +**3. Apply the batch** |
| 43 | + |
| 44 | +Bump the ranges and install in one pass: |
| 45 | + |
| 46 | +``` |
| 47 | +npx --yes npm-check-updates -u --dep dev --target minor |
| 48 | +npm install |
| 49 | +``` |
| 50 | + |
| 51 | +For a single-package scope, restrict it: `npx --yes npm-check-updates -u --dep dev --target minor <package-name>`. |
| 52 | + |
| 53 | +Keep the lockfile in place — `npm install` updates it incrementally. Do **not** `rm -rf node_modules package-lock.json`; a lockfile-free resolve can float unrelated deps to a version your registry/security proxy blocks. |
| 54 | + |
| 55 | +**4. Handle a blocked or platform-rejected version** |
| 56 | + |
| 57 | +A patch/minor bump can still land on a release the registry refuses (e.g. a `403 Forbidden` on `prettier@3.9.0` even though `3.8.4` was fine), or one that fails an engine/platform check. These blocks are typically a **corporate supply-chain policy** (e.g. Netskope enforcing an approved-version allowlist), not a network or certificate fault — the symptom is a clean HTTP `403` with a policy message, not a TLS error. A new CA cert will **not** fix it. |
| 58 | + |
| 59 | +Crucially, the block is usually **version-specific**, so don't assume you must abandon the update. If `npm install` errors with a `403`: |
| 60 | + |
| 61 | +- Identify the offending package and version from the error. |
| 62 | +- **Check whether a higher version is approved before giving up.** The blocked version is often an unvetted intermediate while the current `latest` is allowed. Probe without installing: |
| 63 | + |
| 64 | + ``` |
| 65 | + npm view <pkg> dist-tags # find latest |
| 66 | + cd /tmp && npm pack <pkg>@<ver> # 403 = blocked; downloads = approved |
| 67 | + ``` |
| 68 | + |
| 69 | + If a higher approved version exists, target it explicitly (e.g. `^3.9.3`) and re-run `npm install`. |
| 70 | + |
| 71 | +- Only if **no** approved version in range exists: pin the package back to the last known-good version (exclude it from the batch), re-run `npm install`, and note the exclusion in your report for follow-up (request approval through the org's package-vetting process). |
| 72 | + |
| 73 | +Do **not** force past a policy block with `--force`, a clean reinstall, or by stripping auth/routing around the proxy — that bypasses a security control. |
| 74 | + |
| 75 | +**5. Build and test** |
| 76 | + |
| 77 | +``` |
| 78 | +npm run build |
| 79 | +npm test |
| 80 | +``` |
| 81 | + |
| 82 | +- **Green** → continue to commit. |
| 83 | +- **Red** → stop. Report the failure and leave the changes in the working tree for inspection; do **not** commit. A minor-version regression usually points to one package — bisect by reverting that single bump, not the whole batch. |
| 84 | + |
| 85 | +**6. Commit (signed, commit-only)** |
| 86 | + |
| 87 | +Stage exactly what changed: `package.json`, `package-lock.json`, and any legitimately regenerated build artifacts (a `@babel/*` patch can regenerate `docs/**/*.min.js(.map)` and `packages/**/dist/cjs/index.js`). Review with `git status --short` first, stage explicit paths, and **never** `git add -A` (it would sweep in unrelated working-tree files such as `.claude/` or `CLAUDE.md`). |
| 88 | + |
| 89 | +Use a single Conventional Commits message (the repo enforces commitlint + a husky `commit-msg` hook): |
| 90 | + |
| 91 | +``` |
| 92 | +build(deps-dev): bump patch and minor versions |
| 93 | +``` |
| 94 | + |
| 95 | +Commits are GPG-signed automatically (`commit.gpgsign=true`). Verify with: |
| 96 | + |
| 97 | +``` |
| 98 | +git log -1 --format='%h %G? %an <%ae>' |
| 99 | +``` |
| 100 | + |
| 101 | +`%G?` should print `G` (good signature). **Do not push.** |
| 102 | + |
| 103 | +**7. Report** |
| 104 | + |
| 105 | +Summarize the batch — what was bumped, anything excluded (and why), and the resulting commit: |
| 106 | + |
| 107 | +| Package | Old | New | |
| 108 | +| ------- | ------- | ------- | |
| 109 | +| `<pkg>` | `<old>` | `<new>` | |
| 110 | + |
| 111 | +Note any packages held back (blocked version, engine/platform mismatch, or test failure) and recommend follow-up. |
| 112 | + |
| 113 | +--- |
| 114 | + |
| 115 | +**Safety reminders** |
| 116 | + |
| 117 | +- Never `git push`. |
| 118 | +- Never bypass hooks (`--no-verify`) or force anything. |
| 119 | +- Never clean-nuke the lockfile to resolve an install error — prefer pinning the offending package back and re-running. |
| 120 | +- If the working tree starts dirty or a build/test fails, stop rather than working around it. |
| 121 | +- Reach for `/update-major-deps` the moment a change crosses a major boundary. |
0 commit comments