Introducción

Los pipelines de CI/CI suelen ser frágiles: un paso falla, y el entire workflow se relanza desde cero, desperdiciando tiempo y recursos. Además, la sintaxis declarativa en YAML o TOML limita la lógica condicional y el manejo de errores, obligando a recurrir a scripts externos o soluciones ad hoc. Cloudflarepropone un enfoque radicalmente distinto con su nuevo SDK @cloudflare/ci, anunciado el 5 de agosto de 2026: definir pipelines como código TypeScript que se ejecuta sobre Cloudflare Workflows, aprovechando su capacidad de checkpoint y replay para ofrecer retries durables por paso y ejecución concurrentes por defecto.

Qué ocurrió

Cloudflare publicó el repositorio cloudflare/ci bajo licencia Apache 2.0, un SDK que permite definir pipelines de CI como workflows writing TypeScript. Cada paso del pipeline se ejecuta como un paso de Workflow, lo que hereda tres características clave de la plataforma:

  • Retries durables: si un paso falla, se reintenta automáticamente con el estado preservado (variables de entorno, filesystem, etc.). Además, un pipeline puede reiniciarse desde el paso fallido, sin repetir los anteriores.
  • Ejecución concurrente: los pasos se inician en paralelo por defecto; la concurrencia se limita explícitamente cuando es necesario (ej: deploy después de build).
  • Aislamiento: cada comando se ejecuta en un contenedor Sandbox, que proporciona un filesystem aislado y snapshots para caching.
  • El SDK está orientado al runtime de Cloudflare Workers (no Node.js) y genera código TypeScript compatible con bundlers como Wrangler. Actualmente, la integración con repositorios se hace a través de Cloudflare Artifacts (aún en private beta), pero el roadmap incluye soporte para otros sistemas de control de versiones, primitives de deploy y preview, y manejo de monorepos.

    Impacto para DevOps / Infraestructura / Cloud / Seguridad

    Para equipos que ya operan en Cloudflare, este SDK simplifica la integración de CI/CD con el resto de la plataforma. Un pipeline puede usar Durable Objects para estado compartido, R2 para caching de dependencias, y Workers AI para tareas como análisis de logs o generación de reports. La observabilidad ganada es granular: cada paso emite logs y métricas en Cloudflare’s dashboard, y los retries durables reducen el tiempo de recovery ante fallos transitorios (ej: timeouts en installs de dependencias).

    Fuera del ecosistema Cloudflare, las ideas transferibles son dos:

  • Retries por paso: en lugar de relanzar todo el pipeline, reintentar solo el paso fallido con su contexto intacto. Esto optimiza costos (menor consumo de minutos de CI) y tiempo (feedback más rápido para desarrolladores).
  • Agente de autoreparación: Cloudflare muestra un ejemplo de self-healing donde un agente externo (usando Workers AI y el modelo Kimi de Moonshot) analiza el error del runner, propone un patch, lo commitea a una branch y deja el pipeline original en estado fallido hasta que un humano apruebe el merge. Este patrón puede adaptarse a otras plataformas para automatizar la triage de fallos comunes.
  • El riesgo principal es el lock-in: el SDK depende de Workflows, Sandboxes y otros servicios de Cloudflare. Migra un pipeline a esta solución y migrarlo a otro proveedor requerá reescribirlo. Además, la falta de redaction de secrets en los logs (CiRunnerResult.logs) exige extremar las precauciones con credenciales y tokens.

    Detalles técnicos

    Arquitectura

    • Runtime: Los pipelines se ejecutan en el runtime de Workers (ES2025), no Node.js. El SDK exporta funciones que Workflows invoca como pasos.
    • Dependencias: Requiere @cloudflare/workers (v1.0.0 o superior) y un bundler compatible con Workers (ej: Wrangler ≥ 2.20.0).
    • Caching: El cache de dependencias se implementa con snapshots de Sandbox almacenados en R2. Para habilitarlo, el pipeline debe declararlo explícitamente:

    import { definePipeline } from «@cloudflare/ci»;

    const pipeline = definePipeline({
    steps: [
    {
    name: «install»,
    cache: { key: «deps», restore: true },
    run: «npm install»,
    },
    {
    name: «test»,
    cache: { key: «deps», restore: true },
    run: «npm test»,
    },
    ],
    });

    • Triggers: Los pipelines se activan mediante el evento cf.artifacts.repo.pushed en la configuración de Wrangler:

    [triggers]
    artifacts = { events = [«cf.artifacts.repo.pushed»] }

    Limitaciones

    • Idempotencia: Los comandos en pasos con retries deben ser idempotentes. Por ejemplo, un deploy que suba archivos a S3 con el mismo nombre cada vez duplicará el contenido en un retry.
    • Secrets: Los logs del runner incluyen la salida cruda de los comandos. Cloudflare recomienda usar Wrangler secrets para inyectar variables sensibles y evitar loggearlas.
    • Almacenamiento: Los snapshots de Sandbox para caching tienen un límite de 100 MB por paso (límite actual de Sandbox).

    Ejemplo de pipeline

    import { definePipeline, runCommand } from «@cloudflare/ci»;

    export default definePipeline({
    steps: [
    {
    name: «lint»,
    run: () => runCommand(«npm run lint»),
    },
    {
    name: «typecheck»,
    run: () => runCommand(«npm run typecheck»),
    },
    {
    name: «test»,
    run: () => runCommand(«npm test»),
    },
    {
    name: «build»,
    needs: [«lint», «typecheck», «test»], // Espera a que los pasos anteriores terminen
    run: () => runCommand(«npm run build»),
    },
    {
    name: «deploy»,
    needs: [«build»],
    run: () => runCommand(«wrangler deploy»),
    },
    ],
    });

    Qué deberían hacer los equipos técnicos

    Si ya usás Cloudflare

  • Evaluá la integración con Artifacts: Si tenés acceso a Cloudflare Artifacts (private beta), probá el SDK en un repository no crítico. Verificá que los triggers cf.artifacts.repo.pushed se configuraron correctamente en wrangler.toml.
  • Migrá pipelines simples: Convertí un pipeline básico (lint → test → build → deploy) para comparar el tiempo de ejecución y la experiencia de debug. Usá wrangler dev para testear localmente.
  • Implementá caching: Añadí cache a los pasos de install y build para reducir tiempos. Monitoreá el uso de R2 (el caching consume storage).
  • Revisá idempotencia: Auditá los comandos de todos los pasos (especialmente deploy, notificaciones, etc.) para asegurarte de que son idempotentes.
  • Si no usás Cloudflare

  • Analizá el patrón de retries durables: Evaluá si tu herramienta de CI actual soporte retries por paso (ej: GitHub Actions con retries en cada job, GitLab CI con retry). Si no, considerá alternativas como Dagger (que también ofrece retries por paso y caching por contenido).
  • Explorá el ejemplo de self-healing: El ejemplo de autoreparación muestra cómo integrar un LLM para proponer fixes. Adaptá la idea a tu stack (ej: usar GitHub Copilot API + un script en Python).
  • Compará trade-offs: Workflows + Sandboxes ofrecen retries durables y serverless, pero limitan el entorno de ejecución (no contenedores arbitrarios). Dagger, en cambio, corre en contenedores OCI, pero requiere gestionar un runner.
  • Para todos

    • Protectá secrets: Si implementás pipelines en TypeScript (o cualquier lenguaje), asegurate de:

    – No hardcodear secrets en el código.

    – Usar variables de entorno inyectadas por el runner (ej: process.env.MY_SECRET).

    – Mascar secrets en logs (el SDK de Cloudflare no lo hace automáticamente).

    Conclusión

    @cloudflare/ci es un experimento interesante que lleva la programación de pipelines al siguiente nivel: de la configuración declarativa al código con superpoderes (retries durables, estado persistente, concurrencia). Para equipos en Cloudflare, puede simplificar el CI/CD y aprovechar mejor la plataforma. Para el resto, las lecciones más valiosas son los patrones de resiliencia (retries por paso) y autoreparación, que pueden implementarse en otras herramientas. El principal sacrificio es la portabilidad: adoptar este SDK es una apuesta fuerte por el ecosistema Cloudflare.

    Fuentes

    • https://www.infoq.com/news/2026/08/cloudflare-ci-code-workflows/

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *