在您的平台上、在 Cloudflare 上为数百万仓库运行 CI/CD

我们正朝着一个可以在 Cloudflare 上完全存储、构建、测试和部署代码的世界迈进。我们构建了第一部分,即 Artifacts,这是一个可扩展至数百万仓库的版本化代码存储。
我们通过 CI SDK 将存储、构建和部署步骤连接在一起,该 SDK 构建在 Cloudflare Workflows 之上,以便您可以在 Cloudflare 上运行持续集成(CI)管道。您可以直接将 artifact push 事件发送到您的工作流,通过 wrangler 配置文件中的新 events 字段触发其实例执行——本质上就是一个 CI 作业。然后,直接从安装了 @cloudflare/ci 的工作流中,您可以:
- 自动化构建:在安全、隔离的环境中编译来自 Artifacts 仓库的代码
- 运行 linter 和类型检查:强制执行代码风格,捕获类型错误,并标记任何潜在问题
- 缓存依赖:运行一次
install,并在 CI 作业的各个步骤之间缓存依赖 - 执行单元测试:验证代码的每个部分是否按预期工作
- 自愈:集成 AI 审查代理以捕获构建中的失败步骤,并推送提交进行修复
- 条件部署:仅在构建步骤成功时自动部署代码

如今,每个人都在构建平台,无论是内部的 vibe 编码平台,还是通过代码定制扩展面向客户的产品。平台现在使用 Artifacts 上的数百万个仓库来存储其代码和客户代码,并对两者进行版本控制。但每个团队对持续集成和部署管道都有自己的需求。对于平台而言,他们可能希望为自己的代码定义 CI 作业,与为客户定义的作业不同。
许多在这些平台上构建的最终客户不想额外费心管理他们的持续集成和持续部署(CI/CD)管道。相反,平台可以代表客户管理构建过程:编写一次 CI/CD 管道,并在客户构建的所有应用程序中共享。一些平台的客户可能希望定义自己的 CI;如果是这样,他们可以编写自己的工作流,并仅在其仓库上运行自定义 CI 作业,这由动态工作流促进。美妙之处在于,您不必做出选择:平台管理的 CI 和自定义 CI 可以同时在同一命名空间中运行。

CI/CD 管道就是一个工作流
在此之前,我们已经拥有所有组件,可以让平台在 Cloudflare 上连接其 CI/CD 管道。现在,我们正在带来更好的开发者体验,使其变得简单。
CI/CD 流水线——通常使用 GitHub Actions 编排——是一系列按特定顺序运行的步骤,如果任何步骤失败,则停止运行流水线并报告错误。本质上,CI/CD 流水线就是一个工作流。CI/CD 当由 YAML 文件定义时,由于经常导致 YAML 疲劳的约束,可能会很快变得复杂。但 CI/CD 流水线中的每个步骤都可以简单地转换为工作流的 step.do()。
您可以使用 TypeScript 而不是 YAML 来定义 CI/CD 流水线,以获得更大的定制性和可配置性。
我们正在推出 CI SDK 中的新工具,允许您在安全、隔离的环境中运行 CI 流水线中的每个步骤(例如 build、lint 和 typecheck),该环境直接构建在 Cloudflare 开发者平台上,通过 Workflows 和 Sandbox 实现。此外,您现在可以直接在推送时启动 CI 作业,而无需配置事件订阅、队列和队列消费者。
Sandbox SDK
以前,您必须直接调用 Sandbox API 并自行管理 CI 流水线中不同步骤之间的状态。SDK 允许您在各自的工作流步骤中运行每个沙箱命令,提供 Cloudflare Workflows 内置的重试和超时功能。
您还可以通过缓存步骤结果(例如安装步骤)来加速 CI 流水线,这样您就不需要为所有后续操作重新安装。依赖缓存减少了 CI/CD 流水线的延迟,因为每个 CI 步骤都不需要重新运行安装。

要定义您的 CI 作业,您只需:
- 为任何依赖项(CI 作业所需的外部包或工具)定义
install步骤,例如打包器(如esbuild)、linter(如eslint)或测试运行器(如vitest)。 - 为 CI 作业中的每个步骤指定命令(例如
bun run build、bun run test、bun run lint)。在依赖项被缓存的情况下,每个 CI 步骤可以并行执行,从而减少整体运行的延迟。 - 在
deploy步骤中传递wrangler deploy。当 CI 流水线通过时,您的 Worker 将自动部署。
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,
},
});
在 Workflow 中编写自己的 CI 流水线,可以让您随心所欲地进行自定义。例如,您可以从 CI Workflow 中调用一个 agent,为您的 CI 作业赋予自愈功能:如果构建中的某个步骤出错,agent 可以自动修复,并推送提交供您审批。

尝试使用 Project Think 实现自愈 CI Workflow 的示例:https://github.com/cloudflare/ci/blob/main/examples/self-healing
编写自己的 CI Workflow
要编写自己的 CI Workflow,请从 import { CIWorkflow } from@cloudflare/ci 开始。
.
从一个 install 步骤开始:
- 下载您的依赖项,包括 CI 步骤所需的外部工具或库(例如
vite、react)。 - 指定您的 lockfile,用于跟踪依赖项是否发生变化。
- 通过 sandbox snapshot 缓存您的依赖项,以便所有后续步骤都能访问。快照将存储在您账户的 R2 bucket 中。
const deps = await ci.runner({
name: 'install',
command: 'bun install --frozen-lockfile',
cache: { inputs: ['package.json', 'bun.lock'] },
});
然后为构建和检查定义步骤,每一步都在各自安全、隔离的沙箱环境中执行。

默认情况下,工作流中的每个步骤都是独立启动的,这意味着除非另有指定,否则这些步骤将并发执行。并行运行每个步骤可以减少 CI 运行的延迟。为了确保在 CI 管道继续之前完成所有检查(例如,在部署步骤开始之前完成 build、lint、test 和 typecheck),请将其包裹在 Promise.all() 中:
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' }),
]);
现在,要实际触发你的 CI 工作流,需要在 Worker 的 wrangler 配置中添加一个 events 字段,与你的 Workflow 和 Artifact 绑定一起。events 字段是 triggers 字段中支持的一个新字段。
你已经可以通过 Cloudflare Queues 通过事件订阅 订阅 Artifacts,并在每次有推送事件时启动构建管道。但这需要设置事件订阅、队列、消费者和队列处理器。现在,你可以将该事件直接指向一个 Workflow——每次该事件触发时,它都会触发一个 Workflow 实例。
将 CI Workflow 指定为 artifact push 触发器的目标,即可在每次 cf.artifacts.repo.pushed 事件发生时自动触发一个 Workflow 实例。每次 CI 运行都会显示为一个 Workflow 实例,因此你可以直接在 Workflows 仪表板中查看其逐步执行情况和可观测性。这是一个以 Artifacts 为先的集成;即将推出,types 将支持来自你 Cloudflare 账户中各种来源的事件,以便在整个产品套件中进行程序化消费。
如果你希望在你的命名空间中的每个仓库上运行 CI 工作流——例如,如果你是一个为所有客户仓库运行 CI 的平台——请省略 repoName,只在 filter 中指定 namespace。
{
"triggers": {
"events": [
{
"type": "cf.artifacts.repo.pushed",
// filter 是可选的。如果你不设置 repoName,我们将在你的 Artifacts 命名空间中的任何仓库的每次推送时运行相同的工作流
"filter": {
"namespace": "CI",
"repoName": "my-repo"
},
"target": {
"type": "workflow",
"workflow_name": "ci-workflow"
}
}
]
}
}
要完全配置您的 CI 工作流,请为支撑管道的每个基础设施部分添加绑定:artifacts、workflows、containers 和 durable_objects(以及 exports 配置)绑定(以访问您的沙箱),如果您使用 cache,还需要添加 r2 绑定。R2 绑定是必需的,因为您的 install 步骤沙箱的快照存储在一个 存储桶 中。
自愈 CI 运行
要让您的 CI 作业能够自愈,您需要两个部分:LLM 及其代理框架。在上面的示例中,我们包含了一个 Think 代理,使用 Workers AI 来捕获管道中的错误并代表您运行修复。您的 CI 作业可以在远程运行和重新运行——无需打开笔记本电脑盯着看,也无需每隔几分钟检查一次。相反,Cloudflare 在云端处理它,在容器中与 CI 步骤一起运行您的修复代理。您无需照看 CI 作业、手动修复并重新运行管道,只需在代理完成修复后合并提交即可。
要设置一个自愈 CI 管道的代理,请为您的 Think 代理添加一个 Durable Object 绑定:
"durable_objects": {
"bindings": [
{
"name": "HEALER",
"class_name": "Healer",
},
],
},
创建你的 Think agent — Healer
— 通过扩展 HealingAgent
类,该类包含一个 heal
方法供你在失败时调用。传入你想要使用的任何模型:
export class Healer extends HealingAgent {
getModel() {
return '@cf/moonshotai/kimi-k2.7-code';
}
}
然后,将你的步骤包裹在 try/catch 块中,当失败时触发修复代理:
let deps: CiRunnerResult;
try {
// 只安装一次,然后从共享和缓存的快照运行独立的检查
deps = 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' }),
]);
} catch (failure) {
// 这同时捕获失败的沙箱命令和普通的工作流错误。
// 只有由 runner 报告的错误才应该被修复;其余的错误重新抛出。
if (!isCiRunnerFailure(failure)) {
throw failure;
}
// 将错误传递给代理,以便它可以修复它
const healed = await step.do(
'heal',
{ retries: { limit: 0, delay: 0 }, timeout: '5 hours' },
async () => {
const healer = await getAgentByName(this.env.HEALER, event.instanceId);
using result = await healer.heal({
failure: enrichFailure({ failure, event, baseBranch }),
prompt: '修复所有观察到的失败,而不削弱验证。',
});
// 报告修复分支、其提交以及所花费的步骤数。
const { branch, commit, steps } = result;
return { branch, commit, steps };
}
);
// 源运行保持失败;其验证的修复位于另一个分支上
throw new CiRunFailedWithFix(failure, healed);
}
await deps.runner({
name: 'deploy',
command: 'bun wrangler deploy',
});
此示例演示了一个自愈的 CI 流水线,但实际上,“自带工作流”模型允许您随心所欲地自定义 CI 作业。这可以成为添加安全规则、过滤器或条件 CI 步骤的地方。使用 BYO-W 模型,平台可以根据每个单独用例,跨不同团队、客户或应用配置其 CI/CD 流水线。
使用工作流的好处
通过在 Cloudflare Workflow 上运行 CI 流水线,您自动继承:
弹性重试(持久执行): 如果 CI 作业中的任何步骤失败,它将自动重试并保留状态,这意味着不会丢失任何进度。每个步骤都支持自定义重试和超时行为,因此您可以为每个步骤定义不同的失败逻辑。此外,您可以从特定步骤重新开始,因此例如如果仅 lint 失败,您不必重新运行整个 CI 流水线。
工作流可观测性: 在 Workflows 仪表板中逐步检查您的 CI 作业,其中每个实例都会显示步骤及其输入、输出以及墙钟时间和 CPU 时间。您可以通过仪表板中的工作流图可视化您的 CI 作业,从而轻松查看哪些步骤是并发运行还是顺序运行。您还可以通过Workers Observability 和 GraphQL 检查 Workflows 日志,以更深入地了解 CI 作业的运行情况。
代码的力量: 通过在 Workflow 中运行 CI,您可以为任何想要的内容编写步骤。例如,您可能希望将 AI 代码审查器作为 CI/CD 流水线的一部分运行。您可以通过 Workflows 调用您的代码审查代理——或处理任何您可以放入代码中的自定义逻辑——使用 step.do()。其他示例可能包括将构建产物写入 R2,并在 CI 失败、完成或合并到 main 时发送电子邮件。
下一步
CI/CD 流水线只是一个工作流——借助 CI SDK,您可以用简单的 TypeScript(而不是僵化的 YAML)在您自己的代码和客户的代码中定义 CI。基于 Cloudflare Workflows 原语,您可以定义任何您想要的逻辑,无论是像我们的 Think 示例那样的修复代理,还是将构建产物写入 R2。在 Workflows 上运行 CI 有助于弥合存储(通过 Artifacts)、构建和部署之间的差距。作为平台,这使您能够轻松管理自己代码以及代表客户执行的每个步骤。
请求加入 Artifacts 私有测试版,并开始使用我们的Workflows CI 指南。如果您有任何功能请求或发现任何错误,请通过加入 Cloudflare Developers Discord 社区直接与 Cloudflare 团队分享您的反馈。
接下来会发生什么:
- Workers 和 Workers for Platforms 的直接集成:
build.preview()和build.deploy()原语,用于在推送到 main 时自动部署,并在推送到非默认分支时创建预览。 - 渐进式部署:通过 Workflows 管理基于百分比的发布,以自定义您的部署进度和回滚逻辑。
- Monorepos:使用一个 CI 流水线简化多 Worker 部署的管理。
- 触发器:从不同来源发送推送事件,以从任何版本控制系统(不仅仅是 Artifacts)在仓库上运行 CI 作业。
