环境分支 Branching
环境分支目前处于 Private Alpha 阶段:
- 功能仍在开发中,仅对受邀用户开放,需申请开通后使用。
- 接口、参数和返回字段在正式发布前可能发生不兼容变更。
- 不提供 SLA,请勿用于生产链路。
申请开通或反馈问题,请联系你的商务经理或提交工单。
环境分支让你像管理代码一样管理后端:从一个环境拉出一个分支,分支带着完整的数据库表结构、RLS 策略和数据,是一个完全隔离的环境。你可以在分支上随意改表、写数据、部署函数,或者交给 AI Agent 去改,main 环境不受任何影响。
一次调用 CreateBranch,就能拿到一个可用的分支环境,以及一把只能访问这个分支的临时密钥。
交给 AI Agent 使用
点击页面右侧的“复制文档”或“查看 Markdown”,把内容交给你的 Agent(Claude Code、Cursor、CodeBuddy 等),或者直接把本页链接发给它。
确认 Agent 的运行环境里已经配置好准备工作中的环境变量,然后给它一句指令,例如:
阅读 https://docs.cloudbase.net/database/postgresql/branching ,
用环境变量里的腾讯云密钥,从 main 拉一个叫 feat-login 的分支,
建好后在分支上给 users 表加一个 phone 字段。
适用场景
- 给 AI Agent 一个安全的工作区:Agent 在分支上建表、改 RLS、写测试数据。分支临时密钥无法访问 main,Agent 碰不到生产数据。
- 上线前在真实数据上验证:分支带着 main 的完整数据,新功能、新查询和性能问题可以在接近生产的数据上提前暴露。
- 演练破坏性迁移:删列、改类型、重建索引之前,先在分支上跑一遍,确认耗时和结果。
- 每个任务一个环境:并行开发多个功能时,每个功能一个分支,互不干扰。
工作原理
分支是一个独立的 CloudBase 环境,有自己的环境 ID(BranchId)、数据库、函数和访问地址,同时记录父分支,组成一棵分支树。根环境自身就是 main(Depth 为 0)。
创建分支时,平台把父分支的内容复制到新环境:
| 资源 | 分支中的状态 |
|---|---|
| PostgreSQL | 完整副本:表结构、索引、RLS 策略、函数和数据。分支数据库独立,读写互不影响 |
| 身份认证 | 认证配置随数据库继承 |
| 云函数 | 副本 |
| API Key | 不复制。创建时返回一把分支专属临时密钥,详见分支临时密钥 |
分支规格与父分支一致。分支可以继续创建子分支,最多 5 层。
准备工作
- 开通资格:已开通 Private Alpha 的腾讯云账号,以及一个平台版下、使用 PostgreSQL(共享实例)的 CloudBase 环境。
- 准备一个专用的 CAM 子账号:在访问管理控制台新建子账号,只授予云开发(
tcb)相关权限,为它创建 API 密钥(SecretId / SecretKey)。不要使用主账号密钥。 - 把密钥配置为环境变量,放在运行脚本或 Agent 的环境中(例如 shell 配置、
.env文件或 CI 密钥):
export TENCENTCLOUD_SECRET_ID=<子账号 SecretId>
export TENCENTCLOUD_SECRET_KEY=<子账号 SecretKey>
export ENV_ID=<你的环境 ID>
⚠️ 注意:密钥只放在环境变量里,不要粘贴进 Agent 对话。Agent 只需要知道变量名,执行脚本时由 SDK 自动读取并签名。
- 安装 SDK(Node.js 18+):
npm install tencentcloud-sdk-nodejs-common
快速开始
以下示例使用腾讯云 Node.js SDK 的通用客户端调用云开发 tcb 服务(版本 2018-06-08)。
第 1 步:创建分支
// create-branch.js
const { CommonClient } = require("tencentcloud-sdk-nodejs-common");
const client = new CommonClient("tcb.tencentcloudapi.com", "2018-06-08", {
credential: {
secretId: process.env.TENCENTCLOUD_SECRET_ID,
secretKey: process.env.TENCENTCLOUD_SECRET_KEY,
},
region: "ap-shanghai",
});
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function main() {
const envId = process.env.ENV_ID;
// 1. 从 main(根环境自身)拉出一个分支
const res = await client.request("CreateBranch", {
EnvId: envId,
BranchSetting: { ParentBranchId: envId, BranchName: process.env.BRANCH_NAME },
});
const branchId = res.BranchId;
console.log("BranchId:", branchId);
// 2. 轮询到可用:Status 1 = 创建中,0 = 可用
while (true) {
await sleep(10_000);
const { BranchList } = await client.request("DescribeBranchList", { EnvId: envId, BranchId: branchId });
if (BranchList[0].Status !== 1) {
console.log("Status:", BranchList[0].Status, BranchList[0].FailReason || "ready");
break;
}
}
}
main();
BRANCH_NAME=feat-a node create-branch.js
CreateBranch 立即返回 BranchId,分支进入创建中状态(Status = 1)。轮询 DescribeBranchList,Status 变为 0 即可使用;创建失败时 FailReason 会给出原因。返回中的 ApiKey 是分支临时密钥,见分支临时密钥。
第 2 步:查看分支树
const res = await client.request("DescribeBranchList", { EnvId: process.env.ENV_ID });
for (const b of res.BranchList) {
console.log(`${" ".repeat(b.Depth)}${b.BranchName} ${b.BranchId} status=${b.Status}`);
}
main my-app-xxxx status=0
feat-a feat-a-xxxx status=0
第 3 步:在分支上工作
分支就是一个普通环境,所有接受环境 ID 的工具都可以直接使用 BranchId:
tcb fn deploy hello -e <BranchId>
tcb db execute -e <BranchId> --sql "ALTER TABLE notes ADD COLUMN title text"
也可以用分支临时密钥直接访问分支的数据接口:
# 读:返回分支里的数据(从 main 复制过来的)
curl -s "https://<BranchId>.api.tcloudbasegateway.com/v1/rdb/rest/notes?select=id,body" \
-H "Authorization: Bearer $BRANCH_KEY"
# 写:只写进分支,main 不受影响
curl -s -X POST "https://<BranchId>.api.tcloudbasegateway.com/v1/rdb/rest/notes" \
-H "Authorization: Bearer $BRANCH_KEY" -H "Content-Type: application/json" \
-d '{"body": "written on branch"}'
同一把密钥访问 main 会返回 401 INVALID_CREDENTIALS。
第 4 步:删除分支
await client.request("DeleteBranch", {
EnvId: process.env.ENV_ID,
BranchId: "<BranchId>",
});
删除后分支立即从列表中移除,环境资源随后自动回收。分支下还有子分支时,需要先删除子分支。
分支临时密钥
CreateBranch 的返回中包含一把分支专属的服务端密钥(KeyType 为 ephemeral_secret,以 cb_secret_ 开头):
- 有效期 1 小时,到期自动失效。
- 只能访问这个分支,用于 main 或其他分支会返回
401。 - 等同于该分支的管理员身份,不受 RLS 限制。只能在服务端或 Agent 运行环境中使用,不要放进前端代码。
任务预计超过 1 小时的,建议由开发者本人用 CAM 身份为分支调用 CreateApiKey 创建长期密钥,直接写入环境变量文件,不要让 Agent 代为创建或在对话中粘贴:
tccli tcb CreateApiKey --EnvId <BranchId> --KeyType api_key --KeyName agent-dev \
--region ap-shanghai | jq -r '.ApiKey' > .cloudbase-branch.key
chmod 600 .cloudbase-branch.key
接口参考
三个接口均属于云开发 tcb 服务,版本 2018-06-08,请求域名 tcb.tencentcloudapi.com,签名方式为 TC3-HMAC-SHA256。
CreateBranch
从指定父分支创建一个新分支。
输入参数
| 参数名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| EnvId | String | 是 | 根环境 ID |
| BranchSetting.ParentBranchId | String | 是 | 父分支 ID。从 main 创建时填根环境 ID |
| BranchSetting.BranchName | String | 是 | 分支名称,会作为 BranchId 的前缀 |
| ReqKey | String | 否 | 请求标识 |
输出参数
| 参数名称 | 类型 | 说明 |
|---|---|---|
| BranchId | String | 新分支 ID,同时也是分支的环境 ID |
| BranchInfo | Object | 分支信息,字段同 DescribeBranchList |
| ApiKey | Object | 分支临时密钥:ApiKey(密钥值)、KeyType(ephemeral_secret)、过期时间 |
DescribeBranchList
查询环境下的分支列表。
输入参数
| 参数名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| EnvId | String | 是 | 根环境 ID |
| BranchId | String | 否 | 只查询指定分支 |
| Depth | Integer | 否 | 按层级过滤,0–5,0 为 main |
| Offset | Integer | 否 | 分页偏移 |
| Limit | Integer | 否 | 分页大小 |
输出参数
| 参数名称 | 类型 | 说明 |
|---|---|---|
| Total | Integer | 分支总数(含 main) |
| BranchList[].BranchId | String | 分支 ID |
| BranchList[].BranchName | String | 分支名称,main 为 main |
| BranchList[].Depth | Integer | 层级,main 为 0 |
| BranchList[].ParentBranchId / ParentBranchName | String | 父分支 |
| BranchList[].Status | Integer | 1 创建中,0 可用 |
| BranchList[].FailReason | String | 创建失败原因 |
| BranchList[].CreateTime | String | 创建时间 |
DeleteBranch
删除指定分支。分支下存在子分支时会返回错误,需先删除子分支。
输入参数
| 参数名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| EnvId | String | 是 | 根环境 ID |
| BranchId | String | 是 | 要删除的分支 ID |
限制与说明
- 仅支持平台版下的环境,且数据库为 PostgreSQL 共享实例。普通套餐(个人版、标准版等)环境调用会返回
UnsupportedOperation.BranchOperation。 - 分支规格与父分支一致;每个分支占用一个环境配额。
- 分支创建完成后,main 的后续变化不会同步到分支。
- 当前版本不提供分支对比(diff)、合并回 main、从父分支重置等能力。
- 创建耗时与数据量和函数数量有关。