feat(providers): add CNB (cnb.cool) git provider#208
Conversation
d65f445 to
1273c83
Compare
|
Thanks for the thorough implementation and the live-tested E2E — the One blocker before this can merge, per our docs-sync convention (see
While updating the guide, please also call out the current capability gap: The accept/decline call on carrying a third provider is for the maintainers, but getting the docs in now makes it a complete, mergeable PR either way. Thanks! |
1273c83 to
6f704aa
Compare
|
Friendly nudge on this one — it's been green and mergeable since opening, live-tested end-to-end against real cnb.cool, and I've just rebased it onto current The only thing blocking it is the scope call I flagged up top: do you want a CNB provider in-tree or not? Totally fine either way — I just don't want it to sit in limbo. To make the decision cheap:
Could you give it a 👍/👎 on direction when you have a moment? That's all it needs. |
Adds a third GitProvider alongside github and tgit, following the same
"thin class over a platform CLI" shape as the TGit provider. CNB's official CLI
(`@cnbcool/cnb-cli`) exposes everything the GitProvider interface needs:
- `cnb login` (OAuth2 device flow) + `cnb status` → authenticate / isAuthenticated
- git clone with token / `cnb git-credential` → cloneRepo
- `cnb pulls post-pull` → createPullRequest
- `cnb repositories create-repo` → createRepo
- `cnb users get-user-info` → username
Auth mirrors the GitHub provider's dual path: interactive `cnb login`, or a
`CNB_TOKEN` env var for headless/CI use — the same pattern as GITHUB_TOKEN.
registry.ts maps `cnb.cool` / `cnb.woa.com` to this provider and registers it.
Three robustness issues surfaced by live testing against real cnb.cool and fixed
here (none were caught by a build-only check):
- cnbWhoami() returned the CNB_USERNAME credential placeholder ("cnb") instead
of the real account; now parses the API's `username:` first.
- the CLI prints YAML, not JSON, so username / PR-URL parsing is regex-based.
- the CLI exits 0 even on a 4xx API response, so a non-zero exit code is not
enough to detect failure; `assertCnbApiOk()` now also checks the printed
`status:` and throws on >= 400 (with the API's errmsg).
Test Plan:
- npx tsc --noEmit ; npm run build
- npx vitest run — 142 files, 1754 tests; 9 new in cnb-provider.test.ts (host
detection, factory, repo-input parsing incl. nested groups, assertCnbApiOk).
- Opt-in live smoke in src/__tests__/e2e/cnb-provider-live.test.ts (skipped
without CNB_TOKEN): asserts isAuthenticated() + a real account username.
Read-only by design — some CNB namespaces block Open-API resource deletion, so
a create/delete test would orphan repos.
- The full mutating flow (createRepo → cloneRepo → push → createPullRequest) was
verified manually against real cnb.cool; PR URL came back
https://cnb.cool/<owner>/<repo>/-/pulls/1.
Claude-Session: https://claude.ai/code/session_01GEV81Xj6mhPzSPsyBrDPSd
6f704aa to
884d7b6
Compare
|
Follow-up: I've scoped this down to cnb.cool only, so the PR now matches what's actually been tested. Why: I confirmed the internal path is feasible for a future PR — Changes in this revision:
Re-verified on current |
Follow-up doc pass for #208 (CNB provider) and #192 (session save), which shipped without doc coverage. - docs/providers.md: provider count 两个 → 三个; add `cnb` to the table and the auto-detection block; new "CNB Provider(cnb.cool)" section — auth via `cnb login` / `CNB_TOKEN`, operations delegated to @cnbcool/cnb-cli, nested paths, and the cnb.cool-only scope + TEAMAI_CNB_HOST/CNB_API_ENDPOINT note. - README.md / README.zh-CN.md: add CNB to the git-host list. - docs/usage-guide.md / .zh-CN.md: add CNB to the create-repo step and prerequisites; new "Session Save" section for `teamai session save` (--push / --force / --include-prompt, local ~/.teamai/session-logs path, 90-day retention, "valuable" heuristic, digest Session Highlights, privacy). Docs-only, bilingual kept in sync. Built and verified the documented surface: `session save --help` shows the flags; the cnb.cool host mapping is in the build. Co-authored-by: Eyre921 <Eyre921@users.noreply.github.com>
Summary
Adds a third
GitProvider— CNB (cnb.cool) — alongsidegithubandtgit, using the exact "thin class over a platform CLI" shape the TGit provider established. CNB's official CLI (@cnbcool/cnb-cli) already exposes everything theGitProviderinterface needs, so this is mostly mechanical mirroring of the existing pattern.Type of Change
How each interface method maps to the CNB CLI
GitProviderauthenticate/isAuthenticatedcnb login(OAuth2 device flow) +cnb statuscloneRepogit clonewith token, orcnb git-credentialhelpercreatePullRequestcnb pulls post-pullcreateRepocnb repositories create-repocnb users get-user-info(orCNB_USERNAME)Auth mirrors the GitHub provider's dual path: interactive
cnb loginon a dev machine, or aCNB_TOKENenv var for headless/CI use (no login step) — the same idea asGITHUB_TOKEN.Wiring:
registry.tsmaps thecnb.coolhost to the provider and registers it in the factory. No behavior changes for existing providers. (Scoped tocnb.coolonly; the internalcnb.woa.commirror is a feasible future add but is untested and intentionally left out — see the scope-down comment below.)Test Plan
npx tsc --noEmit,npm run buildnpx vitest run— 142 files, 1751 tests; 6 new incnb-provider.test.ts(host detection, factory, repo-input parsing incl. nested group paths)createRepo → cloneRepo → push main + feature → createPullRequest → delete-repocleanup. The PR URL came backhttps://cnb.cool/<owner>/<repo>/-/pulls/1.Two bugs the live run surfaced (and this PR fixes) — build alone didn't catch them:
cnbWhoami()returned theCNB_USERNAMEcredential placeholder ("cnb") instead of the real account; now parsesusername:from the API first.JSON.parse.Notes for Reviewers
CNB_TOKENsecret and creates/deletes a real repo. Only the pure unit tests run in CI. Happy to add a gated e2e test (behindCNB_TOKEN, self-cleaning) if you want one in the suite.cnbCLI, exactly astgitshells out togf.ensureInstalled()installs it vianpm i -g @cnbcool/cnb-cliwhen missing.getDefaultProvider()is untouched: CNB is only selected by explicitcnb.coolhost, never as a fallback.