Bitbucket Cloud 仓库治理
Bitbucket Cloud 是托管服务,团队不需要安装 Git 服务端,但“无需部署”不等于“无需工程化”。真正决定仓库是否可靠的,是 Workspace、Project、Repository 三层授权如何传递,Branch Restrictions 是否阻断直推和历史重写,Merge Checks 是提示还是强制,以及自动化凭证能否在人员离职时独立回收。
真实事故往往从一句“我明明开了合并检查”开始:main 上出现未经评审的提交,管理员看到页面有黄色提醒,才发现当前套餐只给出建议而没有强制阻断;追查自动化身份时,又发现脚本仍绑定离职员工的 App password。代码本身没有绕过 Git,失效的是权限层、规则层和凭证层之间的闭环。
下面用隔离仓库 governance-lab 重建这条链路。测试需要一个不会承载业务代码的 Workspace/Project、一个仓库管理员身份、一个普通写成员身份,以及本机 Git 和 curl。管理员负责配置,普通成员负责制造直推、审批不足和只读 Token 写入等失败证据;如果始终使用 Workspace admin,规则的真实约束力无法被证明。
Bitbucket Cloud 与 Bitbucket Data Center 是不同产品形态。Cloud 没有需要团队部署的 Git 服务端,也不能套用 Data Center 的 Personal Access Token、服务端 Hook 或集群参数。构建状态可以来自 Pipelines、Marketplace 集成或 Commit Status API,但无论来自哪里,最终都必须绑定 Pull Request 最新提交的 SHA。
凭证先按身份生命周期拆开。用户 scoped API Token 代表创建者,实际能力是“用户原有权限与 Token scope 的交集”;Repository、Project、Workspace access token 绑定资源,适合单用途自动化;需要多用户授权与撤销闭环的正式集成应评估 OAuth。Atlassian 的 access token 说明还明确了层级边界:Repository token 可用于单仓,Project 和 Workspace token 属于 Premium 能力,Token 创建后不能查看或编辑,只能轮换或撤销。
Bitbucket Cloud 无服务端安装步骤。启用入口是 Atlassian 账号、Workspace、Project 和 Repository:
登录 Bitbucket Cloud,在专用 Workspace 下创建测试 Project。创建私有仓库 governance-lab,不要复用业务仓库做规则试验。在 Workspace settings 中建立 developers、maintainers、auditors 等用户组。
通过 Project permissions 或 Repository 的 User and group access 授权。在 Repository settings -> Branch restrictions 建立 main 规则。
本机先确认客户端入口,不把浏览器登录成功误当成 Git 与 API 已可用:
git --version
curl --version
git ls-remote https://bitbucket.org/atlassian/atlassian-connect-express.git HEAD第三条只探测公开仓库的 Git HTTPS 链路,不证明私有仓库权限。企业代理、证书和私有仓库凭证仍需分别验证。
Project 是权限和仓库组织层,不是 Git 命名空间。用户组的 Default Access 影响未来新仓库;新建用户组并不会自动获得已有仓库权限。团队若只配置“以后默认”,却不盘点存量仓库,会形成两套授权结果。
连接方式怎么选
| 入口 | 适用场景 | 治理要点 |
|---|---|---|
| SSH | 开发者日常 clone/push | 每人独立密钥,离职时回收账号和密钥 |
| HTTPS + 用户 API Token | 无法使用 SSH、短期人工验证 | Token 进入系统凭据库,不写进 remote |
| 用户 API Token + API | 个人脚本、短期管理自动化 | 最小 scope、按组织轮换窗口设置到期、人员离职时一并失效 |
| 资源级 access token | 仓库/项目/Workspace 自动化 | 与资源绑定、审计身份独立;核对 Premium 与 API 能力边界 |
| OAuth / Forge app | 正式多用户集成 | 需要授权、回调、撤销和应用生命周期设计 |
权限先按组,再按资源
Bitbucket Cloud 常用权限可以理解为:Read 能查看和 clone;Write 能推送;Admin 能改仓库设置、权限并执行高风险管理操作。Workspace、Project 和 Repository 的授权可能叠加,排查时不能只看仓库页面中的直接成员。
建议基线:
| 用户组 | Project/Repository 权限 | 责任 |
|---|---|---|
workspace-admins | Workspace 管理,极少数 | 账号、组、套餐与全局策略 |
maintainers | 仓库 Write,必要仓库才给 Admin | 合并 PR、维护分支规则 |
developers | 仓库 Write | 推功能分支、创建 PR、评审 |
auditors | Read | 查看代码和治理证据 |
不要把“需要合并 PR”直接等同于 Admin。Branch Restrictions 可以单独指定通过 PR 的 merge access,让维护者保留合并能力而不能任意改仓库设置。
为 main 配置 Branch Restrictions
进入 Repository settings -> Branch restrictions -> Add a branch restriction,对 main 建立:
Write access:只允许极少数应急维护者,日常开发组不在列表中,阻止直接 push。Merge access via pull requests:只允许 maintainers。禁止删除分支和重写历史;不要让“可写”自动意味着“可 force push”。
若有长期维护分支,用精确模式另建规则;宽泛 * 只在清楚重叠语义时使用。
Bitbucket 允许规则重叠,main 和 * 可能同时命中。不同允许列表可能合并出比直觉更宽或更窄的权限,因此每次新增通配规则都要重新验证关键分支。Branch Restrictions REST API把规则拆成 kind、branch_match_kind、pattern、users 和 groups;其中 push 与 restrict_merges 的空例外列表表示无人豁免,这些字段比控制台截图更适合做漂移比较。
把 Merge Checks 从提示变成门禁
按项目风险选择:最少审批数、默认评审人审批、无未解决任务、无 changes requested、最新提交构建成功、源分支更新后重置审批等。然后确认是否启用了 Prevent a merge with unresolved merge checks。
这是最容易产生误判的地方:Merge Checks 官方说明明确区分建议与强制:所有套餐都可以提示未满足的条件,Premium 才能用 Prevent a merge with unresolved merge checks 阻止合并。测试记录必须区分“页面显示警告”和“服务端拒绝合并”,不能统称“已开启门禁”。
构建检查消费的是 PR 最新提交上的 commit status。状态可以来自 Pipelines、Marketplace 集成或 Commit Status REST API;无论上游是哪一种,检查名称、目标 SHA 和上报者都必须纳入治理。
配置默认评审人和合并策略
默认评审人用于自动邀请,不天然等于强制 Code Owner。若要求某类 owner 必须批准,应结合默认评审人审批 check、用户组和分支限制验证。团队还应固定允许的 merge 策略,明确 merge commit、squash、fast-forward 的历史取舍,避免同一仓库出现无法预测的历史形态。
建立可重复的规则实验
初始化测试仓库
在 Bitbucket Cloud 创建空私有仓库后:
mkdir governance-lab
cd governance-lab
git init -b main
git config user.name "Lab Developer"
git config user.email "developer@example.com"
printf "# governance-lab\n" > README.md
git add README.md
git commit -m "初始化治理测试仓库"
git remote add origin https://bitbucket.org/your-workspace/governance-lab.git
git push -u origin main先用管理员完成首推,再配置规则。随后切换到普通 developer 身份。
证明直推失败、功能分支成功
printf "direct push should fail\n" >> README.md
git add README.md
git commit -m "验证 main 直推阻断"
git push origin main预期远端拒绝 main 更新。保留这次提交并转到功能分支:
git switch -c docs/governance-check
git push -u origin docs/governance-check若功能分支也被拒绝,先检查是否有 * 通配限制重叠,不要立即给用户 Admin。
证明 PR 门禁真实阻断
从 docs/governance-check 向 main 创建 Pull Request。依次验证:
审批数不足时能否点击合并。创建一个未解决 PR task 后能否合并。对源分支补交修改后,旧审批是否按预期重置。
最新提交状态失败时是否阻断,状态成功后是否放行。普通写成员、maintainer 和 repository admin 的结果是否符合例外设计。
如果页面只是黄色提醒但仍能合并,说明 checks 未被 Premium 强制,技术门禁并未成立。
用 scoped API Token 验证只读访问
创建到期时间尽量短的 API Token,选择 Bitbucket app 和 read:repository:bitbucket。Git 命令可使用静态用户名并在提示时输入 Token:
git clone https://x-bitbucket-api-token-auth@bitbucket.org/your-workspace/governance-lab.git governance-lab-readonly验证 REST API 时,使用 Atlassian 账号邮箱作为 Basic Auth 用户名:
curl --fail-with-body \
--user "developer@example.com:<bitbucket-api-token>" \
-H "Accept: application/json" \
"https://api.bitbucket.org/2.0/repositories/your-workspace/governance-lab"只读 Token 的 push 必须失败。若要读取 Branch Restrictions,另建短期管理 Token,并仅为本次盘点增加 admin:repository:bitbucket:
curl --fail-with-body \
--user "admin@example.com:<bitbucket-api-token>" \
-H "Accept: application/json" \
"https://api.bitbucket.org/2.0/repositories/your-workspace/governance-lab/branch-restrictions"预期返回分页 JSON,values 中包含命中 main 的规则。完成后撤销两个 Token、删除本地 clone 和测试仓库。若 Workspace 专供实验,也移除测试用户授权,避免继续占用席位。
新仓库接入
推荐顺序是“先权限和门禁,后导入真实代码”:
在正确 Project 下创建私有仓库,确认默认组不会意外获得 Admin。配置用户组、Branch Restrictions、默认评审人和 merge 策略。用最小提交完成直推失败与 PR 成功测试。
导入真实 refs、tag、LFS,并核对 submodule 和外部依赖 URL。接入构建状态后,先观察 context,再开启强制 Merge Checks。将仓库 owner、规则目标、Token 和检查 owner 记录到项目清单。
从其他平台迁移
迁移时至少核对:所有分支和 tag 是否齐全;默认分支是否一致;开放 PR、评论、审批和 Issue 是否需要另行迁移;旧机器人凭证是否撤销;旧平台何时只读。Git mirror 只能搬运 Git refs,不能自动等价搬运 Cloud 的权限、PR、merge check 和审计语义。
git clone --mirror https://example.com/your-org/source-repo.git
cd source-repo.git
git remote set-url --push origin https://bitbucket.org/your-workspace/target-repo.git
git push --mirror--mirror 会删除目标端不存在于源端的 refs,只能用于空目标仓库和已审批迁移窗口。不要把它当日常同步命令。
开发者日常分支闭环
git switch main
git pull --ff-only
git switch -c feat/example-change
# 修改、测试、提交
git push -u origin feat/example-change在 PR 页面确认目标分支、diff、评审人、tasks、构建状态和合并策略。合并后删除功能分支,再执行 git fetch --prune。不要为绕开门禁把 PR 改投一个无保护的长期分支。
轮换 API Token
API Token 的权限创建后不能修改,最长有效期由官方当前规则限制。正确轮换方式是:创建新 Token;在一个消费者上灰度;验证 clone/API;切换全部消费者;撤销旧 Token;确认旧 Token 请求失败;记录完成时间。不能等到过期当天才批量替换。
盘点重叠规则
用 REST API 分页导出 Branch Restrictions,按 branch_match_kind、pattern、kind、users 和 groups 比较。重点查 main 与 *、分支类型与 glob 同时命中的情况。管理 Token 只在盘点窗口启用,导出结果不得包含 Authorization 头。
Git 或 API 突然认证失败
原 App password 集成间歇或持续返回 401,人工 Git 也开始重复提示密码。确认凭证类型、创建时间和调用日志;检查是否仍在使用 App password,而非 scoped API Token。App password 已进入退出窗口,旧集成可能在 brownout 期间间歇失败;或新 Token 已过期/被撤销。
创建带 Bitbucket scopes 的 API Token,Git 使用 Bitbucket username 或 x-bitbucket-api-token-auth,REST API 使用官方要求的账号邮箱;完成后撤销旧凭证。clone、fetch、必要的 push 和 API GET 均成功,旧 App password/Token 明确失败。
API Token 能读仓库却不能读 PR 或规则
仓库 GET 成功,PR 或 Branch Restrictions API 返回 403。逐接口查看 API Token permissions;仓库 read 不包含 PR read,规则管理需要 admin:repository:bitbucket。把“能读代码”误解为“能读所有仓库相关对象”,或创建 Token 时选错 app/scope。
不扩大原 Token;按任务新建最小 scope Token,确认创建者本身也有目标权限。目标接口成功,超出范围的写接口仍被拒绝。
规则已配置,main 仍可被直推
部分用户直推被拒绝,另一些用户仍可 push 或 force push。检查用户是否通过 Workspace、Project、Repository 或用户组获得权限;列出所有命中 main 的规则和例外名单。用户或组在 allowlist;重叠规则产生额外允许;测试者是管理员;只限制 merge 没有限制 write。
将日常开发组移出 direct write,单独设置 merge access,收紧强推/删除权限,并减少个人例外。普通成员、maintainer、admin 各直推一次,再由授权维护者通过 PR 合并。
Merge Checks 未满足却仍能合并
审批、task 或构建检查未完成,合并按钮仍可用。查看是否启用了 Prevent a merge with unresolved merge checks,以及 Workspace 套餐是否支持强制执行。非 Premium 下 checks 只是建议;规则应用到其他分支;用户误把提示当门禁。
升级并启用强制阻断,或在不能升级时明确承认该风险,用更严格 merge access 和外部流程缓解,不能宣称技术强制已实现。制造失败状态和未审批 PR,实际点击/调用 merge,必须得到拒绝。
新提交后旧审批仍有效
PR diff 已改变,之前的批准仍计入门槛。检查 reset approvals / require another approval 等设置,并确认改动是否真的改变 diff。未启用提交变化后的审批失效;使用了“diff 未变化则保留”的智能策略;套餐能力不同。
按风险选择严格重置或智能保留,并把行为写入评审规范。分别追加改变 diff 的提交和空提交,确认两类审批行为符合预期。
功能分支也无法 push
开发者不能推 feat/*,但仓库有 Write 权限。查询 *、分支类型和具体模式的重叠规则;确认 branch pattern 的 glob 结果。为了保护 main 配了全局 push 限制;模式写法与预期不一致。
把高风险规则收窄到具体分支或明确的 release 模式,保留功能分支写入口。功能分支 push 成功,main 直推仍失败。
Bitbucket Cloud 依赖公网 DNS、HTTPS 和 SSH。企业网络中浏览器、Git HTTPS、Git SSH、curl 和构建环境可能走不同出口。排障时分别执行:
git ls-remote https://bitbucket.org/your-workspace/governance-lab.git
ssh -T git@bitbucket.org
curl -I https://api.bitbucket.org/2.0/如果 TLS 被企业代理重签,应通过受管系统信任库安装企业 CA,不要禁用 http.sslVerify。若 SSH 端口受限,可按 Bitbucket Cloud 官方当前 SSH 替代入口配置,但必须重新核对主机指纹;不要复制论坛中的未知 known_hosts 内容。
凭证边界:
| 场景 | 推荐 | 风险控制 |
|---|---|---|
| 开发者 Git | 每人 SSH Key,或系统凭据库中的用户 API Token | 离职回收、禁止共享 |
| 短期 API 脚本 | 用户 scoped API Token | 短有效期、最小 scope、完成即撤销 |
| 单仓自动化 | Repository access token(能力适用时) | 与员工生命周期解耦,只授权单仓 |
| 多仓平台自动化 | Project/Workspace access token 或 OAuth | 套餐校准、独立审计、限制资源范围 |
| 只读部署 | 只读 access token 或 access key | 不得具备 merge/admin 权限 |
API Token 不得出现在 remote URL、命令历史、构建日志和 PR 文本中。交互式 Git 可让凭据管理器保存 Token;自动化应由 secret store 注入。资源级 access token 会以独立身份出现在部分 UI/日志中,但它不能登录网站,也不能被当作 Branch Restrictions 中的普通用户例外,设计前要核对具体 API 限制。
建立可审计的责任边界
Workspace admin 管账号组、套餐和全局应用;Project admin 管项目级授权;Repository admin 管单仓设置;maintainer 管 PR 合并;CI owner 管构建状态。仓库治理失败常常不是缺少功能,而是五类责任都落到一个长期无人复核的个人账号上。
至少每季度盘点:
Workspace、Project、Repository 三层的用户与组权限。Default Access 对新仓库的影响,以及新用户组是否覆盖存量仓库。所有命中默认分支和 release 分支的 Branch Restrictions。
Merge Checks 是否强制、套餐是否仍匹配、管理员是否存在绕过路径。用户 API Token、资源 access token、OAuth consumer 和 access key 的 owner、scope、到期与最后使用时间。
App password 是否已全部迁移;Atlassian 当前公告显示它已进入受控 brownout,永久移除也已排期。实施时必须打开退出公告读取实时窗口,并用调用日志确认没有残留。
把规则配置当作版本化策略
Cloud 控制台设置不会自然进入 Git 历史。团队应通过 API 导出或声明式清单保存预期值,至少记录模式、限制 kind、允许组、审批数、构建数和强制开关。变更要有评审、试验仓库验证和回滚值。导出的是规则元数据,不应包含 Token。
架构取舍
Cloud 与自托管平台怎么选
Bitbucket Cloud 适合希望减少 Git 服务端运维、已经使用 Atlassian 账号/Workspace/Jira 体系、可接受 SaaS 数据边界和套餐约束的团队。它把可用性和升级责任交给供应商,但组织仍负责账号、权限、凭证、规则和集成质量。
若代码必须完全处于隔离网络、需要服务端 Hook 或深度定制、必须控制升级窗口,Bitbucket Data Center 或其他自托管平台可能更合适。反过来,没有数据库、存储、备份和升级能力的团队,不应仅为避免订阅费而自托管。
Merge Checks 的套餐取舍
非 Premium 的建议检查可以改善协作提示,却不是不可绕过的控制。如果合规要求“未经两人审批或构建失败绝不能合并”,就必须采购可强制的能力,或选择能提供等价服务端门禁的平台。用制度要求成员“不要点合并”只能作为风险接受,不能当技术控制。
用户 Token 与资源 Token
用户 API Token 适合代表某个用户的短期操作,集成行为受用户原始权限与离职影响;资源 access token 更适合机器身份和范围隔离,但部分类型是 Premium,且不能完成所有权限管理或充当 merge allowlist 用户。大型集成优先评估 OAuth/Forge,而不是不断累积高权限长期 Token。
App password 迁移存在“间歇成功”陷阱
受控 brownout 期间,同一集成可能昨天成功、今天 401、稍后又恢复。若只在成功时段抽测,会误判迁移无需执行。应按凭证类型盘点配置源和调用日志,切到 scoped API Token 后主动撤销旧 App password,用失败结果证明没有静默回退。Token 创建时必须选择 Bitbucket app、scope 和到期日,明文只显示一次;仓库读取、Pull Request 与规则管理使用不同 scope,不能用 read:repository:bitbucket 推导“可读所有仓库对象”。
重叠 Branch Restrictions 会制造隐形权限
具体分支、glob 和 branching model 可以同时命中,用户/组例外又会影响最终结果。随着规则增长,控制台肉眼审查很难回答“某个人究竟能不能写 main”。治理工具应把规则展开到“分支 x 身份 x 操作”的测试矩阵,至少覆盖 push、force push、delete 和 PR merge。
检查显示成功,不代表检查可信
Merge Check 只消费某个 commit status。若 Token 泄露、上报者权限过宽、状态发给旧 SHA,页面上的绿色结果也可能没有证明最新代码。CI owner 要限制上报凭证、固定 context 命名、校验目标 SHA,并监控长时间不再上报的检查。
权限继承让离职回收容易漏层
成员可能同时通过 Workspace group、Project permission、Repository direct access 和外部应用获得能力。只从一个仓库移除直接授权并不代表完成回收。离职流程应从 User directory 查看有效访问,移除群组和直接权限,撤销用户 Token/SSH Key,并单独处理机器人或共享资源 Token。
SaaS 降低运维,不消除供应商变化
App password 退出、Token scope、套餐功能和控制台路径都会变化。团队需要订阅官方变更渠道,在试验 Workspace 做回归,并为关键自动化保留凭证轮换和供应商故障预案。把所有集成硬编码为单一认证方式,会把一次平台变更放大为全组织中断。
审计证据有保留期和套餐边界
权限变更、规则修改、强制合并和 Token 使用是否能在需要的时间窗内检索,要按当前组织连接方式和订阅能力确认。Bitbucket Cloud 的审计事件说明提醒团队:审计事件仍在增量扩展,仓库管理活动与详细 Commit 活动不是同一份证据;需要组织级证据时还要确认 Workspace 是否已连接 Atlassian Organization/Guard。若法规要求超过平台保留期,应设计合规导出和受控存储,但不能把包含 Token、源码或个人敏感信息的原始响应无差别长期保存。
文档与规则明确只针对 Bitbucket Cloud,没有混入 Data Center 口径。已重新核对套餐、Merge Checks 强制能力和 Token 弃用公告。Workspace、Project、Repository 三层权限均已盘点,日常授权优先使用组。
main 的 direct write、force push、delete 和 PR merge 权限分别明确。已检查具体分支、glob 与 branching model 的重叠结果。Merge Checks 不仅显示,而且在需要时能实际阻断合并。
新提交后的审批失效、未解决 tasks、changes requested 和构建状态均已验证。开发者、maintainer、repository admin 三种身份都完成了行为测试。新接入使用 scoped API Token、资源 access token 或 OAuth,不再设计 App password。
Git 与 REST API 使用正确的用户名和 scope,Token 不在 URL、日志与脚本中。人工凭证与机器人凭证分离,均有 owner、到期日、轮换和撤销验证。构建状态的 context、上报身份和目标 commit SHA 有稳定契约。
规则基线可导出、比较和回滚,例外有审批和期限。测试仓库、测试用户权限、本地 clone 和临时 Token 已清理。
