把 cf 放进自动化脚本:认证、构建产物与验收怎么安排

整理 cf 在脚本和 CI 中的认证、输出、删除行为及构建产物使用方式,让自动化结果能够检查与追溯。

土耳其 VDS,完整 root 权限|BRNCHOST · 自管服务器
建站开服,云上轻松起步|雨云 RCS · 宝塔 / 1Panel 预装
低价年付,搭起你的应用|RackNerd · KVM VPS · SSD 存储
香港轻量,按配置选型|晚安云 · 云服务器
NVMe 机型,关注磁盘 I/O|野草云 · 香港 VPS
大陆优化,连接海外应用|搬瓦工 · CN2 GIA / CTGNet 套餐
读文件、写文档、跑任务|WorkBuddy · AI 工作台
CVM 云主机,配置按需选|腾讯云 · 云服务器
中国方向优化,认准系列|DMIT · Premium / CN2 GIA
双 ISP 住宅 VPS|丽萨主机 · 原生 IP · 多地区产品
每周自动异地备份|Evoxt · 高频 CPU · 云服务器

手动执行一条命令,失败了可以马上看报错。放到定时任务或 CI 之后,事情会变得不同:没人回答交互问题,环境变量可能与本机不同,命令成功退出,也不一定做完了预期操作。

Cloudflare 新 CLI cf 默认提供便于处理的 JSON 结果,并支持 API Token 认证,适合写入自动化。但它目前仍在 Beta,第一次接入生产流程时,最需要提前处理的是版本、目标、凭据和结果检查。

不要让脚本依赖你的浏览器登录

本机使用 cf auth login 很方便,无人值守运行则用 CLOUDFLARE_API_TOKEN。同时显式提供 account ID;区域级任务还应提供 zone,避免依赖某次手动选择留下的缓存。

官方文档要求 Node.js 22.18 或以上。在项目中安装指定版本,提交锁文件,再让自动化使用 npm ci:

npm install --save-dev --save-exact cf@1.0.0-beta.6
npx cf --version

这里的版本是资料核对时的版本,不是永远推荐的版本。升级依赖时,应独立检查命令与配置变化,再更新锁文件;不要让例行部署顺便漂移到一个没有验证过的 Beta。

Token 只给作业实际需要的权限。CI 的秘密变量不要写进仓库,也不要通过 set -x 打印出来。构建检查若不需要远程访问,就不要给该步骤注入凭据。CI 官方指南

先区分资源脚本与项目发布

一个导出 DNS 记录的脚本,只调用公共 API,不要求 Workers 项目配置。一个发布 Worker 的作业,则依赖 cloudflare.config.ts、构建器和生成产物。

不要为了写资源脚本先执行 cf init。也不要在尚未迁移的 Wrangler 项目中,直接把发布入口换成 cf。自动配置在 CI 中可能不经询问修改文件,生成一个不同于原项目的配置。

项目配置应该在自己的开发环境生成、审阅后提交,自动化只消费已经确定的配置。否则每次构建都带着“工具可能顺手重写项目”的不确定性。Wrangler 用户说明

资源盘点脚本,从只读开始

以下示例要求秘密变量由运行环境提供,输出也应存放在权限受控的位置:

#!/usr/bin/env bash
set -euo pipefail
umask 077
: "${CLOUDFLARE_API_TOKEN:?请由运行环境提供 Token}"
: "${CLOUDFLARE_ACCOUNT_ID:?缺少账号 ID}"
: "${CLOUDFLARE_ZONE_ID:?缺少区域 ID}"
export CF_SEND_TELEMETRY=false
npx cf dns records list \
  --zone "$CLOUDFLARE_ZONE_ID" \
  --page 1 --per-page 100 > dns-page-1.json
jq -e 'type == "array"' dns-page-1.json > /dev/null

这个脚本只是单页示例,不是完整备份程序。正式盘点要继续分页,并在有任一页失败时阻止输出“完成”报告。记录数量、收集时间和账号目标,应作为盘点结果的一部分。

公开站点的 DNS 看似都可查询,但完整导出仍可能暴露源站地址、内部命名和服务结构。把文件作为作业产物保存时,检查访问范围和保留期限。

标准输出、标准错误和退出状态分别处理

cf 的 API 结果主要输出 JSON,提示、选择和错误写到标准错误。自动化可以把两者分别保存:

npx cf zones list > zones.json 2> zones.log

标准错误有内容不一定代表失败,正常提示也会写进去。标准输出为空也不一定失败,有些变更本来不返回数据。先检查退出状态,再按具体命令解析结果。

如果命令返回原始内容,例如一个 R2 对象,就直接写到目标文件,不要再交给 JSON 解析器。统一包装脚本时应保留这项区别。Agent 文档中的输出约定

最容易漏掉的是中止删除

无交互运行的删除命令,没有 --force 时会中止,输出 Aborted.,但可能以状态 0 退出。于是 set -e 不会中断,后面步骤可能继续执行。

这不是建议给所有命令加 force。某些命令里,该参数还会改变 API 操作本身的行为。正确做法是明确选定对象、查看帮助、审阅变更,再按资源回读判断结果。

删除不存在的对象、没权限删除对象、提示被默认拒绝,属于不同状态。日志里只留一个绿色勾,无法帮助下一次排障。自动化应该记录目标 ID、执行结果和最终状态,凭据本身除外。

Worker 发布尽量只构建一次

经常见到的流水线是:检查阶段 build 一次,发布阶段 deploy 又 build 一次。两个步骤用到的依赖或输入如果不同,真正发布的就未必是检查过的产物。

cf 提供 --prebuilt,可以部署前一阶段的 Build Output:

npx cf build --mode production
npx cf deploy --prebuilt --mode production --dry-run
# 审阅并准备正式发布后
npx cf deploy --prebuilt --mode production

这组命令要求项目已正确配置。mode 必须与构建记录一致;如果构建用 staging,发布也用 staging。--prebuilt 跳过重新构建和自动配置,使用已有 .cloudflare/output 的产物。

cf deploy 帮助中关于预构建产物、模式与 dry run 的参数

部署命令中的预构建产物、模式与请求预览选项。

构建产物传递到下一阶段时,还要保留准确的提交版本、依赖锁文件和构建模式。单独保存一个目录,却没有来源记录,仍然不好追溯。构建与部署文档

把没有凭据的检查留在 PR 阶段

可以让 pull request 运行安装、构建和 dry run,正式部署只在受控的主分支任务中注入 Token。来自 fork 的 PR 一般没有仓库 secrets,这种分工也能让基础检查正常进行。

GitHub Actions 中,构建与检查部分可以写成:

permissions:
  contents: read
jobs:
  check:
    runs-on: ubuntu-latest
    env:
      CF_SEND_TELEMETRY: "false"
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: "22"
          cache: npm
      - run: npm ci
      - run: npx cf build --mode production
      - run: npx cf deploy --prebuilt --mode production --dry-run

这是 job 配置片段,完整工作流还需要 name、触发事件等。正式部署步骤另行注入 secrets,并结合项目的审批、分支及环境规则,不要为了让演示“自动跑通”取消已有发布限制。

dry run 之后,还需要真实验收

预览可以检查请求和部署计划,却不能证明远程权限、实际绑定数据、域名证书或访问结果正确。发布以后,至少回读版本与部署状态,再请求关键业务接口。

一个返回 200 的首页也不是所有功能健康。对访问数据库的 Worker,应确认数据库绑定和必要查询;对静态站点,应确认文章和资源路径。验收内容由应用决定,CLI 返回成功只是开始。

正式接入时可以先让作业仅运行盘点和预览,保留原来的发布路径;等新流程的结果能够稳定复现,再将发布职责交给它。