↑ top
← Back to blog
EN | ES

CI Que Escribe de Vuelta al Repositorio

El patrón donde CI genera artefactos, los commitea a main, y usa [skip ci] para evitar loops infinitos. Cuándo es la herramienta correcta y cuándo no.

✦ AI Summary

El repositorio es la fuente; CI es un consumidor. Cuando publica un post, genera archivos, los commitea de vuelta a `main', y hace push.

CI Que Escribe de Vuelta al Repositorio

La mayoría de los pipelines de CI son unidireccionales: el código entra, los artefactos salen. Los tests corren, las imágenes Docker se construyen, los despliegues suceden. El repositorio es la fuente; CI es un consumidor.

El CI de este sitio también corre en la otra dirección. Cuando publica un post, genera archivos, los commitea de vuelta a main, y hace push. El repositorio es tanto la fuente como el destino.

Aquí está el porqué, cómo funciona, y cuándo no deberías hacer esto.

Por Qué CI Escribe de Vuelta

Publicar un post implica dos tipos de salidas: cosas que deberían ser efímeras (el worker desplegado) y cosas que deberían estar versionadas (los artefactos de publicación).

Los artefactos que CI genera:

  • scripts/kv-seed.json — los datos KV serializados para todos los posts (índice, contenido, resúmenes)
  • Actualizaciones de frontmatter — publish.js establece image: true en el frontmatter del post después de subir una imagen hero

Estos necesitan estar en el repositorio por dos razones:

  1. Recuperación. Si se pierden los datos de KV, el archivo seed es la fuente de verdad. Sin él, necesitarías regenerar todo desde cero.

  2. Futuras ejecuciones de CI. Una ejecución posterior que solo cambia src/worker.js no debería necesitar reprocesar imágenes y resembrar KV. Pero debería poder resembrar KV si es necesario. El archivo seed lo hace posible sin una publicación completa.

El Patrón [skip ci]

La parte peligrosa de escribir de vuelta al repositorio: si CI hace push de un commit y ese commit dispara CI, obtienes un loop infinito. Los commits siguen disparando commits.

La solución es [skip ci] en el mensaje del commit:

yaml- name: Commit artifacts
  run: |
    git config user.name "github-actions[bot]"
    git config user.email "github-actions[bot]@users.noreply.github.com"
    git add scripts/kv-seed.json posts/
    git diff --staged --quiet || git commit -m "chore: update publish artifacts [skip ci]"
    git push

GitHub Actions y la mayoría de proveedores de CI reconocen [skip ci] (o [ci skip]) en un mensaje de commit y omiten el workflow. El commit llega a main pero no dispara otra ejecución.

git diff --staged --quiet || git commit es la guarda de idempotencia: si nada cambió (sin imágenes nuevas, sin frontmatter modificado), no hay commit. CI no hace push de commits vacíos.

El Trigger Condicional

No todo push a main debería ejecutar el pipeline completo de publicación. Los cambios en código fuente no necesitan resembrar KV. Los cambios en posts no necesitan desplegar el worker.

Los filtros de ruta de GitHub Actions manejan esto:

yamlon:
  push:
    branches: [main]
    paths:
      - "posts/**"
      - "images/**"
      - "src/**"
      - "scripts/**"
      - "static/**"

Dentro del workflow, cada paso principal verifica qué archivos cambiaron:

yaml- name: Publish posts
  if: contains(steps.changed.outputs.files, 'posts/') || contains(steps.changed.outputs.files, 'images/')
  run: npm run publish

- name: Deploy worker
  if: contains(steps.changed.outputs.files, 'src/')
  run: npm run deploy

Un commit que solo cambia posts/mi-post.md ejecuta publish pero no deploy. Un commit que cambia src/worker.js ejecuta deploy pero no publish. El auto-commit con [skip ci] no dispara nada.

El Riesgo de Conflictos de Merge

Escribir de vuelta a una rama a la que también hacen push los desarrolladores crea una race condition. Si hago push a main al mismo tiempo que CI está intentando hacer push de su auto-commit, uno de ellos fallará con un error de non-fast-forward.

Mitigaciones:

  • Usar git pull --rebase antes del push de CI
  • La ventana de conflicto es pequeña (segundos entre el push original y el auto-commit)
  • Para un repositorio de un solo desarrollador, raramente es un problema en práctica

Si tienes un equipo haciendo push frecuentemente a main, este patrón se vuelve más riesgoso. Se necesitaría un mecanismo de cola o bloqueo.

Cuándo No Hacer Esto

No escribas de vuelta si los archivos generados son grandes. Los archivos seed de KV para un blog son pequeños. Si generas megabytes de artefactos en cada commit, el repositorio crece rápidamente y git clone se vuelve lento.

No escribas de vuelta si los archivos cambian en cada ejecución. Timestamps de build, checksums que incluyen fechas, cualquier cosa no determinista creará un commit en cada ejecución de CI aunque nada haya cambiado realmente.

No escribas de vuelta si tienes protección estricta de ramas. Muchos equipos requieren PRs para todos los cambios a main. Un auto-commit de CI omite eso. O añade el bot de CI como excepción o usa almacenamiento diferente de artefactos (S3, Artifacts, una rama separada).

El patrón es un atajo pragmático que funciona bien para proyectos pequeños con workflows simples. Se rompe a escala. Conoce los límites antes de adoptarlo.

Was this helpful?