Cómo convive un bot que publica por la API de GitHub con cambios hechos a mano en el mismo repo: tokens efímeros, concurrencia optimista y reglas de push.
El escenario: un bot y una persona escribiendo en el mismo repositorio
El blog de esta web lo publica un bot. Cada pocos días escribe un post y lo sube al repositorio de la web: la página del post, el índice del blog y el sitemap. En ese mismo repositorio trabajo yo a mano: cambios de diseño, páginas nuevas, correcciones. Dos escritores sobre los mismos ficheros, y uno de ellos no avisa antes de escribir.
Primera lección: un token que caduca en silencio
El sistema de publicación automática que usaba antes, para otros blogs míos, subía los posts con git push y un token personal de acceso de GitHub. Los tokens de grano fino caducan, y ese caducó a los 30 días. La publicación automática estuvo unos cinco días caída en silencio: el push fallaba, el error quedaba escrito en un log y no saltaba ninguna alerta. Lo descubrió una auditoría, no un aviso.
Lo sustituí por una GitHub App. La diferencia es de diseño, no de comodidad: la App firma con su clave privada un JWT de vida muy corta (minutos), lo cambia por un token de instalación que dura una hora, y el bot lo cachea y lo renueva antes de que caduque. No hay credenciales de larga duración que puedan morir en silencio. Y la clave privada nunca se escribe en un registro.
Segunda lección: escribir sin pisar lo que no has visto
El bot no usa git: escribe por la API de contenidos de GitHub, fichero a fichero. Esa API tiene un mecanismo que resuelve la mitad del problema de la concurrencia: para actualizar un fichero hay que enviar el identificador (el sha) de la versión que leíste. Si alguien lo ha cambiado desde entonces, ese sha ya no es el actual y GitHub rechaza la escritura.
Eso es concurrencia optimista, y cambia el tipo de fallo. En lugar de "el bot pisó el cambio de otro", el fallo pasa a ser "el bot no pudo publicar y lo dice". El error se clasifica como no reintentable: reintentar a ciegas la misma escritura con el mismo sha no puede salir bien. Y el post queda registrado como fallido, a la vista, y el bot avisa por Telegram en el momento: justo lo que faltaba con el token.
Para las páginas de post, que son ficheros nuevos, la API funciona al revés: crear un fichero es escribir sin sha. Si el fichero ya existe (por ejemplo, al republicar un post), el bot lee primero su sha y lo actualiza en lugar de crear un duplicado.
Tercera lección: el orden de las escrituras es parte del diseño
Publicar un post son hasta tres escrituras: la página, el índice y el sitemap. La API de contenidos no permite hacerlas en un único commit atómico, así que el orden decide qué pasa si algo falla a mitad:
- Primero la página. Si falla, no se toca nada más y no queda un teaser apuntando a una página que no existe.
- Después el índice del blog. A partir de aquí el post es visible.
- El sitemap, el último y sin tumbar nada. Si falla, el post ya está publicado y el fallo se registra para corregirlo aparte.
Un único commit con varios ficheros (con la API de árboles de git) sería más limpio y lo tengo apuntado como mejora. Mientras tanto, el orden garantiza que un fallo deja el sitio coherente, aunque incompleto.
El lado humano: las mismas reglas, sin API que las imponga
Cuando trabajo a mano uso git normal, y ahí nadie me obliga a enviar el sha correcto. Así que me impongo las reglas equivalentes:
- Fetch antes de push, y comprobar. Antes de subir, traigo el estado remoto y compruebo que el último commit remoto es el que espero. Si el bot ha publicado entretanto, no subo nada y reviso.
- Nada de force-push sin confirmarlo antes. Un force-push sobre la rama principal borraría los commits que el bot haya hecho desde mi último fetch, y lo haría sin avisar.
- Lejos de la hora del bot. Conozco a qué hora publica, así que los cambios que tocan el índice o el sitemap no los hago cerca de esa hora.
- Si toco lo que el bot también escribe, regenero justo antes de aplicar. Un cambio preparado por la noche sobre el índice del blog puede quedarse viejo si el bot ha publicado por la mañana. Se regenera sobre el estado actual antes de copiarlo.
Resultado
El bot publica sin credenciales que caduquen, no puede sobrescribir un cambio que no ha visto, y cuando algo sale mal deja el sitio en un estado coherente y un registro de qué pasó. En el lado humano, un push que no cuadra con lo esperado se para en lugar de forzarse.
No es un sistema sofisticado. Es tratar el repositorio como lo que es cuando hay un bot dentro: un recurso compartido con más de un escritor. Así funciona el blog automático con IA que ofrezco como servicio.
Daniel · Arquitecto Digital. Los sistemas los diseño y dirijo yo; la implementación la hago con asistentes de IA de programación.