Despliegue
En esta página
- El comando deploy
- Desplegar a todos los destinos a la vez
- local
- github-pages
- s3
- azure
- gcs
- firebase
- ftp / sftp
- rsync
- netlify
- vercel
- cloudflare-pages
- El comando package
- GitHub Actions (publicación multiversión)
- Qué hace
- Configuración inicial
- Publicar dos versiones a la vez
- Usar esto para tu propio proyecto
- Servir desde una subruta de Pages de proyecto
- Restringir quién puede acceder a tu sitio
Despliegue
site/ es un sitio estático simple - aloja donde sea que sirva archivos
estáticos. bxSites deploy lo envía allí
directamente, en un solo comando: S3 (y cualquier servicio compatible con
S3 - DigitalOcean Spaces, Cloudflare R2, Backblaze B2, MinIO), Azure Blob
Storage, Google Cloud Storage, Firebase Hosting, FTP, SFTP, rsync sobre
SSH, Netlify, Vercel, Cloudflare Pages, un directorio local, o GitHub
Pages.
El comando deploy
Todo destino salvo los dos más simples (local/github-pages, que
funcionan solo con opciones - consulta
Referencia de la CLI) se configura mediante
un archivo deployments/<name>.json en la raíz de tu proyecto - un
archivo por cada destino de despliegue que realmente uses, cada uno
indicando en target cuál es, además de los propios campos de ese
destino:
bxSites deploy --entry=production
{ "target": "s3", "bucket": "my-docs-site", "accessKeyIdEnvVar": "AWS_ACCESS_KEY_ID", "secretAccessKeyEnvVar": "AWS_SECRET_ACCESS_KEY" }
Los secretos siempre provienen de una variable de entorno, nunca de un
valor literal en deployments/*.json. Cada campo que termina en
EnvVar indica el nombre de la variable de entorno que contiene el
secreto real (una clave de acceso, una contraseña, un token de API) -
resuelta en el momento del despliegue, de modo que deployments/*.json
en sí siempre es seguro de incluir en un commit. Un campo que es una
ruta a un archivo de credenciales que ya gestionas tú mismo (una clave
privada SSH, una clave JSON de cuenta de servicio de GCP descargada) es
la única excepción - un campo normal, ya que lo que se mantiene fuera del
control de versiones es el propio archivo, no su ruta. Localmente, esas
variables de entorno también pueden provenir de un archivo .env (BoxLang
carga uno automáticamente y getSystemSetting() - lo que usa cada destino
para resolverlas - lo consulta de forma transparente) en lugar de
exportarlas a mano en tu shell; en CI, configúralas como secretos reales
en el ejecutor.
Desplegar a todos los destinos a la vez
Ejecuta bxSites deploy sin --entry ni --target y cada entrada
deployments/*.json se despliega por turno, a partir de una única
construcción compartida:
bxSites deploy
El sitio solo se construye una vez sin importar cuántas entradas tengas.
Que un destino falle no detiene el resto - se intenta cada entrada, y el
comando solo sale con un código distinto de cero si al menos uno de ellos
falló; el resumen reporta cuántos tuvieron éxito (por ejemplo, Deployed to 2/3 target(s) (1 failed)). Añade --verbose (también funciona con
--entry/--target) para imprimir una línea de progreso a medida que la
construcción y cada destino comienzan y terminan, en lugar de solo el
resumen final.
local
Copia el sitio construido a cualquier directorio - una unidad compartida,
una carpeta de staging, donde sea. El único destino que no necesita
ninguna entrada en deployments/.
bxSites deploy --target=local --destination=/path/to/somewhere
github-pages
El mismo push que hace gh-deploy,
también accesible desde este comando unificado - tampoco necesita
ninguna entrada en deployments/:
bxSites deploy --target=github-pages [--branch=gh-pages] [--remote=origin] [--message="..."]
s3
AWS S3 real, o cualquier servicio compatible con S3 - configura
endpoint para cualquier cosa que no sea AWS, y forcePathStyle: true
para la mayoría de los proveedores que no son AWS.
{
"target": "s3",
"bucket": "my-docs-site",
"region": "us-east-1",
"prefix": "",
"accessKeyIdEnvVar": "AWS_ACCESS_KEY_ID",
"secretAccessKeyEnvVar": "AWS_SECRET_ACCESS_KEY"
}
{
"target": "s3",
"bucket": "my-docs-site",
"endpoint": "https://nyc3.digitaloceanspaces.com",
"forcePathStyle": true,
"accessKeyIdEnvVar": "SPACES_KEY",
"secretAccessKeyEnvVar": "SPACES_SECRET"
}
La misma forma (endpoint personalizado + forcePathStyle: true)
también cubre Cloudflare R2
(https://<accountid>.r2.cloudflarestorage.com), Backblaze B2, y
MinIO/Wasabi.
azure
Azure Blob Storage, autenticado con un token SAS, una clave de cuenta, o una cadena de conexión completa - exactamente uno de los tres.
{
"target": "azure",
"account": "mystorageaccount",
"container": "site",
"accountKeyEnvVar": "AZURE_STORAGE_KEY"
}
gcs
Google Cloud Storage, autenticado con una clave JSON de cuenta de servicio descargada (Google Cloud Console -> IAM & Admin -> Service Accounts -> Keys).
{
"target": "gcs",
"bucket": "my-docs-site",
"serviceAccountKeyPath": "/path/to/service-account.json"
}
firebase
Firebase Hosting, usando el mismo tipo de clave de cuenta de servicio que
gcs.
{
"target": "firebase",
"siteId": "my-firebase-site",
"serviceAccountKeyPath": "/path/to/service-account.json"
}
ftp / sftp
Sube todo el sitio a un servidor remoto por FTP o SFTP, conservando su estructura de carpetas. SFTP acepta una contraseña o una clave SSH.
{
"target": "sftp",
"host": "example.com",
"username": "deploy",
"remotePath": "/var/www/html",
"key": "/home/me/.ssh/id_rsa"
}
rsync
Sincroniza el sitio con un servidor remoto por SSH mediante el binario
real de rsync - más rápido que FTP/SFTP para una reconstrucción
completa, ya que solo transfiere lo que cambió. Requiere rsync y ssh
en la máquina que ejecuta bxSites.
{
"target": "rsync",
"host": "example.com",
"username": "deploy",
"remotePath": "/var/www/html",
"identityFile": "/home/me/.ssh/id_rsa"
}
netlify
{
"target": "netlify",
"siteId": "my-site-id-or-name.netlify.app",
"authTokenEnvVar": "NETLIFY_AUTH_TOKEN"
}
vercel
{
"target": "vercel",
"projectId": "my-project",
"authTokenEnvVar": "VERCEL_TOKEN"
}
cloudflare-pages
Cloudflare no tiene una API REST documentada oficialmente para
despliegues de carga directa - solo su CLI wrangler. Este destino
aplica ingeniería inversa al propio flujo de carga de Wrangler, y
necesita una implementación de hash BLAKE3 en el classpath de la JVM que
la mayoría de las instalaciones de Java por defecto no incluyen -
consulta Referencia de la CLI y el propio
código fuente del destino para el detalle completo y honesto sobre las
asperezas de este caso.
{
"target": "cloudflare-pages",
"accountId": "your-account-id",
"projectName": "my-project",
"apiTokenEnvVar": "CLOUDFLARE_API_TOKEN"
}
El comando package
¿Prefieres un archivo simple antes que cualquiera de los destinos de
arriba - adjuntar una construcción a un release de GitHub, entregarla a
un host que solo acepta una carga en zip, o enviarla a algún lugar que
ninguno de los destinos conectables alcanza?
bxSites package construye el sitio y
luego lo comprime en un único archivo cuya raíz son los propios
contenidos del sitio construido (no una carpeta site/ que lo envuelva):
bxSites package
bxSites package --output=dist/my-site.zip
--output por defecto es <projectRoot>/site.zip; un valor relativo se
resuelve contra la raíz del proyecto, y sus directorios padre se crean
automáticamente si todavía no existen.
GitHub Actions (publicación multiversión)
Para la publicación automática en cada push, en lugar de ejecutar
bxSites deploy/gh-deploy a mano, este módulo incluye un flujo de
trabajo de GitHub Actions listo para usar (.github/workflows/pages.yml)
que publica main y development como dos versiones del mismo sitio
activas de forma independiente en GitHub Pages. El resto de esta guía
cubre ese flujo de trabajo, que la propia documentación de este
repositorio usa.
Qué hace
En cada push a main o development que toque docs/, bxsites.yaml, o
la propia fuente del módulo (cambios de tema/canalización), el flujo de
trabajo:
- Instala BoxLang + bx-markdown
- Registra este repositorio como un módulo para que
boxlang bxSites buildse resuelva - En cualquier rama que no sea
main, apuntabaseURLa.../<branch-name>/solo para esta construcción (consulta más abajo) - Ejecuta
boxlang bxSites build - Empuja
site/a la ramagh-pages-maina la raíz del sitio,developmenta/development/- sin tocar la otra versión
También está disponible como un disparador manual (workflow_dispatch)
desde la pestaña Actions, para una republicación puntual sin un nuevo
commit.
Configuración inicial
GitHub Pages necesita apuntar a la rama gh-pages antes de que el flujo
de trabajo pueda publicar nada - esto es una configuración del
repositorio, no algo que un archivo de flujo de trabajo pueda activar por
sí solo. La primera ejecución exitosa crea gh-pages por ti, así que
haz esto después de que el flujo de trabajo se haya ejecutado al menos
una vez:
- Settings -> Pages
- En Build and deployment -> Source, elige Deploy from a branch
- En Branch, elige gh-pages y / (root)
Después de eso, cada push coincidente construye y despliega automáticamente. La URL publicada aparece en Settings -> Pages en cuanto se completa el primer despliegue.
Publicar dos versiones a la vez
main se publica en la raíz del sitio
(https://<user>.github.io/<repo>/) - trata esto como la documentación
estable/publicada. development se publica en /development/
(https://<user>.github.io/<repo>/development/) - la documentación más
reciente, no publicada. Ambas permanecen activas simultáneamente: el
trabajo de cada rama solo empuja a gh-pages con keep_files: true y su
propio destination_dir, de modo que un despliegue de development
nunca sobrescribe el contenido de main y viceversa.
El propio bxsites.yaml de main debería tener baseURL configurado a
la raíz del sitio (https://<user>.github.io/<repo>/); el flujo de
trabajo lo sobrescribe para cualquier otra rama en el momento de la
construcción, así que el bxsites.yaml de development no necesita su
propia entrada baseURL para que esto funcione.
Para añadir una tercera rama (por ejemplo, una vista previa de
release/2.0), añádela a la lista on.push.branches y dale su propio
paso de despliegue if: github.ref_name == '...' con
destination_dir: release-2.0 (o similar) - el patrón es el mismo que el
de development.
Usar esto para tu propio proyecto
Copia .github/workflows/pages.yml en tu propio proyecto (ajusta la
línea modules: si tu proyecto necesita algo más allá de
bx-markdown), activa Pages como arriba, y los push a main/
development se publicarán de la misma manera. Si solo quieres una
única versión publicada, elimina la rama que no necesites de
on.push.branches y su paso de despliegue correspondiente.
Servir desde una subruta de Pages de proyecto
Un sitio de GitHub Project Pages (a diferencia de un sitio user
<user>.github.io) se sirve desde https://<user>.github.io/<repo>/, no
desde la raíz del dominio. Configura baseURL en bxsites.yaml con esa
URL completa para que cada enlace interno, recurso y entrada de
navegación obtenga el prefijo /<repo>/ que necesita - y para que
también se genere un sitemap.xml real:
baseURL: "https://<user>.github.io/<repo>/"
{ "baseURL": "https://<user>.github.io/<repo>/" }
Consulta Configuración para el desglose
completo de qué hace baseURL. Un sitio de usuario <user>.github.io, o
cualquier dominio personalizado asignado a la raíz del sitio, puede dejar
baseURL en su valor por defecto (/).
Restringir quién puede acceder a tu sitio
Aquí no hay control de acceso incorporado - bx-sites solo produce un
site/ estático simple, y un archivo estático no tiene ningún concepto
de "quién lo está pidiendo". El robots: false
de bxsites.json le dice a los rastreadores bien portados que no indexen
una construcción (útil para un despliegue de staging/vista previa que no
quieres que aparezca en los resultados de búsqueda), pero es una petición
educada, no un candado - la URL sigue funcionando para cualquiera que la
tenga. Si de verdad necesitas restringir el acceso, eso tiene que suceder
delante de los archivos estáticos, en el propio host que los sirve -
algunas opciones habituales, adecuadas para sitios estáticos:
- Cloudflare Pages/Access - coloca el sitio desplegado detrás de una política de Cloudflare Access (lista blanca de correos, SSO, o un PIN de un solo uso), sin necesidad de código de aplicación.
- Netlify - protección con contraseña incorporada, por sitio o por despliegue, solo desde los ajustes del sitio.
- Un pequeño proxy inverso (cualquier host) - HTTP Basic Auth delante
de los archivos estáticos (una regla al estilo
.htpasswd, o un Cloudflare Worker/Netlify Edge Function de un solo archivo) es suficiente para "mantener fuera a los motores de búsqueda y a cualquiera al azar", aunque no es una identidad real por usuario como la que tendría una aplicación con inicio de sesión.
Nada de esto son funciones de bx-sites - son ajustes a nivel de host que
activas dondequiera que termine sirviéndose site/.