Article

El patrón de dos fases para eliminar un módulo de Drupal sin romper los despliegues

Borrar el código de un módulo de Drupal es la parte fácil. Hacerlo sin romper su siguiente despliegue automatizado requiere una migración en dos fases: este es el patrón, y el incidente en producción que nos lo enseñó.
July 14, 2026
Topics:DeploymentConfiguration Management
Tags:DrupalDrushPHP

En un proyecto Drupal con configuración como código, eliminar un módulo personalizado parece trivial: borre la carpeta del módulo, quite su entrada de core.extension.yml, haga commit y fusione. Todo está en verde en local. Entonces el siguiente despliegue falla antes incluso de llegar al código de su aplicación, y el error nombra un módulo que usted estaba seguro de haber eliminado.

Esta es una trampa de orden de despliegue que tarde o temprano afecta a casi todos los equipos de Drupal maduros. La solución es un patrón pequeño y repetible de eliminación en dos fases. Esto es lo que sale mal, por qué, y cómo eliminar un módulo limpiamente en todos los entornos.

Qué sale mal

Su entorno local está bien, porque el módulo ya está desinstalado ahí. Pero sus bases de datos de staging y producción todavía tienen el módulo instalado: su nombre de máquina sigue apareciendo como habilitado en la configuración activa de cada entorno. Cuando se lanza la nueva versión, el código de ese módulo simplemente ya no está en la imagen.

La mayoría de los despliegues automatizados de Drupal ejecutan una secuencia como drush updatedb, luego drush config:import, y luego un puñado de pasos drush específicos del entorno. Cada comando drush tiene que inicializar primero el contenedor completo, y esa inicialización lee la lista de módulos activos. Cuando Drupal intenta cargar un módulo que está habilitado en la base de datos pero cuyo código ya no existe en disco, lanza:

In ExtensionList.php line 542:
  The module my_module does not exist.

El despliegue muere ahí. Peor aún, si su paso config:import está envuelto de modo que sus fallas no sean fatales, la importación falla silenciosamente al desinstalar el huérfano y el entorno sigue cojeando en un estado a medio romper hasta que un comando posterior choca con el mismo muro, con un mensaje mucho más confuso que la causa real.

Por qué borrar primero el código es el error

Drupal espera que un módulo se desinstale —se elimine de la configuración activa, con sus hooks de desinstalación ejecutados— antes de que su código desaparezca. Borrar la carpeta se salta ese paso por completo. La importación de configuración normalmente puede desinstalar un módulo que se ha quitado de core.extension.yml, pero solo mientras el código del módulo siga presente para cargarlo y ejecutar la desinstalación. Retire el código de debajo de un módulo instalado y habrá creado un huérfano que ninguna parte del despliegue puede resolver limpiamente.

El patrón de dos fases

Fase uno: desinstalar, con el código todavía presente. En la versión que retira el módulo:

  • Reduzca el módulo a un stub de desinstalación mínimo: conserve su .info.yml y un archivo .module vacío para que Drupal aún pueda descubrirlo y cargarlo, pero elimine toda la lógica real, las bibliotecas y las dependencias.
  • Quite el módulo de core.extension.yml para que la importación de configuración sepa que debe desinstalarse.
  • Añada un hook_post_update_N() en un módulo que sobreviva a la versión, para desinstalar el objetivo de forma determinista durante drush updatedb, que se ejecuta antes de los frágiles pasos de importación de configuración y de entorno:
function mymodule_post_update_uninstall_legacy(): ?string {
  if (!\Drupal::moduleHandler()->moduleExists('legacy_module')) {
    return NULL;
  }
  \Drupal::service('module_installer')->uninstall(['legacy_module']);
  return 'Uninstalled the retired legacy_module.';
}

La comprobación inicial lo hace idempotente: no hace nada en los entornos donde el módulo ya no está (local, instalaciones nuevas o una nueva ejecución). Como el código del stub sigue en disco, la desinstalación se ejecuta limpiamente, y todos los pasos drush posteriores se inicializan sin tropezar con un huérfano.

Fase dos: borrar el código. Una vez que la primera versión se ha desplegado en todas partes y todos los entornos han ejecutado la desinstalación, lance una segunda versión trivial que borre la carpeta del stub y el hook post-update ya consumido. Ya no hay un módulo instalado en ningún sitio que contradiga la ausencia del código.

La lección más amplia

La configuración como código hace que la mayor parte de Drupal sea reproducible desde Git, pero el estado de los módulos instalados vive en la base de datos de cada entorno, no en su repositorio. Eliminar un módulo es, por tanto, una migración, no un borrado de archivos: necesita un paso de desinstalación que se ejecute contra todos los entornos en funcionamiento antes de que se permita que el código desaparezca. Incorpore eso a su lista de verificación de versiones y toda una clase de fallas a mitad de despliegue simplemente deja de ocurrir.

El patrón es pequeño, pero convierte una falla de producción alarmante y difícil de diagnosticar en una tarea aburrida de dos pasos, que es exactamente lo que debería ser el trabajo de infraestructura.