Run CI/CD for millions of repos — on your platform, on Cloudflare
Captured source
source ↗Run CI/CD for millions of repos — on your platform, on Cloudflare | The Cloudflare Blog
Skip to content
We are moving toward a world in which you can store, build, test, and deploy your code fully on Cloudflare. We built the first piece with Artifacts , versioned code storage that scales to millions of repos. We have stitched the store, build, and deploy steps together with the CI SDK , built on Cloudflare Workflows , so that you can run your continuous integration (CI) pipeline on Cloudflare. You can send artifact push events directly to your Workflow, triggering an instance of its execution — a CI job, essentially — through a new events field in your wrangler configuration file. Then, directly from the Workflow with @cloudflare/ci installed, you can: Automate builds: compile code from your Artifacts repo in a safe, isolated environment Run linters and typechecks: enforce code style, catch type errors, and flag any potential issues Cache dependencies: run your install once and cache dependencies across steps in the CI job Execute unit tests: verify that each piece of your code works as expected Self-heal: integrate an AI review agent to catch broken steps in your build and push commits to fix Deploy conditionally: automatically deploy your code, only if your build step is successful
Today, everyone is building a platform, whether it’s an internal vibe coding platform or an extension of your customer-facing product via customization through code. Platforms are now using millions of repos on Artifacts to store their code, and their customers’ code, and version control across the two. But every team has their own needs for a continuous integration and deployment pipeline. For platforms, they might want to define a CI job for their own code differently from that of their customers. Many of the end customers building on these platforms don’t want the extra headache of managing their continuous integration and continuous deployment (CI/CD) pipeline. Instead, the platform can manage the build process on their customers’ behalf: write the CI/CD pipeline once and share it across all the applications that their customers are building. Some of the platform’s customers might want to define their own CI; if so, they can write their own Workflow and run custom CI jobs on just their repo, facilitated by dynamic workflows . The beauty is, you don’t have to pick and choose: both platform-managed and custom CI can run at the same time, in the same namespace.
A CI/CD pipeline is just a Workflow Before today, we had all the pieces to allow platforms to wire their CI/CD pipeline together on Cloudflare. Now, we’re bringing a better developer experience to make it simple. A CI/CD pipeline — commonly orchestrated with GitHub Actions — is a series of steps that run in a specific order where, if any step fails, you stop running the pipeline and report the error. In essence, a CI/CD pipeline is just a Workflow. CI/CD, when defined by a YAML file, can get complicated quickly, given the constraints that so often lead to YAML fatigue. But each step in a CI/CD pipeline can translate simply to a Workflow step.do() . Instead of YAML, you can define your CI/CD pipeline in Typescript for greater customization and configurability. We are launching new tools in the CI SDK that allow you to run each step in your CI pipeline (e.g. build , lint , and typecheck ) in a safe, isolated environment, built directly on Cloudflare’s developer platform via Workflows and the Sandbox SDK . Plus, you can now kick off a CI job directly on push instead of configuring an event subscription, a queue, and a queue consumer. Previously, you’d have to call the Sandbox API directly and manage state yourself across different steps in the CI pipeline. The SDK allows you to run each sandboxed command in its own Workflow step, providing the retries and timeouts built into Cloudflare Workflows. You can also speed up your CI pipeline by caching step results — for example, your install step — so that you don’t need to reinstall for all subsequent operations. Dependency caching reduces the latency of your CI/CD pipeline since every CI step won’t need to rerun the install.
To define your CI job, all you need to do is: Define your install step for any dependencies (external packages or tools that your CI job needs), such as bundlers (e.g. esbuild ), linters (e.g. eslint ), or test runners (e.g. vitest ). Specify the command for each step in the CI job (e.g. bun run build , bun run test , bun run lint ). With your dependencies cached, each CI step can execute in parallel, reducing the latency of the overall run. Pass wrangler deploy in a deploy step. Your Worker will automatically deploy when the CI pipeline passes.
const deps : CiRunnerResult = await ci. runner ({ name: 'install' , command: 'bun install --frozen-lockfile' , cache: { inputs: [ 'package.json' , 'bun.lock' ] }, });
await Promise . all ([ deps. runner ({ name: 'lint' , command: 'bun run lint' }), deps. runner ({ name: 'test' , command: 'bun run test' }), deps. runner ({ name: 'typecheck' , command: 'bun run typecheck' }), deps. runner ({ name: 'build' , command: 'bun run build' }), ]);
await deps. runner ({ name: 'deploy' , command: 'bun wrangler deploy' , cloudflareCredentials: { accountId: this .env. CLOUDFLARE_DEPLOY_ACCOUNT_ID , }, }); Writing your own CI pipeline in a Workflow allows you to customize as much as you want. For example, you could call an agent from your CI Workflow to give your CI jobs self-healing functionality: if a step in your build errors, the agent can fix it automatically, and push a commit for your approval.
Try an example of self-healing CI Workflows with Project Think: https://github.com/cloudflare/ci/blob/main/examples/self-healing
Write your own CI Workflow To write your own CI Workflow, get started with import { CIWorkflow } from@cloudflare/ci . Start with an install step: Download your dependencies, including any external tools or libraries that your CI steps will need (e.g. vite , react ). Specify your lockfile, which tracks whether your dependencies have changed. Cache your dependencies via a sandbox snapshot so that all subsequent steps have access. The snapshot will be stored in an R2 bucket on your account.
const deps = await ci. runner ({ name: 'install' , command: 'bun install --frozen-lockfile' , cache: { inputs: [ 'package.json' , 'bun.lock' ] }, }); Then define steps for the build and checks, each executed in its own safe,...
Excerpt shown — open the source for the full document.
Notability
notability 2.0/10Low traction, general CI/CD post, not AI research.