Mi servidor no trae los cambios de GitHub al reiniciar: el culpable era el comando de inicio
Tenías GitHub y la actualización automática activados, pero al reiniciar el servidor seguía con el código viejo. Así encontramos la causa y cómo arreglarla.
Por Carlospinto_tgz38 min de lectura
Hace poco nos llegó un caso que parecía imposible. Un servidor de Node.js tenía bien puesta la dirección del repositorio de GitHub, la rama correcta, el token de acceso y la actualización automática encendida. Aun así, cada vez que se reiniciaba seguía con el código antiguo, y en un servidor recién reinstalado ni siquiera aparecía el código: la carpeta estaba vacía y el bot se caía al arrancar.
La configuración de GitHub no tenía nada mal. El problema estaba en un sitio que casi nadie mira: el comando de inicio del servidor. En este artículo contamos cómo lo encontramos, por qué pasa y cómo comprobar si a tu servidor le ocurre lo mismo.
Cómo funciona el despliegue desde GitHub en el panel
En nuestro panel, la sección GitHub de cada servidor guarda unas variables: la dirección del repositorio (GIT_ADDRESS), la rama (BRANCH), el usuario y el token si el repositorio es privado, la actualización automática (AUTO_UPDATE) y la opción de archivos subidos a mano (USER_UPLOAD).
Esas variables por sí solas no hacen nada. Son solo valores. Quien las lee y decide si clonar o actualizar es el comando de inicio, el script que se ejecuta cada vez que pulsas *Iniciar* o *Reiniciar*. Si ese script no sabe qué hacer con una variable, da igual que la pongas en 1.
Los síntomas
- Haces
git pusha tu repositorio, reinicias el servidor y el código sigue igual que antes. - En la consola no aparece ningún mensaje de
git pullni de clonación al arrancar. - Tras reinstalar el servidor, la carpeta queda vacía (sin
package.json) y la consola muestra errores comoCannot find module '/home/container/index.js'. - Si subes los archivos a mano por SFTP, el servidor sí arranca, lo que despista todavía más.
La causa: un comando de inicio antiguo que nunca clonaba
En Pterodactyl, el panel en el que se basa el nuestro, cada tipo de servidor (lo que internamente se llama *egg*) trae un comando de inicio por defecto. Pero cuando se crea un servidor, ese comando se copia dentro del servidor. A partir de ahí el servidor tiene su propia copia y no se entera si después se mejora el del tipo de servidor.
Encima, reinstalar el servidor no cambia el comando de inicio. Reinstalar vuelve a ejecutar el script de instalación, pero el comando con el que arranca se queda tal cual. Por eso un servidor creado hace meses puede seguir usando un comando anticuado aunque lo reinstales varias veces.
Los servidores afectados tenían este comando antiguo:
if [[ -d .git ]] && [[ {{AUTO_UPDATE}} == "1" ]]; then git pull; fi;
if [[ ! -z {{NODE_PACKAGES}} ]]; then /usr/local/bin/npm install {{NODE_PACKAGES}}; fi;
if [[ ! -z {{UNNODE_PACKAGES}} ]]; then /usr/local/bin/npm uninstall {{UNNODE_PACKAGES}}; fi;
if [ -f /home/container/package.json ]; then /usr/local/bin/npm install; fi;
{{COMMAND}}Fíjate en la primera línea. Solo hace git pull si ya existe la carpeta `.git`. No usa GIT_ADDRESS en ningún momento y no tiene ningún git clone. Es decir:
- Si el repositorio nunca llegó a clonarse (por ejemplo, porque la instalación falló o porque se puso la dirección del repositorio después de instalar), no hay
.git, así que no hace nada y arranca con la carpeta vacía. - Tampoco revisa
USER_UPLOAD, así que no distingue entre un servidor que manda GitHub y uno con archivos subidos a mano.
En el caso que investigamos se juntaron las dos cosas: el servidor se reinstaló antes de rellenar la dirección del repositorio. La instalación terminó con el error GIT_ADDRESS no definido, no se creó .git, y el comando antiguo nunca lo iba a clonar por su cuenta. El resultado era una carpeta vacía en cada arranque.
Cómo lo comprobamos
Antes de cambiar nada en producción reproducimos el problema en un contenedor de pruebas aparte, con la misma imagen de Docker y las mismas variables que el servidor afectado, pero cambiando el comando final por node -v para que terminara enseguida. Probamos dos arranques seguidos:
- Primer arranque con la carpeta vacía: con el comando antiguo no pasaba nada; con el nuevo, el repositorio se clonaba.
- Segundo arranque, ya con `.git` y `AUTO_UPDATE=1`: con el comando nuevo se ejecutaba
git pully se descargaban los últimos cambios.
Así confirmamos que la diferencia estaba solo en el comando de inicio y no en GitHub, el token ni la red.
El comando de inicio que sí funciona
El comando corregido lee todas las variables de GitHub y cubre los dos casos: clona si todavía no hay repositorio y actualiza si ya lo hay. Esta es la versión para Node.js, con saltos de línea añadidos para que se lea mejor:
if [[ ! -z "${GIT_ADDRESS}" ]] && [[ "${USER_UPLOAD}" == "0" ]]; then
if [[ ! -d .git ]]; then
# Primera vez: clona el repositorio en una carpeta temporal y lo copia
rm -rf /tmp/gitclone
if [[ -z "${BRANCH}" ]]; then BRANCH_OPT=""; else BRANCH_OPT="-b ${BRANCH}"; fi
if [[ -z "${USERNAME}" ]] || [[ -z "${ACCESS_TOKEN}" ]]; then
git clone $BRANCH_OPT "${GIT_ADDRESS}" /tmp/gitclone
else
git clone $BRANCH_OPT "https://${USERNAME}:${ACCESS_TOKEN}@$(echo ${GIT_ADDRESS} | sed 's#https://##')" /tmp/gitclone
fi
cp -a /tmp/gitclone/. /home/container/
rm -rf /tmp/gitclone
elif [[ "${AUTO_UPDATE}" == "1" ]]; then
# Siguientes arranques: trae los últimos cambios
git pull
fi
fi
if [[ ! -z ${NODE_PACKAGES} ]]; then /usr/local/bin/npm install ${NODE_PACKAGES}; fi
if [[ ! -z ${UNNODE_PACKAGES} ]]; then /usr/local/bin/npm uninstall ${UNNODE_PACKAGES}; fi
if [ -f /home/container/package.json ]; then /usr/local/bin/npm install; fi
${COMMAND}Las diferencias importantes respecto al antiguo:
| Situación | Comando antiguo | Comando nuevo |
|---|---|---|
Hay GIT_ADDRESS pero no hay .git | No hace nada: carpeta vacía | Clona el repositorio |
Ya hay .git y AUTO_UPDATE = 1 | Hace git pull | Hace git pull |
| Repositorio privado | Depende de que la instalación lo haya clonado | Clona usando usuario y token |
USER_UPLOAD = 1 (archivos por SFTP) | Lo ignora | No toca tus archivos |
| Rama distinta de la principal | No la tiene en cuenta | Clona la rama de BRANCH |
Clonamos en /tmp/gitclone y luego copiamos en vez de clonar directamente en /home/container porque git clone se niega a clonar en una carpeta que no está vacía, y en un servidor ya suele haber algún archivo (registros, un .env, etc.).
Para bots en Bun el comando es el mismo cambiando npm install por bun install y npm uninstall por bun remove.
Cómo arreglarlo en tu servidor
Después de este caso actualizamos el comando por defecto de los tipos de servidor Node.js y Bun, y pasamos al nuevo los servidores que todavía tenían el antiguo. Si tu servidor tiene un comando personalizado, no lo tocamos, así que conviene que lo revises tú:
- Entra en tu servidor en el panel y abre la sección Inicio.
- Mira el comando de inicio. Si empieza por
if [[ -d .git ]]y no aparecegit clonepor ningún lado, tienes el comando antiguo. - Pulsa Restablecer al valor predeterminado del tipo de servidor y después Guardar. Eso copia el comando actualizado del tipo de servidor.
- En la sección GitHub, comprueba que la dirección del repositorio termina en
.git, que la rama es la correcta y que Archivos subidos a mano está apagado. - Reinicia el servidor y mira la consola: en el primer arranque debería clonar y en los siguientes hacer
git pull.
git pull. Haz los cambios en tu repositorio y súbelos con git push.Si después de cambiar el comando sigue sin actualizar
- Error de autenticación al clonar: el token caducó o no tiene permiso de lectura sobre ese repositorio. Genera uno nuevo en GitHub con acceso de solo lectura al repositorio y vuelve a pegarlo.
- `git pull` falla con conflictos: alguien modificó archivos dentro del servidor. Ejecuta
git statusen la consola para ver cuáles son, o bórralos y deja que se vuelvan a descargar. - Clona la rama equivocada: la variable
BRANCHsolo se usa al clonar. Si la cambias después, borra la carpeta.git(o todo el contenido) para que se vuelva a clonar con la rama nueva. - Se descargan los cambios pero el bot no los usa: revisa que tu archivo principal (
index.js,main.js…) sea el que indica la variable del comando final, y que no estés compilando a una carpeta comodist/que nunca se regenera.
Lo que aprendimos
El fallo no estaba en la parte que el cliente veía (la sección de GitHub), sino en una pieza intermedia que se queda congelada al crear el servidor. Ahora, cuando alguien nos dice que GitHub no se actualiza, lo primero que revisamos es el comando de inicio, antes que el token o el repositorio.
Si tienes un bot o una app con despliegue desde GitHub y no tienes claro qué comando de inicio usa tu servidor, abre un ticket en la mesa de ayuda y lo revisamos contigo.
