Ir al contenido

Publicación y ciclo de vida de borradores

Qué es esto

Cómo un cambio pasa de ser una edición a una página publicada mediante MCP: el ciclo de vida del borrador, la publicación en dos pasos (realmente tres llamadas) y el hecho que confunde a los agentes: el ID del documento rota en cada publicación, por lo que la forma duradera de nombrar una página es mediante su slug + idioma, nunca su path.

Cómo funciona

Borradores

Editar una página activa nunca la modifica. update-page escribe un nuevo documento de borrador y mantiene la URL activa mostrando el contenido antiguo hasta que publiques. Dos propiedades son importantes:

  • Buscar o crear. Las ediciones repetidas en el mismo (slug, idioma) actualizan el mismo borrador; las ediciones secuenciales se consolidan en uno solo, no en una pila.
  • Sin cambios (Zero-diff) no hace nada. Una edición que no cambia nada no crea un borrador, y un borrador existente que es idéntico byte a byte al activo se elimina del manifiesto, del conteo de traducciones y de la promoción.

Descarta un borrador que no desees con discard-draft; esta función rechaza rutas activas, ocultas y archivadas.

Rotación de ID de documento, el slug como identificador

El ID del documento en Firestore es el path. Cuando se edita una página activa, el nuevo borrador obtiene un ID nuevo generado automáticamente; al publicar, ese borrador se promociona y el documento activo anterior se elimina. El efecto neto: el path que sirve a una URL determinada cambia después de cada ciclo de edición-publicación. El canonical_slug de la página se conserva durante todo el ciclo.

Por lo tanto, dirígete a las páginas mediante su identificador duradero (slug, idioma)get-page-content y update-page lo aceptan directamente— y lee el nuevo path desde publish-status.published_urls después de cada publicación. Nunca guardes en caché un path entre publicaciones.

La publicación, paso a paso

  1. publish — una prueba. Devuelve un manifiesto de diferencias por página (change_type create o replace, título/descripción antes/después + tamaños en bytes, will_publish_to) además de un confirmation_token de un solo uso con una TTL de 5 minutos. No escribe nada. La publicación es todo o nada en todo el proyecto: el manifiesto enumera cada borrador pendiente, no solo los tuyos; revisa la lista completa antes de confirmar.
  2. publish-confirm — consume el token, verifica nuevamente que ningún borrador o tema haya cambiado desde la prueba (un aborto por deriva), luego ejecuta la canalización de forma asíncrona: promocionar → traducir → validar en segunda pasada → desplegar. Devuelve inmediatamente { publish_id, status: "running" }.
  3. publish-status — sondea con el publish_id hasta que sea succeeded (devuelve published_urls, cada una con la nueva ruta activa) o failed.

Traducciones

translations_planned en el manifiesto cuenta los idiomas hermanos que la canalización escribirá: la suma de los borradores de los idiomas de destino menos el idioma de origen. Cuando un proyecto no tiene idiomas de destino configurados, es 0 (sin conteo fantasma).

Cuándo usarlo

  • Al crear automatizaciones que editan y luego publican, y necesitan la URL posterior a la publicación.
  • Para entender por qué una segunda edición no creó un segundo borrador.
  • Para explicar por qué un path de la semana pasada ya no funciona.

Campos que leerás

FuenteCampoSignificado
Manifiesto publishdrafts[].change_typecreate (nuevo) o replace (existente)
drafts[].will_publish_tola URL activa a la que apunta este borrador
summary{ total, creates, replaces }
translations_plannedidiomas hermanos que la canalización escribirá
confirmation_tokende un solo uso, TTL de 5 min
publish-confirmpublish_id, statusrunning inmediatamente
publish-statusstatusqueued / running / succeeded / failed
published_urls[]{ title, language, slug, url } — la nueva ruta activa

Ejemplo

(two edits, one draft)
update-page(project_id, slug: 'guides/intro', content: '## v1') -> draft_id X
update-page(project_id, slug: 'guides/intro', content: '## v2') -> draft_id X (same draft)
publish(project_id, project_name)
-> manifest { drafts: [ { slug: 'guides/intro', change_type: 'replace',
will_publish_to: 'https://example.com/guides/intro/' } ],
summary: { total: 1, creates: 0, replaces: 1 },
translations_planned: 0 },
confirmation_token (single-use, 5-min TTL)
publish-confirm(project_id, confirmation_token) -> { publish_id, status: 'running' }
publish-status(project_id, publish_id)
-> { status: 'succeeded',
published_urls: [ { slug: 'guides/intro', language: 'en',
url: 'https://example.com/guides/intro/' } ] }

Errores comunes

  • duplicate_draft_target — dos borradores pendientes apuntan a la misma URL (slug, idioma). publish rechaza y no genera un token; el campo collisions[] del error enumera las rutas de los borradores en conflicto. Conserva uno y usa discard-draft en el resto (o cambia un slug), luego publica de nuevo. El mismo slug en dos idiomas diferentes está bien.
  • Token caducado o usadoconfirmation_token es de un solo uso con una TTL de 5 minutos. Vuelve a ejecutar publish.
  • El manifiesto cambió desde la prueba — un borrador o el tema se movió entre publish y publish-confirm. La confirmación se aborta; vuelve a ejecutar publish.
  • path obsoleto — un ID de documento anterior a una publicación ya no resuelve. Vuelve a resolver mediante (slug, idioma).

Consulta la referencia de errores para ver la lista completa.

Relacionado

Última actualización: