feat(providers): add CNB (cnb.cool) git provider#208
Conversation
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
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! |
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.tsmapscnb.cool/cnb.woa.comhosts to the provider and registers it in the factory. No behavior changes for existing providers.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.