Guía / deploy

Despliega un release, paso a paso

Usa este recorrido cuando un repositorio Git es dueño de un artifact o kit y quieres un release repetible y auditable desde hubbound.json.

Antes de empezar

Necesitas un CLI de HubBound con soporte para deploy, un directorio de proyecto que contenga hubbound.json, un worktree Git con remote origin y credenciales obtenidas con hubbound auth login para un release real.

Deploy lee exactamente --path/hubbound.json. No camina hacia un manifest padre, así que elige --path conscientemente cuando ejecutes el comando desde un subdirectorio.

  • Usa un manifest de proyecto v2. hubbound init crea la forma inicial.
  • Usa versiones SemVer exactas como 1.2.0 en deployments y pins; no uses latest en dependencies de un proyecto v2.
  • Verifica que origin sea HTTPS sin credenciales embebidas y que HEAD sea un SHA hexadecimal de 40 o 64 caracteres.
  • Mantén el bundle en máximo 250 archivos, 2 MiB por archivo y 10 MiB lógicos en total.

1. Define el deployment

Un deployment es una receta de release con nombre. Un artifact tiene kind, path, tag, version, visibility, artifact_type, content y files. Un kit tiene kind, path, tag, version, visibility y members; no puede definir artifact_type, content ni files.

path es relativo al root del manifest e identifica el root del paquete para files. El nombre del deployment es el selector local que pasas a hubbound deploy; no es el tag público.

{
  "schema_version": 2,
  "name": "security-tools",
  "deployments": {
    "auditor": {
      "kind": "artifact",
      "path": "packages/auditor",
      "tag": "vendor/security-auditor",
      "version": "1.2.0",
      "visibility": "public",
      "artifact_type": "SKILL",
      "content": { "entrypoint": "SKILL.md" },
      "files": ["SKILL.md", "references/**", "scripts/**"]
    }
  }
}

2. Ejecuta el preflight local

Empieza con dry-run. Valida el manifest, resuelve los deployments seleccionados, revisa procedencia Git y expande los patrones de archivos sin crear un release remoto, subir bytes ni hacer commit.

Omite los nombres para validar todas las entradas. Pasa uno o más nombres para limitar el run. Si un kit seleccionado referencia deployments locales de artifacts, se incluyen automáticamente y se preparan antes del kit.

$ hubbound auth login

$ hubbound deploy --path . --dry-run --json

$ hubbound deploy auditor --path . --dry-run

$ hubbound deploy auditor --path . --dry-run --json > deploy-preflight.json

--path <dir> Directorio exacto que contiene hubbound.json. Default: .; no hay búsqueda en ancestros.
[deployment...] Nombres locales opcionales. Sin nombres significa todos; deben existir bajo deployments.
--dry-run Validación local de manifest, Git y archivos. No muta el backend.
--json Resultado legible por máquina con estado, cantidades, SHA y datos de release cuando existan.
--allow-dirty Permite tracked, untracked o borrados y marca source.dirty=true.

3. Haz que pase el snapshot de archivos

files usa patrones relativos y soporta **. Todo artifact necesita al menos un patrón, incluso un MCP cuya configuración de runtime vive sobre todo en content. Un patrón sin matches es un error.

El snapshot conserva archivos regulares, no symlinks y de texto UTF-8. Rechaza material inseguro o sensible antes de la primera mutación remota; corrige el paquete en vez de intentar saltar la barrera.

  • Máximo 250 archivos, 2 MiB por archivo y 10 MiB lógicos en total.
  • Se excluyen .git, hubbound.json, archivos .env, backups terminados en ~ o .bak y material privado .pem/.key/.crt.
  • Se rechazan imágenes, archives, PDFs, ejecutables, fonts y otras firmas binarias.
  • Los entrypoints deben ser relativos al paquete y no pueden ser absolutos ni escapar con ..; usa el mismo path en content y files.

4. Publica el release

Cuando el dry-run esté limpio, ejecuta la misma selección sin --dry-run. El cliente prepara el release con el control plane autenticado, recibe los digests faltantes y URLs presigned, sube solo esos bytes y hace commit del release.

El PUT presigned es otra frontera de confianza: usa exactamente los headers devueltos por el backend y no agregues Authorization ni DPoP. El cliente envía una idempotency key para que un retry pueda identificar el mismo intento.

$ hubbound deploy auditor --path . --json

$ hubbound deploy security-kit --path . --allow-dirty --json

artifact Prepara metadata, sube blobs CAS faltantes y hace commit de la versión del artifact.
kit Prepara la composición exacta. Los deployments locales se preparan primero; el kit no sube blobs duplicados.
--wait-timeout <duration> Máximo de espera de un watcher configurado del registry público; default 5m.
--yes Aceptado por compatibilidad; el flujo actual no muestra confirmación interactiva.

5. Interpreta bien el resultado

Guarda el output JSON en CI o en un log de auditoría. Un commit exitoso significa que el control plane autenticado aceptó la versión inmutable. No demuestra automáticamente que un install público anónimo pueda verla.

Trata release_state y publication_state como evidencia separada. El wiring actual del CLI puede reportar publication status unavailable cuando no hay watcher público configurado; eso es distinto de un commit fallido.

  • committed: el backend aceptó el commit del release.
  • active: la proyección del registry público está disponible para discovery/install anónimo.
  • unavailable: este cliente no tiene evidencia de watcher para la proyección pública; verifica aparte en el control plane de release/registry.
  • Para reintentar, compara nombre de deployment, tag, version, SHA e idempotency key antes de asumir que creaste otro release.

Fallos comunes y correcciones

La mayoría de errores ocurre temprano a propósito. El mensaje indica qué contrato falló; corrige el manifest o el paquete y vuelve a ejecutar dry-run antes de intentar un deploy real.

hubbound.json not found Pasa --path al directorio que contiene el manifest; deploy no busca en padres.
deployment not found Usa la key bajo deployments, no el tag público, o elimina nombres para procesar todos.
dirty worktree Commitea los archivos intencionados o usa --allow-dirty explícitamente cuando source.dirty=true sea aceptable.
pattern matched no files Revisa path y el patrón relativo al paquete. Recuerda que files debe producir al menos un match.
unsafe/binary/too large Quita el archivo de files, conviértelo a texto UTF-8 seguro o divide el paquete dentro de los límites.
public status unavailable El commit puede ser válido; el monitoreo de publicación es separado y puede no estar conectado en este checkout.