Documentación · Referencia
El despliegue
Publicar en una carpeta, por FTP, SFTP o en S3.
Versión 0.16
ehundu desplegar [carpeta] [--simular] [--todo]
Compila el proyecto entero, como ehundu compilar, y si no hay errores lo
publica en el destino de la sección despliegue de sitio.yml: una carpeta,
un servidor FTP o SFTP, o un cubo de S3 o de un servicio compatible. Los
campos de cada destino y los secretos están en el §2 del formato.
Con --simular dice qué subiría y qué borraría, sin tocar el destino; sí se
conecta, para saber qué hay allí. Un destino carpeta que todavía no existe no se
crea. Con --todo lo sube todo aunque no haya
cambiado, que es lo que hace falta si alguien ha tocado a mano los ficheros
del servidor o si el sitio ha cambiado de dirección.
Qué se sube y qué se borra¶
Ehundu deja en el destino un fichero, .ehundu.json, con lo que ha subido:
la versión del manifiesto, la url del sitio y la ruta, el MD5 y el tamaño de
cada fichero, y nada más. Es un JSON así:
{
"ehundu": 1,
"url": "https://ejemplo.com",
"ficheros": {
"css/estilo.css": { "md5": "…", "tamano": 1234 },
"index.html": { "md5": "…", "tamano": 5678 }
}
}
ehundu es la versión del manifiesto (un Ehundu 1.x lee el de cualquier versión
anterior, y no lee uno que diga otra cosa), url puede faltar (un despliegue de
la 0.1) y las rutas van sin barra al principio, sin .. y ordenadas. Al
desplegar lo lee, compara con lo que acaba de compilar y sube solo
lo nuevo o lo que ha cambiado. El manifiesto vive en el propio destino para
que cualquier máquina que despliegue el sitio vea lo mismo, y para que el
motor no tenga que escribir nada en el proyecto fuera de salida/. Se puede
leer desde la web, como cualquier fichero del sitio: dice qué ficheros hay,
también los que no enlaza ninguna página.
Se borra solo lo que subió Ehundu y ya no se genera. Lo que haya en el
destino y no esté en el manifiesto no se toca nunca: el fichero con el que se
verifica un dominio, el .well-known de un certificado, un formulario en PHP.
La contrapartida es que, la primera vez que se despliega sobre un sitio que ya
existía, lo que dejó el sitio anterior se queda allí hasta que alguien lo
quite. Las carpetas que se quedan sin nada de Ehundu se intentan quitar; si
tienen algo más, se quedan.
Si el destino no tiene manifiesto, se sube todo y no se borra nada. Si lo
tiene pero está estropeado, el despliegue se detiene: sin él no se sabe qué
se puede borrar. --todo lo rehace.
Un destino de otro sitio¶
La url del manifiesto dice de qué sitio es el destino. Si no es la de
sitio.yml, el despliegue se detiene antes de tocar nada, también al
simular. Lo normal es que la ruta esté mal, por ejemplo en un sitio.yml
copiado de otro sitio que comparte servidor, y desplegar ahí borraría todo
lo que subió el otro sitio.
Si es el mismo sitio con otra dirección (otro dominio, con www o sin él,
de http a https), --todo lo confirma: se sube todo, se borra lo que
subió Ehundu y ya no se genera, como siempre, y el manifiesto pasa a la
dirección nueva. Un aviso lo deja dicho. La comparación es exacta, sin la
barra final: cualquier cambio en la url pide confirmarlo.
Un manifiesto sin url, de un despliegue con Ehundu 0.1, se acepta y la
gana en el siguiente despliegue.
En qué orden¶
Primero se suben los ficheros (CSS, imágenes, documentos), después las
páginas y al final el sitemap y el feed (también el de cada idioma, eu/feed.xml),
para que una página nueva no enlace algo que todavía no está. Los borrados van al final. FTP y SFTP no permiten
cambiarlo todo de golpe, así que durante unos segundos conviven lo nuevo y lo
viejo; este orden hace que lo que se ve en ese rato funcione.
El manifiesto se guarda cada 50 ficheros o cada 15 segundos, y al terminar. Si un despliegue se corta, el siguiente sigue donde se quedó: lo que ya subió está anotado. Si falla un fichero concreto, se guarda lo hecho hasta ahí antes de detenerse.
Subir por lotes¶
Desde un proceso web con límite de tiempo, Desplegador::desplegar() admite un
presupuesto de $segundos: al agotarse guarda el manifiesto y para, siempre
después de al menos un fichero, y el InformeDeDespliegue dice que no está
completo ($completo) y cuántos ficheros quedan ($pendientes). La llamada
siguiente traza el plan otra vez, ve en el manifiesto lo que ya está subido y
sigue por el resto. Con $todo no se reparte, porque sube todo sin mirar el
manifiesto. Por eso con $todo el presupuesto se ignora y se sube todo en una
sola llamada.
Junto con una compilación repartida en llamadas que ya ha terminado
(CompiladorIncrementalEnProceso::avanzar), se pasa su Informe como
$compilado y el despliegue no vuelve a compilar en cada llamada.
Cada destino¶
Carpeta. Una ruta de esta máquina: la raíz de un servidor web local, una carpeta sincronizada, un disco de red. Si es relativa, se cuenta desde el proyecto, y no puede estar dentro de él. Si no existe, se crea al subir el primer fichero, no antes.
FTP. Con la extensión ftp de PHP, que viene con PHP pero puede estar
desactivada (en Windows se activa en php.ini con extension=ftp). Usa una
sola conexión y el modo pasivo. Si algo falla, lo repite, hasta dos veces, y
lo deja dicho en un aviso: si la conexión se ha cortado, vuelve a conectar; si
sigue abierta, el servidor ha contestado que no, y eso puede ser pasajero
(vsftpd contesta «Failure reading network stream» cuando una subida le llega
mal, y deja el fichero a medias), así que lo repite una vez. Algunos
servidores FTPS, además, cortan siempre la subida de ciertos tamaños exactos
de fichero, sea cual sea su contenido, y ahí repetir no sirve. Por eso, como
último recurso, un fichero que no ha subido entero se sube en dos partes: la
primera normal y el resto añadido al final (APPE), partiendo por otro punto si
tampoco así, y comprobando con SIZE que al final mide lo que tiene que medir
(si el servidor no responde a SIZE, valen sus dos respuestas). Queda dicho en
un aviso. Los ficheros de 7.000 bytes o menos no se parten. La segunda parte
sale de un fichero temporal del sistema, fuera del proyecto, que se borra al
terminar, porque la extensión solo sabe mandar APPE desde un fichero. Si
tampoco sube en dos partes, es un error. Un fichero que se queda a medias no
entra en el manifiesto, así que el siguiente despliegue lo vuelve a subir. Por
defecto va cifrado (FTPS explícito); cifrado: no lo desactiva, pero entonces
la contraseña viaja a la vista. El cifrado necesita además la extensión
openssl, que traen casi todas las instalaciones de PHP. La extensión cifra
pero no comprueba el certificado del servidor: protege de quien escucha, no de
quien se haga pasar por el servidor. Para eso está SFTP.
SFTP. Con phpseclib, que es PHP puro. Se entra con contraseña (clave) o
con una clave privada (clavePrivada, y frase si la lleva). Antes de mandar
nada, se comprueba que el servidor es quien dice ser, con la huella de su
clave: huella en sitio.yml, tal como la escribe ssh-keygen -l. Si
falta, el primer despliegue se detiene y dice cuál es, para que se compruebe
con quien administra el servidor y se anote; si no coincide, se detiene.
S3. Cualquier servicio compatible: AWS, Scaleway, Cloudflare R2,
Backblaze, Hetzner. Las peticiones se firman en el propio motor, sin el SDK
de Amazon, y van por HTTPS con lo que trae PHP (la extensión openssl). El cubo va en el nombre del
servidor (cubo.s3.fr-par.scw.cloud), salvo si su nombre lleva puntos o
mayúsculas, o si el servidor lleva puerto, es localhost o es una dirección IP:
entonces va en la ruta. servidor puede llevar http:// o un puerto, para un
servicio local; sin esquema, es HTTPS. Cada fichero sube con su tipo MIME y con su MD5,
para que el servicio compruebe que le ha llegado entero. Que el cubo sirva un
sitio web se configura en el servicio; el motor no lo toca.
Lo que no hace¶
Nada después de desplegar: ni avisa a otros servicios ni vacía la caché de
una CDN. No hay variables de entorno para los secretos: van en .secretos.yml
o los da el programa que incrusta el motor. Y no hay bloqueo: si dos máquinas
despliegan el mismo sitio a la vez, el manifiesto puede quedar mal; se
arregla con --todo.
Para quien incruste el motor¶
Desplegador::desplegar() recibe los secretos directamente, sin fichero, e
informa de cada fichero subido o borrado según avanza. Decidir qué hacer
(PlanDeDespliegue) va aparte de hacerlo (Desplegador::ejecutar()), así que
un plan se puede ejecutar por partes, en varias peticiones (ver «Subir por lotes»).