Bruno:Git 原生 Collection 如何安全执行
Bruno 的核心取舍非常明确:请求集合首先是本地文件,团队协作首先走 Git。它减少了“资产只存在某个账号云空间”的不确定性,却没有自动解决 Secret、脚本权限、执行顺序和报告泄漏。纯文本让问题可见,仍需要团队决定哪些文件进入仓库、哪些值在运行时注入、哪种集合格式是主源,以及 CLI 到底执行了多少请求。
安装桌面端,也把 CLI 固定在项目里
桌面端从官方渠道或内部软件仓库安装,记录版本、发布者和实际 Collection 默认目录。CLI 是独立 Node.js 包;个人电脑可以全局安装用于诊断,项目和 CI 应使用精确开发依赖与 lockfile,避免每次任务取得不同版本。
npm install --save-dev --save-exact @usebruno/cli
npx --no-install bru --version团队升级时让桌面端与 CLI 处在经过验证的兼容线。CLI major 可能改变默认 sandbox 与参数,集合格式也会演进。网页上的“最新版本”不是运行证据,流水线开头应打印实际版本但不打印环境变量。
Collection 是一个可以审查的目录
创建 Collection 时,Bruno 会在选定目录生成根配置和推荐的 .gitignore。默认路径只是个人便利,项目资产更适合放在业务仓库或专用 API 仓库中,由同一分支和 Code Owner 审查。
api-tests/
bruno.json
collection.bru
environments/
local.example.bru
ci.bru
health/
get-health.bru
users/
get-me.bru
.env.sample
.gitignore
README.md目录结构同时承担人类导航与 CLI 选择。文件夹名应对应业务场景,副作用请求与只读 smoke 分开,README 说明执行顺序、测试身份、目标环境和清理动作。不要把所有接口堆进一个“misc”目录,再依赖 GUI 搜索维持可用性。
Git 记录变化,却不会判断变化是否安全。评审必须关注 URL、方法、Header、认证继承、脚本、测试和请求顺序;.bru、YAML、JSON 和响应样本都能容纳 token 或内部数据,仍要执行 Secret 扫描。
OpenCollection YAML 与 Bru 格式怎样选择
Bruno 当前同时支持 .bru 与 OpenCollection YAML。官方对新 Collection 推荐 OpenCollection YAML;.bru 继续受到支持。YAML 使用 opencollection.yml 作为根文件,能够直接利用通用 YAML 工具与规范;Bru 格式使用 bruno.json 和 .bru 文件,已有项目可以继续维护。
| 判断信号 | OpenCollection YAML | Bru 格式 |
|---|---|---|
| 新建团队资产 | 官方当前推荐,可结合通用 YAML 工具 | 仍可用,但不是新项目默认优先 |
| 已有稳定集合 | 先做兼容实验再迁移 | 保持主源,避免无价值重写 |
| 外部工具解析 | 规范与 JSON Schema 更容易接入 | 需要 Bru 解析能力 |
| PR 可读性 | 团队熟悉 YAML 时较直接 | 请求 DSL 紧凑,现有用户更熟悉 |
两种格式可以在迁移阶段共存,不代表应长期维护同一请求的双份定义。冻结一个小目录试迁移,对比 CLI 请求数、变量解析、脚本和断言;确认工具链后再逐批转换。没有成熟自动迁移路径时,不为追逐格式标签手工重写整个集合。
OpenCollection 描述“怎样调用 API”,OpenAPI 描述“API 是什么”。从 OpenAPI 导入可以生成请求起点,后续场景和断言仍需维护;Collection 的一次成功也不能反向证明 OpenAPI 与实现完全一致。
环境变量解决复用,Secret 解决暴露
非敏感环境文件可以保存 base URL、租户、功能开关和超时。真实 token、客户端密钥、Cookie 与证书密码不进入仓库环境。桌面端标记的 Secret 保存在本机状态,CLI 不能假设能直接取得这些 GUI Secret;无界面运行应从 CI Secret、外部 Secret Manager 或临时 .env 注入。
vars {
baseUrl: {{process.env.API_BASE_URL}}
apiToken: {{process.env.API_TOKEN}}
}Collection 根目录的 .env 必须加入 .gitignore,权限限制为当前用户,并在任务结束时删除。仓库只提交 .env.sample,列出键名和来源说明,不提供假装安全的共享测试 token。
umask 077
BRUNO_ENV_FILE="$PWD/api-tests/.env"
trap 'rm -f "$BRUNO_ENV_FILE"' EXIT
printf 'API_BASE_URL=%s\nAPI_TOKEN=%s\n' \
"$API_BASE_URL" "$API_TOKEN" > "$BRUNO_ENV_FILE"Bruno 报告会对识别出的 Secret 做掩码,但不能把掩码当成唯一防线。派生值、URL 编码、响应回显和脚本日志仍可能泄漏。最稳妥的报告默认跳过 Header 与 Body,只在隔离任务中短时保留必要内容。
用一个请求建立桌面与 CLI 的共同事实
创建只读 /health 请求,断言状态码、响应类型和稳定字段。先把主机改成 .invalid,证明 DNS/连接错误发生在 HTTP 之前;再使用撤销 token,确认请求抵达网关并返回 401 或 403;最后注入有效低权限 token,取得业务成功和 request id。
test('health is ready', function () {
expect(res.getStatus()).to.equal(200);
expect(res.getBody().status).to.equal('ready');
});脚本 API 以目标版本创建请求时的官方示例为准。团队应保存的是实验状态和预期输出,不是依赖某段永久不变的 API 语法。桌面运行通过后,从干净 checkout 使用同一环境引用执行 CLI;两者请求数、目标和断言必须一致。
CLI 的选择规则必须显式
进入 Collection 根目录运行 bru run 会执行集合;传入文件夹时要确认递归语义,tag、禁用请求和排序也会改变实际范围。GUI 中看得到十个 smoke,不代表 CI 运行了十个。任务应输出选择条件与执行摘要,并断言请求数量符合基线。
cd api-tests
npx --no-install bru run health -r \
--env ci \
--tags smoke \
--bail \
--reporter-junit ../reports/bruno.xml \
--reporter-skip-all-headers \
--reporter-skip-body--bail 适合存在依赖或副作用的短 smoke,避免前置失败后继续制造噪声;大规模独立回归可能希望收集全部失败。选择应写进任务目的,不机械套用。报告只保存断言、耗时与关联标识,artifact 设置短保留期和受控访问。
Safe sandbox 是默认安全边界
CLI 的 Safe 模式限制脚本访问文件系统、外部 npm 包和系统能力。Collection 如果要求这些能力,需要显式使用 Developer sandbox。Safe 下失败首先说明脚本超出了最小运行面,不应直接把 CI 全部切到 Developer 模式。
npx --no-install bru run --sandbox=developer确实需要 Developer 模式时,审查每段脚本、固定外部依赖、使用隔离 runner,并限制工作目录、网络和环境变量。脚本可以读取文件或发起额外请求,它属于代码执行面,不是请求配置的无害附属品。第三方 Collection 在 Developer 模式运行前必须当作外部程序审查。
请求顺序和副作用需要显式建模
Collection 常用登录、创建、查询和清理组成场景。顺序依赖应尽量缩小,动态值通过运行时变量传递,失败后仍要执行安全清理。有副作用的请求默认不进入 PR smoke,或使用隔离租户、幂等键和明确标签。
全部请求每次执行会增加网关限流、第三方调用和测试数据成本。合理分层是快速只读 smoke、环境级场景回归和人工诊断集合。tag 与目录只是选择机制,owner 仍需维护断言和数据生命周期。长期没有进入任何流水线的请求,通常已经退化为不可信文档。
代理、CA、Cookie 与 mTLS 分开诊断
Bruno 桌面端的代理可关闭、显式开启或使用系统设置,CLI 又可能继承 runner 环境。连接失败时依次对比目标是否必须走代理、NO_PROXY、企业 CA、服务端证书链和客户端证书。Cookie jar 还可能让桌面请求隐式继承旧会话,而干净 CLI 正确失败。
npx --no-install bru run \
--cacert "$CORP_CA_FILE" \
--client-cert-config "$CLIENT_CERT_CONFIG"--insecure 或关闭证书校验只用于确认信任链责任层,不能写进共享配置。客户端私钥和密码由 Secret 系统提供,不进入 Collection、导出文件或报告。排障完成后清理临时证书副本与 Cookie。
Git 协作需要格式和执行双重评审
PR 中看见清晰文本,是 Bruno 的优势,但评审不能只看文本是否漂亮。格式检查确认 YAML 或 Bru 可解析,执行检查确认选定 smoke 真正运行,安全检查确认没有 Secret 与危险脚本,契约检查确认 URL 和 schema 没有偏离主源。
合并冲突应按请求语义解决。seq、文件移动和环境改名可能影响执行顺序;直接接受双方文本会得到可解析但行为错误的集合。合并后从干净 checkout 重跑 CLI,才算冲突关闭。
升级和格式迁移以可重建为准
升级前保存桌面与 CLI 版本、Collection 格式、请求数量、环境来源、sandbox 模式和脱敏 smoke 报告。在隔离分支用候选版本重跑,比较根配置、脚本、变量优先级和报告。若发生自动格式写回,先审查差异,再允许团队成员升级。
停用 Bruno 时,将仍有效的请求迁移到新主源或最小 curl smoke,撤销测试身份与外部 Secret 权限,删除 .env、本地凭证、证书、报告和缓存,归档不含 Secret 的最后提交。卸载 GUI 不会停止 CI 中的 @usebruno/cli,还要从依赖和流水线删除执行入口。
Bruno 的“本地优先”是一套资产所有权选择,不是安全结论。只有集合格式唯一、Git 差异可读、Secret 在运行时注入、Safe sandbox 默认生效、CLI 执行范围可证明并且退出能完整收尾,纯文本请求才真正转化为团队可维护的接口资产。
