Actualizar dependencias
El objetivo es un proyecto cuyas dependencias estén actualizadas y no tengan vulnerabilidades conocidas, entregado como un cambio en el que el usuario pueda confiar: cada paso verificado por las comprobaciones propias del proyecto, y cada paso arriesgado aislado para que pueda revisarse o revertirse por sí solo.
El trabajo con dependencias falla de dos formas típicas. Una es la "actualización masiva", donde todo se actualiza a la vez, algo se rompe y nadie puede identificar qué actualización lo causó. La otra es una "solución" que oculta el problema, como --force, --legacy-peer-deps, aflojar un rango de versión o suprimir un aviso. El flujo de trabajo siguiente está diseñado para evitar ambas.
0. Decidir lo que se pidió
- Solo verificar ("¿alguna vulnerabilidad?", "¿qué está obsoleto?"): realiza los pasos 1–3, informa y detente. No modifiques archivos.
- Actualizar (por defecto para "actualiza mis dependencias", "arregla las advertencias de auditoría", "mantén los paquetes actualizados"): realiza todo el flujo de trabajo.
- Un paquete ("actualiza vite a la v8"): realiza los pasos 1–2, luego el paso 6 para ese paquete (junto con cualquier paquete que deba moverse con él), luego 7–8.
1. Vuelo previo
-
Lee los documentos de contribución del repositorio (
AGENTS.md,CLAUDE.md,CONTRIBUTING.md) y la configuración de CI (.github/workflows/*) para conocer los comandos de verificación (lint, typecheck, test, build) y la convención de mensajes de commit. Usa lo que el repositorio realmente ejecuta en CI. Si no hay nada documentado, usa los scripts definidos en el manifiesto. -
Asegúrate de que el árbol de trabajo esté limpio. Si no lo está, detente y pregunta. Mezclar el trabajo no confirmado del usuario en commits de dependencias causa daños reales.
-
Detecta los ecosistemas por sus archivos de bloqueo y manifiestos (un repositorio puede tener varios):
Archivos Referencia package-lock.json,pnpm-lock.yaml,yarn.lock,bun.lockreferences/node.mdrequirements*.txt,pyproject.toml,uv.lock,poetry.lock,Pipfile.lockreferences/python.mdCargo.toml/Cargo.lockreferences/rust.mdgo.mod/go.sumreferences/go.mdcualquier otro (Gemfile.lock, composer.lock, …) usa la herramienta propia del ecosistema, además de scripts/osv_check.pypara la auditoríaLee el archivo de referencia correspondiente. Enumera los comandos exactos y las trampas de ese ecosistema.
-
Encuentra la versión de tiempo de ejecución objetivo del proyecto:
.nvmrc,engines,.python-version,requires-python,rust-version, la directivago, o la versión en CI. Algunos paquetes deben seguir la versión de tiempo de ejecución, no la última versión. Por ejemplo,@types/nodedebe coincidir con la versión mayor de Node que el proyecto ejecuta, por lo que actualizarlo a una versión mayor más reciente de Node permite que el código use APIs que fallan en producción. Trata "última versión" como un candidato, no como un objetivo. -
Ejecuta los comandos de verificación antes de cambiar nada y anota el resultado. Si algo ya falla, debes saberlo ahora. De lo contrario, culparás a una actualización por un fallo que ya existía, o enviarás una rama en rojo. Si la línea base está en rojo, informa al usuario y pregunta si debe continuar.
2. Inventario
Recopila dos listas con las herramientas del ecosistema (consulta la referencia):
- Vulnerabilidades: la herramienta de auditoría nativa. Si no está instalada y no se puede ejecutar de forma efímera, usa el escáner incluido:
python3 <directorio-skill>/scripts/osv_check.py <archivo-de-bloqueo>...(consulta osv.dev; solo stdlib). Ejecutar el escaneo OSV además de la herramienta nativa es económico y a menudo vale la pena, porque las herramientas nativas a veces omiten avisos en copias anidadas o duplicadas de un paquete. - Paquetes obsoletos: actual → deseada (dentro del rango declarado) → última.
Para cada vulnerabilidad, determina qué dependencia directa incorpora el paquete vulnerable y qué versión de esa dependencia directa lo soluciona. Los usuarios actúan sobre las dependencias directas. El nombre de un paquete transitivo por sí solo no es procesable.
3. Planificar e informar
Clasifica todo en tres grupos y muestra el plan como una tabla corta antes de realizar cambios:
- Correcciones de seguridad: cualquier cosa que elimine un aviso. Lo más urgente. Si la corrección necesita una actualización mayor, es mayor (grupo 3), pero enuméralo primero allí y di que está impulsado por la seguridad.
- Actualizaciones seguras: parche/menor dentro de semver (para paquetes 0.x, una menor cuenta como cambio importante).
- Mayores: todo lo demás, una fila cada uno. Agrupa los paquetes que deben moverse juntos (un framework y sus plugins, una herramienta y sus definiciones de tipos, paquetes que comparten una dependencia entre pares) y trata cada grupo como una unidad.
La gravedad es importante para el orden, y la alcanzabilidad es importante para la explicación. Un aviso crítico en un ejecutor de pruebas solo de desarrollo sigue valiendo la pena corregirlo, pero di claramente que es solo de desarrollo en lugar de alarmar al usuario. Para solicitudes de solo verificación, este informe es el resultado. Incluye la gravedad, el ID del aviso, la ruta de la dependencia y la versión de la corrección.
4. Rama
Crea chore/deps-AAAA-MM-DD (la fecha de hoy) a partir de la rama predeterminada actualizada, a menos que el usuario ya esté en una rama creada para este trabajo.
5. Correcciones de seguridad y actualizaciones seguras
- Aplica las correcciones de seguridad dentro del rango, vuelve a ejecutar los comandos de verificación y haz commit.
- Aplica las actualizaciones seguras de parche/menor juntas, vuelve a ejecutar los comandos de verificación y haz commit. Si la verificación falla, divide en dos: revierte la mitad del lote y vuelve a intentar hasta que encuentres el culpable, luego sácalo y manéjalo como una actualización mayor.
Deja que el gestor de paquetes escriba el archivo de bloqueo. Nunca edites los archivos de bloqueo manualmente.
6. Mayores, una unidad a la vez
Para cada unidad mayor, en orden (primero las impulsadas por seguridad, luego las herramientas fundamentales antes que las que dependen de ellas, p. ej., el compilador antes que el plugin del linter que depende de él):
- Lee lo que cambió. Encuentra la guía de migración o las notas de la versión para cada versión mayor que estás cruzando (v2→v5 significa leer v3, v4 y v5). Las buenas fuentes son el
CHANGELOG.mddel proyecto, los lanzamientos de GitHub y la página de "migración" del sitio de documentación. Extrae los cambios importantes que aplican a este código base: busca las API y claves de configuración eliminadas o renombradas. - Verifica pares. Asegúrate de que la nueva versión cumpla con los requisitos de pares y motor de todo lo que la rodea. A veces la última versión mayor aún no se puede adoptar porque un plugin no se ha puesto al día. Entonces toma la versión más nueva que funcione y registra lo que bloquea el resto.
- Actualiza y corrige. Actualiza la unidad, aplica la migración (cambios de nombre de configuración, cambios de API, codemods si el proyecto los incluye), y vuelve a ejecutar los comandos de verificación hasta que pasen. Corrige el código correctamente. No debilites las pruebas, añadas
skips, ni silencies errores de tipo conanyo escapes de estilo@ts-ignorepara llegar al verde. - Haz commit de la unidad por sí sola, con las notas de migración en el cuerpo.
- Sabe cuándo detenerte. Si una unidad necesita una refactorización grande o una decisión de producto (característica eliminada, cambio de comportamiento en tiempo de ejecución que no puedes verificar), o no puedes llegar al verde con un esfuerzo razonable, reviértela limpiamente (
git checkout -- .hasta el último commit) y regístrala como diferida, con el bloqueador específico. Una actualización mayor diferida con una razón clara es un buen resultado. Una a medio hacer no lo es.
7. Re-verificar y re-auditar
Ejecuta los comandos de verificación completos y la auditoría nuevamente en el estado final. Cada aviso ahora debe estar corregido o explicado. Para un aviso que no pudiste corregir:
- Si es transitivo y el paquete padre no ha lanzado una corrección, se acepta una anulación/resolución que fije la versión transitiva parcheada solo si esa versión es compatible semver con lo que espera el padre. Verifícalo y anótalo en el PR para que alguien lo elimine más tarde.
- Si no existe ninguna versión parcheada en ningún lugar, dilo y evalúa si la ruta de código vulnerable es alcanzable en este proyecto.
- Nunca uses mecanismos de ignorar/lista blanca para que la auditoría pase en silencio.
8. Entregar
Los commits siguen la convención del repositorio. Si el repositorio usa Commits Convencionales y no dice nada más específico, usa:
fix(deps): ...para una corrección de seguridad a una dependencia de tiempo de ejecuciónbuild(deps): ...para actualizaciones, y para correcciones de seguridad a herramientas solo de desarrollo- el resumen nombra el paquete y el objetivo, p. ej.,
build(deps): subir vitest a v5. El cuerpo enumera los avisos corregidos y cualquier cambio de migración realizado.
Haz push y abre un PR (gh pr create) a menos que el usuario haya pedido lo contrario o no haya remoto. Usa este cuerpo:
## Resumen
<una o dos oraciones: qué se movió, cuántos avisos se resolvieron>
## Seguridad
| Aviso | Gravedad | Paquete (ruta) | Corregido por |
|---|---|---|---|
## Actualizaciones
| Paquete | Desde | Hasta | Tipo | Notas |
|---|---|---|---|---|
<Tipo = seguridad / parche / menor / mayor; Notas = cambios de migración realizados>
## Diferidos
| Paquete | Última | Por qué no ahora |
|---|---|---|
<par bloqueado, necesita refactorización, fijación de tiempo de ejecución, ...; "ninguno" si está vacío>
## Avisos restantes
<ninguno, o cada uno con motivo y evaluación de alcanzabilidad>
## Verificación
<los comandos exactos ejecutados en el commit final y su resultado>
Termina con un breve resumen de chat: el enlace del PR, el número de avisos corregidos frente a los restantes, y las actualizaciones mayores diferidas con razones de una línea.