feat(integrations): add Bitbucket Cloud - #6860
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview The surface area is 30 registered tools (workspaces through pipeline step logs), a workflow block with operation-specific fields, cascading workspace/repository pickers, and server routes that authorize credentials, refresh tokens, and call Bitbucket with strict API cursor validation (host/path/workspace binding, no redirects) plus bounded JSON and raw reads. OAuth is wired end-to-end: consumer config env vars, connector registration (basic-auth token exchange), self-hosted docs with required consumer permissions, connect-modal scope text keyed by provider, and catalog/docs/icons for the integration page. Supporting tests cover block↔tool mapping, selector hooks, and repository/workspace API routes (auth order, malformed provider responses, cursor rejection). Reviewed by Cursor Bugbot for commit f5cf56c. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryAdds a Bitbucket Cloud OAuth integration with repository, source, pull-request, and pipeline actions.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/auth/connectors/providers.ts | Registers Bitbucket as a connector-only OAuth provider with Basic-auth token exchange and scoped user-info retrieval. |
| apps/sim/lib/oauth/oauth.ts | Adds Bitbucket refresh configuration and rotating refresh-token handling through the existing credential persistence path. |
| apps/sim/app/api/tools/bitbucket/workspaces/route.ts | Adds an authenticated, credential-authorized workspace selector endpoint with validated pagination. |
| apps/sim/app/api/tools/bitbucket/repositories/route.ts | Adds a credential-authorized repository selector endpoint scoped to a validated workspace. |
| apps/sim/blocks/blocks/bitbucket.ts | Defines the Bitbucket block’s 30 operations, cascading selectors, parameter mappings, outputs, and canvas presentation. |
| apps/sim/tools/bitbucket/utils.ts | Implements shared URL binding, response normalization, pagination, and bounded byte-reading utilities. |
| apps/sim/tools/bitbucket/utils.server.ts | Implements pinned secure reads, constrained redirect resolution, retry behavior, and response-size protections. |
| apps/sim/tools/registry.ts | Registers all new Bitbucket tools for generic workflow dispatch. |
Sequence Diagram
sequenceDiagram
participant User as Workflow user
participant Block as Bitbucket block
participant Selector as Selector API
participant OAuth as OAuth credential service
participant Tool as Bitbucket tool
participant BB as Bitbucket Cloud
User->>Block: Configure operation
Block->>Selector: Load workspaces/repositories
Selector->>OAuth: Authorize credential use
OAuth-->>Selector: Access token
Selector->>BB: Fetch selector options
BB-->>Selector: Paginated resources
Selector-->>Block: Normalized options
User->>Block: Execute operation
Block->>Tool: Mapped operation parameters
Tool->>OAuth: Resolve or refresh token
OAuth-->>Tool: Valid access token
Tool->>BB: Validated API request
BB-->>Tool: API/raw response
Tool-->>Block: Bounded normalized output
Reviews (3): Last reviewed commit: "fix(bitbucket): stop advanced-field leak..." | Re-trigger Greptile
c80ee96 to
e74c06c
Compare
…nd selector paths Splits the `closeSourceBranch` advanced subBlock into per-operation ids. Advanced fields serialize without evaluating their condition, so a value set on Create Pull Request reached Merge Pull Request and closed the source branch unprompted. Also: - read step logs through the byte-capped server transport and map an empty-log 416 to an empty result, keeping a genuine 416 an error - trim a step log's partial leading line after the character cap rather than before, and never return an empty log when the retained window held content - surface Bitbucket's `error.detail` alongside `error.message` - treat commit-status `key`/`state` as nullable so one malformed row cannot drop a page - match repository `full_name` case-insensitively and reject dot segments in a workspace slug before the outbound request - type `reviewerAccountIds` as the comma-separated string it is - trim optional Bitbucket query strings; correct the token lifetime to two hours
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit d226be6. Configure here.
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d226be6. Configure here.
| } | ||
| } else if (candidatePath.replace(/\/$/, '') !== exactPath) { | ||
| throw new Error('nextUrl does not belong to this Bitbucket list endpoint') | ||
| } |
There was a problem hiding this comment.
Case-sensitive Bitbucket path binding
Medium Severity
Workspace and repository slugs are bound with exact pathname equality in bitbucketApiUrl, validateBitbucketPullRequestRedirect, and mergeTaskLocation, while Bitbucket and the repository selector treat those slugs as case-insensitive. A mixed-case workspaceSlug or repoSlug still works on the first request, but provider next links, PR diff/diffstat Location headers, and async merge task URLs typically use the canonical lowercase path, so pagination and post-merge polling throw even though Bitbucket accepted the original request. A failed merge-task parse after 202 is especially painful because the merge may already have started.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit d226be6. Configure here.
There was a problem hiding this comment.
Real bug, fixed in 5fb1ae5.
Bitbucket resolves workspace and repository slugs case-insensitively but echoes the canonical lowercase form back, so exact string equality broke every follow-up request after a mixed-case slug succeeded on the first one. All three sites now compare case-insensitively via a shared equalsIgnoreCase helper:
bitbucketApiUrl— both the exact-path branch and thenextPathPrefixsegment comparison, plusnextRevision(hex SHAs are case-insensitive by definition, andrequireBitbucketSha1already accepts uppercase)validateBitbucketPullRequestRedirect— prefix match only; the opaque spec after the prefix is still sliced from the original pathname verbatimmergeTaskLocation— same, with the task id decoded from the untouched pathname
Repository file paths deliberately keep verbatim comparison — git treats those as case-sensitive, so src/Dir must not match src/dir. There is a test asserting exactly that alongside the mixed-case acceptance cases, in utils.test.ts and pull-requests.test.ts.
Worth noting the same class of bug was independently found and fixed in the repository selector route in the previous commit (full_name prefix match); this closes it in the tool layer too.
There was a problem hiding this comment.


Summary
Adds a complete Bitbucket Cloud action integration with 30 OAuth-backed tools for repository/source inspection, pull request collaboration, and pipeline operations.
Includes:
No triggers or webhooks are included.
Type of Change
Testing
bunx vitest run app/api/tools/bitbucket hooks/selectors/providers/bitbucket blocks/blocks/bitbucket.test.ts tools/bitbucket— 323 tests passedbun run tool-metadata:checkbun run check:tool-registry-boundarybun run apps/sim/scripts/check-canvas-sentences.ts --block=bitbucket— 30/30 operationsbun run check:bare-iconsbun run integration-catalog:checkbun run docs:checkbun run check:api-validationbun run type-checkgit diff --checkReviewer focus:
Known follow-ups intentionally outside this PR:
typediscriminator needs a disposable live-provider probe before adding an undocumented value.Checklist
Screenshots/Videos
Not applicable; no standalone visual workflow changes.