CNB hello-cnb 闯关全自动化复盘文档
时间:2026-10-11 09:25 (UTC+8)
目标仓库:https://cnb.cool/cnb/tutorial/hello-cnb
验证机制:向该仓库提交 PR,其内置 CI(.cnb.ymlinclude 的 hello-cnb-ci 各 level.yml)自动检查,8 条流水线全绿即通关,自动绑定「天才程序员」身份(个人设置 → 身份认证 自助领取 666 Credits/月)。
本文档记录从零到 8 条流水线全绿的完整可复现路径,所有操作均基于 API/HTTP 完成,无需打开浏览器。
0. 前置知识
- API 网关:
https://api.cnb.cool(OpenAPI,Bearer Token 认证,请求头必须带Accept: application/vnd.cnb.api+json,否则部分 POST/DELETE 返回 406) - Swagger:
https://api.cnb.cool/swagger.json(1.1MB,199 个路径,先拉下来通读一遍,很多任务能不能用 API 做取决于它) - Web 前端私有接口:
https://cnb.cool/<path>同源接口,需要浏览器 Cookie(CNBSESSION+csrfkey)+ 请求头X-Csrftoken: <csrfkey值> - CNB CLI(可选辅助):
npm i @cnbcool/cnb-cli,基于同一套 swagger,CNB_TOKEN环境变量认证 - Git 推拉认证:
https://<username>:<token>@cnb.cool/<org>/<repo>.git
关键结论先行(避免走弯路):
| 能力 | API token 能否做 | 说明 |
|---|---|---|
| 改签名 Bio | 能 | POST /api.cnb.cool/user |
| 改用户名 | 不能直接改 | 需要 Web Cookie:POST <https://cnb.cool/user/rename_check/{name}> → POST <https://cnb.cool/user/rename/{name}> |
| 昵称 | 谁都改不了 | 平台禁止,返回 403 Nickname cannot be changed |
| 关注用户/关注仓库 | 不能直接改 | 需要 Web Cookie:PUT <https://cnb.cool/user/following/{username}、PUT> <https://cnb.cool/user/starred/{org}/{repo}> |
| 仓库墙 Pin | 需要 Web Cookie | PUT <https://cnb.cool/user/pinned-repos,body> 为 ["org/repo"] |
| 建仓库/建组织内资源 | 能 | POST /{slug}/-/repos |
| 保护分支 | 能 | POST /{repo}/-/settings/branch-protections(body 必须全量给齐所有布尔字段,缺了报 400) |
| 流水线 push/tag/PR | 能 | 配好 .cnb.yml 后自动触发 |
| web_trigger / tag_deploy | API token 不行,Web Cookie 能 | 见 5.4 / 5.5 |
| Docker 制品/知识库/NPC/任务集/工作空间 | 能 | 流水线或 API 完成 |
1. 准备阶段
# 1.1 拉 swagger,摸清能力边界
curl.exe -s <https://api.cnb.cool/swagger.json> -o swagger.json
# 1.2 验证 token
curl.exe -s -H "Authorization: Bearer <TOKEN>" <https://api.cnb.cool/user>
# 1.3 拉 CI 验证脚本(每关怎么验的,看了才知道往哪打)
curl.exe -s -o level1.yml <https://cnb.cool/cnb/tutorial/hello-cnb-ci/-/git/raw/main/level1.yml>
# level2~8 同理
通读 level*.yml 后得到的精确通关条件:
| 关 | 条件 |
|---|---|
| L1 | 用户名非 cnb. + 11 位随机串;bio 非空;pinned 仓库 ≥1;follow_count ≥1;follow_repo_count ≥1 |
| L2 | 源仓库有 ≥1 条保护分支规则;LICENSE 可识别(MIT 等);.cnb/settings.yml 含 workspace.launch.button 与 fork.button |
| L3 | auto_trigger=true;push/pull_request/tag_push/web_trigger/tag_deploy 各有 ≥1 次 success 构建记录;存在 .cnb/tag_deploy.yml |
| L4 | 工作空间列表 ≥1;.cnb.yml 的 "$".vscode[].docker.image 非空;vscode service options 含 onlyPreview 与 launch |
| L5 | list-packages --type docker total ≥1 |
| L6 | 组织下任务集 ≥1 |
| L7 | repo flags 含 KnowledgeBase 与 NPC;仓库内有本人 author 的 commit |
| L8 | 以上 resolve key 全部 await 后跑 cnbcool/bind-genius |
注意:仓库 README 里写的推荐关注对象与 CI 实际校验的名单不一致,且 CI 只看数量 ≥1,不用纠结具体关注谁。
2. 建闯关仓库(不用 Fork)
OpenAPI 没有 fork 接口,用「镜像 push」等效替代:
git clone <https://cnb.cool/cnb/tutorial/hello-cnb.git>
curl.exe -s -X POST -H "Authorization: Bearer $t" -H "Content-Type: application/json" `
-H "Accept: application/vnd.cnb.api+json" `
--data-raw '{"name":"hello-cnb","visibility":"public","description":"CNB tutorial"}' `
"<https://api.cnb.cool/><ORG>/-/repos"
cd hello-cnb
git push --mirror "<https://<user>:<token>@cnb.cool/><ORG>/hello-cnb.git"
要点:
- 新建仓库
auto_trigger默认已为 true(可用GET /{repo}/-/settings/cloud-native-build确认),任务 3.1 天然完成 - mirror push 会带上上游的 tag,无副作用
3. 一次性写入全部配置(L2/L3/L4 的仓库文件部分)
在仓库根目录准备 4 个文件(完整示例见本文末尾附录):
LICENSE— 标准 MIT 全文(2.2).cnb/settings.yml— UI 定制 + NPC 角色(2.3 + 7.2 的角色定义部分).cnb/tag_deploy.yml— 两个环境 development/staging(3.6).cnb/web_trigger.yml— 一个按钮(3.5).cnb.yml— 核心,见下
.cnb.yml 必须覆盖的事件(缺一个 L3 就红):
"$":
vscode: # L4.2/4.3:镜像 + options
- docker:
image: cnbcool/default-dev-env:latest
services:
- docker
- name: vscode
options:
onlyPreview: true
launch: python3 -m http.server 8686
daemon: true
keepAliveTimeout: 3600000
web_trigger: # L3.5
- stages:
- name: manual trigger ok
script: echo ok
main:
push: # L3.2 + L7.1 知识库 + L5 Docker 制品
- stages:
- name: build knowledge base
type: knowledge:update
options: { include: "**/**.md" }
- name: docker build & push
services: [docker]
stages:
- name: docker image
script: |
docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/hello:latest .
docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/hello:latest
pull_request: # L3.3
- stages:
- name: pr ok
script: echo ok
"v*": # L3.4:tag_push 挂在 tag 名模式下,不是分支名下!
tag_push:
- stages:
- name: tag ok
script: echo ok
tag_deploy.development: # L3.6
- stages:
- name: deploy dev
script: echo ok
tag_deploy.staging:
- stages:
- name: deploy staging
script: echo ok
踩坑记录(全部实测撞过):
pull_request必须挂在目标分支名(main)下面,挂顶层不触发tag_push/tag_deploy必须挂在 tag 名 glob("v*")下面,挂在 main 下不触发- vscode 镜像用
cnbcool/default-dev-env:latest;cnbcool/default与default-dev不存在 onlyPreview: true时 launch 必须真监听 8686 端口且要daemon: true,否则 Prepare 超时报错- docker 构建用
services: [docker],普通镜像里没有 docker 命令 - 知识库(L7.1)就是靠 push 流水线里的
knowledge:update内置任务开启的,跑完一次 repo flags 自动变KnowledgeBase;NPC(7.2)靠在 settings.yml 定义角色 + 在 Issue 里 @ 一次 NPC,跑完 flags 变NPC(延迟约 1 分钟)
push 后逐项验证:
# 构建记录
curl.exe -s -H "Authorization: Bearer $t" "<https://api.cnb.cool/><ORG>/hello-cnb/-/build/logs?page_size=20"
# 单条构建各 stage 状态
curl.exe -s -H "Authorization: Bearer $t" "<https://api.cnb.cool/><ORG>/hello-cnb/-/build/status/<SN>"
# stage 日志(排障用)
curl.exe -s -H "Authorization: Bearer $t" "<https://api.cnb.cool/><ORG>/hello-cnb/-/build/logs/stage/<SN>/<PIPELINE_ID>/prepare"
# docker 制品(npm CLI)
npx @cnbcool/cnb-cli registries list-packages --slug "<ORG>/hello-cnb" --type docker --verbose
4. 纯 API 能搞定的设置项
4.1 签名(L1.3)
curl.exe -s -X POST -H "Authorization: Bearer $t" -H "Content-Type: application/json" `
-H "Accept: application/vnd.cnb.api+json" `
--data-raw '{"bio":"..."}' <https://api.cnb.cool/user>
4.2 保护分支(L2.1)
body 必须给齐全部字段,只给 rule 会 400:
curl.exe -s -X POST -H "Authorization: Bearer $t" -H "Content-Type: application/json" `
-H "Accept: application/vnd.cnb.api+json" `
--data-raw '{"rule":"main","allow_creation":false,"allow_deletions":false,"allow_force_pushes":false,"allow_master_creation":true,"allow_master_deletions":true,"allow_master_force_pushes":true,"allow_master_manual_merge":true,"allow_master_pushes":true,"allow_pushes":false,"required_approved_review_count":1,"required_approved_review_ratio":1,"required_linear_history":false,"required_master_approve":false,"required_must_auto_merge":false,"required_must_push_via_pull_request":false,"required_pull_request_reviews":false,"required_status_checks":false}' `
"<https://api.cnb.cool/><ORG>/hello-cnb/-/settings/branch-protections"
4.3 任务集(L6)
curl.exe -s -X POST -H "Authorization: Bearer $t" -H "Content-Type: application/json" `
-H "Accept: application/vnd.cnb.api+json" `
--data-raw '{"name":"dev-plan","description":"...","visibility":"public","repos":["<ORG>/hello-cnb"]}' `
"<https://api.cnb.cool/><ORG>/-/missions"
4.4 NPC(L7.2)
settings.yml 定义角色 + push 后,建 Issue @ 自己的 NPC:
curl.exe -s -X POST -H "Authorization: Bearer $t" -H "Content-Type: application/json" `
-H "Accept: application/vnd.cnb.api+json" `
--data-raw '{"title":"...","body":"@<ORG>/hello-cnb(expert) hi"}' `
"<https://api.cnb.cool/><ORG>/hello-cnb/-/issues"
# 约 1 分钟后 GET /{repo} 的 flags 应含 NPC
4.5 个人 commit(L7.3)
正常 git push 即可(git 认证用 https://<user>:<token>@cnb.cool/...),author 用账号默认 noreply 邮箱。
5. 需要 Web Cookie 的设置项(L1 的核心 + L3.5/3.6 触发)
要两条东西:浏览器里的 CNBSESSION Cookie 值和 csrfkey 值。前端 JS(_next/static/chunks/pages/_app.js)里能看到 axios baseURL 就是同源根路径,接口路径可从各页面 chunk 里 grep。
请求模板(CSRF 头必须带,否则可能 401):
$ck = "CNBSESSION=<session值>; csrfkey=<csrfkey值>"
curl.exe -s -X PUT -H "Cookie: $ck" -H "X-Csrftoken: <csrfkey值>" `
-H "Accept: application/vnd.cnb.api+json" "<URL>"
5.1 改用户名(L1.1)
# 先查占用
POST <https://cnb.cool/user/rename_check/><新名字> # 返回 {"result":true,...} 即可用
# 再改名
POST <https://cnb.cool/user/rename/><新名字> # 200 即成功,token 不失效
5.2 关注用户(L1.5)
PUT <https://cnb.cool/user/following/><username> # 200 空体即成功
5.3 Star 仓库 = 关注仓库(L1.6)
PUT <https://cnb.cool/user/starred/><org>/<repo> # 200 即成功,follow_repo_count +1
5.4 仓库墙 Pin(L1.4)
PUT <https://cnb.cool/user/pinned-repos>
Content-Type: application/json
body: ["<ORG>/hello-cnb"]
5.5 web_trigger 手动触发(L3.5)
# 拿按钮 id(yml 里配置的按钮,id 形如 "0-0")
GET <https://cnb.cool/><ORG>/hello-cnb/-/build/web-trigger/config?refs=main
# 触发(注意 body 必须是合法 JSON,建议写临时文件避免 shell 转义/BOM 问题)
POST <https://cnb.cool/><ORG>/hello-cnb/-/build/start/web-trigger
body: {"ref":"main","env":{},"event":"web_trigger","id":"0-0","customTitle":"api trigger"}
5.6 tag_deploy 部署(L3.6)
# deployList 查询:ref 必须带 refs/tags/ 前缀(不带前缀报 DEPLOY_TYPE_ERROR)
GET <https://cnb.cool/><ORG>/hello-cnb/-/build/deploy/deploy-config?ref=refs/tags/v0.2.1
# 触发部署
POST <https://cnb.cool/><ORG>/hello-cnb/-/build/start/deploy
body: {"ref":"refs/tags/v0.2.1","environmentName":"development","sync":false}
踩坑:tag 指向的 commit 的 .cnb.yml 里必须有 tag_deploy.<环境名> 事件配置,且配置需先随 tag push 上去,否则构建报 CI config file not found。
5.7 云原生开发工作空间(L4.1,token 也能开)
POST <https://api.cnb.cool/><ORG>/hello-cnb/-/workspace/start
body: {"slug":"<ORG>/hello-cnb","branch":"main"}
失败会留 pending/error 记录,可用 POST /{repo}/-/build/stop/<SN> 停掉再重开。
6. 提交上游 PR 并让 CI 全绿
- 在闯关仓库建一个分支,加一个无关紧要的文件(如
hello.txt),push - 跨仓 PR 用 API 直接建(不需要 fork 关系):
curl.exe -s -X POST -H "Authorization: Bearer $t" -H "Content-Type: application/json" `
-H "Accept: application/vnd.cnb.api+json" `
--data-raw '{"title":"天才程序员来报道!","head":"<分支名>","head_repo":"<ORG>/hello-cnb","base":"main","body":"..."}' `
"<https://api.cnb.cool/cnb/tutorial/hello-cnb/-/pulls>"
- 查 CI 结果:
curl.exe -s -H "Authorization: Bearer $t" -H "Accept: application/vnd.cnb.api+json" `
"<https://api.cnb.cool/cnb/tutorial/hello-cnb/-/pulls/><PR号>/commit-statuses"
- 重要:源分支后续 push 不会自动重跑上游 CI。需要重跑时,关闭再重开 PR(
PATCH /pulls/<n>body{"state":"closed"}→{"state":"open"}),reopened 事件会触发pull_request.target流水线 - L1 的检查项全部就绪后重跑,8 条全绿,
bind-genius自动绑定身份
7. 多账号批量复现清单
对每个新账号,按顺序执行(约 15~20 分钟/个):
-
GET /user验 token,记录 username - 镜像 push 建
<ORG>/hello-cnb - 写入 LICENSE、.cnb.yml、.cnb/settings.yml、.cnb/tag_deploy.yml、.cnb/web_trigger.yml,push main
- 等 push 流水线跑完(KB+Docker),确认 flags=KnowledgeBase、docker 包存在
- API:改 bio、建保护分支、建任务集
- 建 Issue @ NPC,等 flags=KnowledgeBase,NPC
- API:开工作空间(失败则 stop 后重试)
- Web Cookie:改用户名 → 关注 2~3 人 → star 2 个仓库 → pin 仓库
- 建 v* tag push(触发 tag_push)
- Web Cookie:web-trigger 按钮(L3.5)、start/deploy(L3.6)
- 建分支 hello.txt,push,API 建上游 PR
- 查 commit-statuses,不绿则关闭重开 PR;全绿收工
附录 A:.cnb/settings.yml 完整示例
npc:
roles:
- name: expert
slogan: Tutorial assistant
prompt: |
You are 'expert', a concise technical assistant for this CNB tutorial repo.
workspace:
launch:
button:
name: Start Coding
description: Launch cloud dev environment
hover:
- image: <https://cnb.cool/cnb/tutorial/hello-cnb/-/git/raw/main/assets/banner.svg>
- title: Cloud Native Dev
description: Full dev environment in browser
fork:
button:
name: Fork me
description: Fork this tutorial repo
hover:
- image: <https://cnb.cool/cnb/tutorial/hello-cnb/-/git/raw/main/assets/banner.svg>
- title: Hello CNB
description: CNB onboarding tutorial
附录 B:.cnb/tag_deploy.yml
environments:
- name: development
description: Development environment
env:
name: development
tag_name: $CNB_BRANCH
- name: staging
description: Staging environment
env:
name: staging
tag_name: $CNB_BRANCH
附录 C:.cnb/web_trigger.yml
branch:
- buttons:
- name: Manual Build
description: Trigger manual web_trigger pipeline
event: web_trigger
附录 D:经验性结论
- swagger.json 是唯一权威,OpenAPI 文档页只是入口
- 前端私有接口的路径都在 Next.js 页面 chunk 里,
_app.js+ 对应页面 chunk grep 即可还原全部 Web API - 请求头缺
Accept: application/vnd.cnb.api+json时 POST/DELETE 会 406(GET 不挑) - PowerShell 传 JSON body 建议
InFile(UTF8 无 BOM),-data-raw的引号转义在 cmd/PS 下极易出错 - 构建状态排障三板斧:
build/logs列表 →build/status/<SN>→build/logs/stage/<SN>/<PID>/<STAGE> - 删仓库接口被组织管理策略挡(root group management rules),需要网页操作
- token 粒度:改用户资料需要
account-profile:rw,仓库设置需要repo-manage:rw,给 token 勾权限时按需给
欢迎指出任何有错误或不够清晰的表达,可以在下面评论区评论。