Installs into .claude/skills of the current project.
Are you the author of Infra Deps Update?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kamiletar-infra-deps-update)
---
name: infra-deps-update
description: Систематическое обновление зависимостей монорепо через bun с проверкой безопасности и сборки
allowed-tools: Bash(bun outdated:*), Bash(bun update:*), Bash(bun add:*), Bash(bun audit:*), Bash(bun install:*), Bash(bun scripts/check-all.mjs:*), Bash(bun scripts/check-peer-deps.mjs:*), Bash(bun scripts/check-patched-deps.mjs:*), Bash(bun patch:*), Bash(nx run-many:*)
disable-model-invocation: true
---
# Deps Update - Обновление зависимостей
Обнови зависимости проекта безопасно и систематически.
## Когда использовать
- Регулярное обновление (раз в неделю/месяц)
- Критичное обновление безопасности
- Новая major версия важного пакета
## Шаги
### 1. Проверка устаревших пакетов
```bash
bun outdated
```
### 2. Обновление по группам
**Безопасные обновления (patch):**
```bash
bun update
```
**Minor обновления:**
```bash
bun update --latest
```
**Major обновления (осторожно!):**
```bash
bun add <package>@latest
```
### 3. Приоритет обновлений
1. **Критичные (безопасность)**
- `bun audit` для проверки
- Обновить немедленно
2. **Фреймворки**
- Next.js, React, Chakra UI
- Проверить changelog на breaking changes
3. **Инструменты разработки**
- ESLint, TypeScript, Vitest
- Обычно безопасны
4. **Остальные**
- По необходимости
### 4. После обновления
```bash
# Пересобрать
bun install
# Проверки целостности: патчи зависимостей, peer-диапазоны, намеренные пины,
# дрейф electron
bun scripts/check-all.mjs --group=deps
# Проверить типы
nx run-many -t typecheck:tsgo
# Запустить тесты
nx run-many -t test
# Проверить сборку
nx run-many -t build
```
С 2026-08-28 эти проверки запускаются **сами** — ручной прогон остался как
способ увидеть результат раньше и подробнее, а не как единственная точка входа:
- **pre-commit** (`scripts/hooks/pre-commit-deps-integrity.sh`) — `patched-deps`,
`peer-deps` и `intentional-pins`, но **только** если в staged-наборе есть `bun.lock` или
`package.json`. Обычный коммит по коду не платит ничего (~0.13 с на проверку
индекса), коммит с bump'ом — ~0.3 с. Обход для заведомо ломающего
промежуточного коммита: `GIT_SKIP_DEPS_INTEGRITY=1 git commit ...`
- **CI** (шаг `Integrity checks` в `.github/workflows/ci.yml`) — `bun
scripts/check-all.mjs --ci`, весь набор кроме того, чему нужны приватные
submodule.
⚠️ **Автозапуск не отменяет чтение вывода глазами — по двум причинам.**
Во-первых, `peer-deps` завершается кодом 0 **всегда**: ни хук, ни CI на нём
упасть не могут по построению, смотреть на список обязан человек (см. ниже).
Во-вторых, в CI часть проверок видит не весь репозиторий: приватные submodule
там намеренно не выкачиваются, поэтому `electron-drift` не проверяет
`poster-microtext-desktop`, а `lib-subpath-paths` — tsconfig приватных
приложений. Раннер объявляет это строкой «неполное покрытие» в логе, но зелёный
CI на этих двух проверках означает «зелено на том, что было видно», а не
«зелено везде». Полное покрытие даёт только локальный прогон
`bun scripts/check-all.mjs` с выкаченными submodule.
Реестр проверок и что каждая роняет — `bun scripts/check-all.mjs --list`.
⚠️ **Шаг «проверить peer-зависимости» не заменяет чтение вывода `bun install`
глазами.** `bun` (проверено на 1.3.14, включая `--verbose` и `--force`) не
печатает предупреждений о несовпадении `peerDependencies` вообще — ни в каком
режиме. `bun scripts/check-peer-deps.mjs` — единственный способ это увидеть,
он читает `bun.lock` и сверяет через `Bun.semver`. Скрипт всегда завершается
кодом 0 (это отчёт для человека, не gate) и в выводе всегда есть несколько
строк известного фонового шума (например eslint 10.x против старых
eslint-plugin-\*) — смотри не на список целиком, а на то, не появилась ли
**новая** строка после этого прогона `bun update`/`bun add`. Подробности
класса ошибки и почему это отдельный шаг —
[root-pin-peer-drift.md](/.claude/docs/root-pin-peer-drift.md).
⚠️ **Шаг «проверить патчи зависимостей» обязателен, если bump задел
пропатченный пакет.** Ключ `patchedDependencies` в корневом `package.json`
прибит к **точной** версии (`"@chakra-ui/react@3.37.0"`), а сама зависимость
стоит по caret-диапазону (`^3.37.0`). Любой bump разводит их — и bun 1.3.14
в этой ситуации **молчит**: `bun install`/`bun update --latest` завершаются
кодом 0, ничего не печатают, патч просто не накладывается. Файл
`patches/*.patch` при этом остаётся на диске, ключ в `package.json` — на
месте, в git всё выглядит здоровым; единственный след — блок
`patchedDependencies` тихо пропадает из `bun.lock`, и в диффе lock-файла на
тысячи строк его никто не заметит. Проверено эмпирически, разбор —
PLAN-INFRA-6.md §118.
Цена пропуска на сегодняшнем патче `@chakra-ui/react` — рассинхрон гидратации
во **всех ~30 приложениях сразу**, без единой ошибки сборки, lint или
typecheck ([chakra-css-memo-prop-order-hydration.md](/.claude/docs/chakra-css-memo-prop-order-hydration.md)).
`bun scripts/check-patched-deps.mjs` завершается кодом **1** при расхождении
(в отличие от `check-peer-deps.mjs` — это gate, а не отчёт) и сам смотрит в
свежеустановленную копию пакета: скажет, нужен ли патч дальше (тогда покажет
команды `bun patch` для пересоздания) или апстрим уже починил — и патч надо
**удалить**, а не переносить на новую версию.
## Чеклист
- [ ] `bun audit` без критичных уязвимостей
- [ ] `bun scripts/check-all.mjs --group=deps` — gate-проверки зелёные (код 0)
- [ ] в его выводе секция `peer-deps` — нет **новых** строк по сравнению с прошлым
прогоном (сама она код возврата не меняет, автозапуск на ней упасть не может)
- [ ] Все тесты проходят
- [ ] Сборка успешна
- [ ] Приложения запускаются
- [ ] Основной функционал работает
## Известные особенности
### Зафиксированные версии
`overrides`/`resolutions` в корневом `package.json` держат несколько
транзитивных пакетов на конкретных диапазонах ради security-патчей
(`minimist`, `qs`, `picomatch`, `serialize-javascript`, `protobufjs`,
`seroval`, `shell-quote`, `websocket-driver`, `@xhmikosr/decompress` —
актуальный список смотри в самом файле, не здесь, чтобы не рассинхронизироваться).
⚠️ **Точный пин (без `^`/`~`) в `dependencies`/`devDependencies` — отдельная
категория риска, не про security.** `kysely` и `@tanstack/react-query` были
точно запинены весной 2026 и оставались так до 2026-08-25 — оба пина снят,
прецеденты разобраны в
[root-pin-peer-drift.md](/.claude/docs/root-pin-peer-drift.md).
⛔ **Прежде чем снимать любой точный пин — сверься с
[`scripts/intentional-pins.json`](/scripts/intentional-pins.json).** Реестр
заведён 2026-09-03 ровно потому, что этот шаг команды не выполнялся: пин
`@tanstack/react-devtools@0.10.5`, поставленный как фикс падения прод-сборки
(§112), был снят обычным `deps update` через неделю — падение вернулось во все
приложения-потребители `@letar/query-provider` (§142). Строка в JSON не может
объяснить себя, а комментарии в коде библиотеки объясняли её собственный фикс,
не пин.
- у каждой записи есть поле `unpinWhen` — условие, при котором пин можно
снимать. Условие выполнено → снимай пин **и удаляй запись из реестра тем же
коммитом**, с закрытием задачи в корневой очереди `tasks/` (`done --summary`: почему причина отпала);
- условие не выполнено → пакет не трогаешь, даже если `bun outdated` показывает
его отставшим;
- заводишь **новый** точный пин → заводи и запись в реестре (`reason`, `doc`,
`unpinWhen`), не только задачу в `tasks/`;
- пакеты из секции `unexplained` — унаследованные точные пины без известной
причины. Их как раз можно и стоит возвращать на диапазон, удаляя запись.
Сверяет `bun scripts/check-intentional-pins.mjs` (gate в `--group=deps` и в
pre-commit). Он же называет вслух точный пин, не описанный в реестре вовсе.
### Пропатченные пакеты
Актуальный список — в `patchedDependencies` корневого `package.json` (не здесь,
чтобы не рассинхронизироваться). На 2026-09-30 это `@chakra-ui/react` и `@react-pdf/hyphenate`.
Порядок пересоздания патча под новую версию:
```bash
bun patch <pkg>@<новая-версия>
# правишь файл(ы) в node_modules/<pkg>/ — ESM и CJS обычно оба
bun patch --commit node_modules/<pkg>
rm patches/<старый>.patch # bun кладёт новый файл рядом, старый не удаляет
bun scripts/check-all.mjs --only=patched-deps
```
Промежуточные коммиты внутри этой процедуры блокирует pre-commit-хук (он и
должен — версии в этот момент вправду разошлись). Пропустить его на конкретном
коммите: `GIT_SKIP_DEPS_INTEGRITY=1 git commit ...`
⚠️ **Заводишь новый патч — добавь запись в `UPSTREAM_MARKERS`**
(`scripts/check-patched-deps.mjs`): где внутри пакета лежит место, ради
которого патч заведён, и по какому маркеру видно, что апстрим его ещё не
починил. Без записи скрипт при следующем bump'е сможет сказать только «версии
разошлись», но не «патч ещё нужен» / «патч пора удалить».
### Проблемные пакеты
- `chalk` — в корневом `package.json` сейчас `^6.0.1` (ESM only; потребитель — `scripts/bump-version.ts`). Старая пометка «используем v4» устарела; транзитивно v4 тянут сторонние пакеты (electron-fuses, jest) — это не наш пин
## После обновления
1. Обнови CHANGELOG.md:
```markdown
### Changed
- Обновлены зависимости: Next.js 16.x, React 19.x
```