Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/labels-and-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ or a contract-free mix of substrates (e.g. `tools/spec-inventory` is
| [`tools/egress-gateway`](../tools/egress-gateway/) | `substrate:sandbox` | Egress-allowlist forward proxy (proxy.py plugin); host-level egress chokepoint — defence-in-depth for RFC-AI-0003 §4.4 |
| [`tools/container-gateway`](../tools/container-gateway/) | `substrate:sandbox` | Per-project policy proxy for the podman / docker API; label-scoped, mount- and privilege-checked container access from inside the sandbox |
| [`tools/forwarder-relay`](../tools/forwarder-relay/) | `contract:report-relay` | Adapter contract for inbound-relay backends (ASF Security relay, huntr.com, HackerOne triagers). Pure interface spec; adapters declare detection + credit-extraction + reporter-addressing rules. |
| [`tools/bitbucket`](../tools/bitbucket/) | `contract:change-request` + `contract:tracker` | Coverage: `partial`. Bitbucket Cloud and Bitbucket Data Center bridge foundation for repository metadata context, branch restriction context for PR-management decisions, pull-request discovery/fetching, read-only commit fetching, read-only diff fetching, comments-only discussion fetching, read-only review-state fetching, Cloud-only pull-request task listing/fetching, read-only merge-check context fetching, and read-only status fetching, plus narrowly scoped Cloud pull-request comment creation and approve/unapprove actions. Native Bitbucket issue operations are not implemented: Atlassian removed the native Bitbucket Cloud Issue Tracker API on 2026-08-20 and Data Center native issues were never supported, so the historical issue CLI surface fails closed before any request. Data Center `pr jira-issues <id>` provides read-only discovery of Jira keys associated with pull-request commits and hands them to the Jira bridge (`tools/jira`) for tracker operations. The `partial` qualifier means this tool implements named contract operations but does not satisfy the complete contract and must not be counted as a complete/selectable backend. Broader linked Jira coverage and the remaining pull-request coverage are incomplete. |
| [`tools/bitbucket`](../tools/bitbucket/) | `contract:change-request` + `contract:tracker` | Coverage: `partial`. Bitbucket Cloud and Bitbucket Data Center bridge foundation for repository metadata context, branch restriction context for PR-management decisions, pull-request discovery/fetching, read-only commit fetching, read-only diff fetching, comments-only discussion fetching, read-only review-state fetching, Cloud-only pull-request task listing/fetching, read-only merge-check context fetching, and read-only status fetching, plus narrowly scoped pull-request comment creation on Cloud and Data Center and Cloud-only approve/unapprove actions. Native Bitbucket issue operations are not implemented: Atlassian removed the native Bitbucket Cloud Issue Tracker API on 2026-08-20 and Data Center native issues were never supported, so the historical issue CLI surface fails closed before any request. Data Center `pr jira-issues <id>` provides read-only discovery of Jira keys associated with pull-request commits and hands them to the Jira bridge (`tools/jira`) for tracker operations. The `partial` qualifier means this tool implements named contract operations but does not satisfy the complete contract and must not be counted as a complete/selectable backend. Broader linked Jira coverage and the remaining pull-request coverage are incomplete. |
| [`tools/forgejo`](../tools/forgejo/) | `contract:tracker` + `contract:source-control` + `contract:change-request` | Coverage: `partial`. Forgejo / Gitea REST API and `tea` CLI forge bridge foundation for issue listing/fetching, confirmed issue creation, body edits, comments, labels, and milestones under `contract:tracker`, git-backed branch/commit/push operations under `contract:source-control`, and pull-request creation via REST API / compare URL and label edits under `contract:change-request`. Project boards are unsupported (`no-op`) due to absence of REST card/column endpoints. The `partial` qualifier means this tool implements named contract operations but does not satisfy the complete contract and must not be counted as a complete/selectable backend. |
| [`tools/fossil`](../tools/fossil/) | `contract:tracker` + `contract:source-control` | Fossil SCM forge bridge: integrates local SQLite-backed ticket tracking, wiki, and forum reads with the version-control shim |
| [`tools/github`](../tools/github/) | `contract:tracker` + `contract:source-control` + `contract:change-request` + `contract:people` | GitHub REST / GraphQL tracker substrate (called by every lifecycle phase) plus the Git source-control binding documented in [`source-control.md`](../tools/github/source-control.md) (runnable backend in [`tools/vcs`](../tools/vcs/)), the pull-request review/merge gate (`change-request`; the ASF default backend, alongside `tools/jira-patch/` and `tools/mail-patch/` for SVN-first projects), and account profiles / collaborators / team membership (`people`) |
Expand Down
36 changes: 18 additions & 18 deletions tools/bitbucket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fuller Pipelines run/log/retry coverage.
## Partial coverage roadmap

The Bitbucket bridge currently provides partial coverage for repository
and pull-request context (the native issue commands are fail-closed stubs), plus narrowly scoped Bitbucket Cloud
and pull-request context (the native issue commands are fail-closed stubs), plus narrowly scoped Bitbucket
write operations. It intentionally does not claim full Bitbucket backend parity.

Implemented commands and compatibility stubs:
Expand All @@ -77,7 +77,7 @@ Implemented commands and compatibility stubs:
- `magpie-bitbucket pr jira-issues <id>` (Data Center-only linked Jira discovery)
- `magpie-bitbucket pr diff <id>`
- `magpie-bitbucket pr discussion <id>`
- `magpie-bitbucket pr comment <id> --body-file <path>` (Cloud-only write)
- `magpie-bitbucket pr comment <id> --body-file <path>` (Cloud and Data Center write)
- `magpie-bitbucket pr reviews <id>`
- `magpie-bitbucket pr review <id> --verdict {comment,approve,request-changes} --body-file <path>` (Cloud-only write)
- `magpie-bitbucket pr approve <id>` (Cloud-only write)
Expand All @@ -104,10 +104,10 @@ including reviewers, approvals, change-request signals, and related review
activity where exposed by the configured Bitbucket backend.

Write coverage is intentionally narrow. The bridge supports confirmed
Bitbucket Cloud top-level pull-request comment creation and pull-request
approve/unapprove, request-changes/remove-request-changes, decline,
backend-neutral reject, and merge actions after the calling skill has
obtained explicit user confirmation. Native Bitbucket Cloud issue writes
top-level pull-request comment creation on Bitbucket Cloud and Data Center.
Additional confirmed Cloud-only writes cover pull-request approve/unapprove,
request-changes/remove-request-changes, decline, backend-neutral reject, and
merge actions after the calling skill has obtained explicit user confirmation. Native Bitbucket Cloud issue writes
are unavailable because Atlassian removed the native Issue Tracker API.
Other writes, such as editing/deleting pull-request comments, changing
branches, or triggering builds, remain out of scope and should be added
Expand Down Expand Up @@ -160,7 +160,7 @@ surface:
| Change requests / tracker handoff | `pr jira-issues <id>` | Partial read-only, Data Center only | Fetches Jira issue keys associated by Bitbucket Data Center with commits in the pull request. Output identifies `tools/jira` as the handoff tool; this command does not fetch or mutate Jira issues. Bitbucket Cloud has no equivalent bridge endpoint here and fails closed. |
| Change requests | `diff` supplement / `pr diff <id>` | Partial read-only | Fetches the pull request unified diff so partial Bitbucket `get` coverage can expose proposal diffs. This does not mutate files, branches, refs, or repository history. |
| Change requests | `get_discussion` / `pr discussion <id>` | Partial read-only | Fetches a comments-only discussion subset with pagination. Participants beyond comment authors and unresolved-thread accounting remain incomplete. |
| Change requests | `pr comment <id> --body-file <path>` | Partial write, Cloud only | Creates one top-level Bitbucket Cloud pull-request comment from a caller-supplied body file after explicit caller-side confirmation. Data Center PR comment writes remain unsupported in this command. |
| Change requests | `pr comment <id> --body-file <path>` | Partial write | Creates one top-level Bitbucket Cloud or Data Center pull-request comment from a caller-supplied body file after explicit caller-side confirmation. |
| Change requests | `reviews` supplement / `pr reviews <id>` | Partial read-only | Fetches reviewers, approvals, change-request signals, pending review requests, normalized review events, and an aggregate review decision. This does not post reviews or mutate PR state. |
| Change requests | `pr approve <id>` / `pr unapprove <id>` | Partial write, Cloud only | Approves or withdraws the authenticated user's approval after explicit caller-side confirmation. Data Center approval writes remain unsupported by these commands. For a review body together with a verdict, use `pr review` (the `post_review` contract). |
| Change requests | `pr request-changes <id>` / `pr remove-request-changes <id>` | Partial write, Cloud only | Requests changes or removes the authenticated user's change request after explicit caller-side confirmation. Data Center change-request writes remain unsupported by these commands. For a review body together with a verdict, use `pr review` (the `post_review` contract). |
Expand Down Expand Up @@ -213,7 +213,7 @@ uv run --project tools/bitbucket magpie-bitbucket pr diff 123
# Fetch pull request discussion/comments
uv run --project tools/bitbucket magpie-bitbucket pr discussion 123

# Create a Bitbucket Cloud pull request comment after caller-side confirmation
# Create a Bitbucket Cloud or Data Center pull request comment after caller-side confirmation
uv run --project tools/bitbucket magpie-bitbucket pr comment 123 --body-file /tmp/comment.txt

# Fetch pull request review state
Expand Down Expand Up @@ -265,7 +265,7 @@ injected by the caller as `BITBUCKET_TOKEN` / `BITBUCKET_CLOUD_USER`.
| Variable | Required for | Description |
|---|---|---|
| `BITBUCKET_KIND` | all commands | `cloud` or `datacenter`. Defaults to `cloud`. |
| `BITBUCKET_TOKEN` | authenticated API calls | API token or personal access token accepted by the selected backend. Read-only PR/repository commands should use minimum read scopes. Cloud pull-request comment, approve/unapprove, request-changes/remove-request-changes, decline, and merge writes require credentials permitted to write pull requests. `repo restrictions` needs elevated repository-admin scope on Bitbucket Cloud and may require `REPO_ADMIN` on Data Center. |
| `BITBUCKET_TOKEN` | authenticated API calls | API token or personal access token accepted by the selected backend. Read-only PR/repository commands should use minimum read scopes. Pull-request comment writes on Cloud or Data Center, plus Cloud approve/unapprove, request-changes/remove-request-changes, decline, and merge writes require credentials permitted to write pull requests. `repo restrictions` needs elevated repository-admin scope on Bitbucket Cloud and may require `REPO_ADMIN` on Data Center. |
| `BITBUCKET_AUTH_SCHEME` | all commands | Authentication scheme. Defaults to `Basic` for Cloud and `Bearer` for Data Center. |
| `BITBUCKET_CLOUD_USER` | Cloud Basic auth | Atlassian account email/user used with `BITBUCKET_TOKEN`. |
| `BITBUCKET_WORKSPACE` | Cloud | Bitbucket Cloud workspace slug. |
Expand All @@ -292,29 +292,29 @@ to know which backend answered.

## Write-path discipline

The bridge can execute narrowly scoped Bitbucket Cloud pull-request
The bridge can execute narrowly scoped Bitbucket pull-request
mutations, but it does **not** decide whether to mutate. Every write operation
must be gated on **explicit user confirmation in the calling skill**; the bridge
only executes an already-confirmed action.

Comment bodies are read from `--body-file` to avoid shell-quoting issues.
Missing or empty body files fail before any outbound write request is made.

The bridge currently supports these narrow Cloud mutations (native Cloud
The bridge currently supports these narrow mutations (native Cloud
issue writes were removed upstream and fail closed):

- top-level pull-request comment creation
- pull-request approval and approval withdrawal
- pull-request change-request creation and removal
- pull-request decline
- pull-request merge with source-commit pinning
- top-level pull-request comment creation on Cloud and Data Center
- Cloud-only pull-request approval and approval withdrawal
- Cloud-only pull-request change-request creation and removal
- Cloud-only pull-request decline
- Cloud-only pull-request merge with source-commit pinning

For pull-request merge, the calling skill must run and inspect
`pr merge-checks <id>` before invoking `pr merge`; the merge command itself
does not independently enforce approval, build-status, or merge-check gates.

Bitbucket Data Center issue-comment, pull-request-comment, review-state,
decline, and merge writes remain unsupported by these commands.
Bitbucket Data Center issue-comment, review-state, decline, and merge
writes remain unsupported by these commands.

All other Bitbucket mutations remain out of scope for the current bridge and
must be introduced separately with the same confirmation discipline.
Expand Down
37 changes: 28 additions & 9 deletions tools/bitbucket/src/magpie_bitbucket/datacenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,15 @@
import json
from typing import Any

from magpie_bitbucket.client import BitbucketConfig, BitbucketError, get_json, get_text, quote_path, require
from magpie_bitbucket.client import (
BitbucketConfig,
BitbucketError,
get_json,
get_text,
post_json,
quote_path,
require,
)


def _api_base(config: BitbucketConfig) -> str:
Expand Down Expand Up @@ -476,19 +484,26 @@ def _pull_request_source_commit(raw: dict[str, Any]) -> str:
raise BitbucketError(msg)


# Bitbucket Data Center exposes PR comments through the broader activities feed.
# We fetch the paginated feed here and filter comment-bearing activities during
# normalization so review/merge/rescope lifecycle events are not exposed as
# discussion comments.
def create_pull_request_comment(
config: BitbucketConfig,
pull_request_id: str,
body: str,
) -> dict[str, Any]:
"""Reject pull-request comment creation for Data Center for now."""
_ = (config, pull_request_id, body)
msg = "Bitbucket Data Center pull request comment writes are not supported by this command yet"
raise BitbucketError(msg)
"""Create one top-level comment on a Bitbucket Data Center pull request."""
project_key = quote_path(require(config.project_key, "BITBUCKET_PROJECT_KEY"))
repo_slug = quote_path(require(config.repo_slug, "BITBUCKET_REPO_SLUG"))
pr_id = quote_path(pull_request_id)
url = f"{_api_base(config)}/projects/{project_key}/repos/{repo_slug}/pull-requests/{pr_id}/comments"

comment = post_json(
url,
config,
{"text": body},
)
return {
"pull_request_id": pull_request_id,
"comment": comment,
}


def post_pull_request_review(
Expand Down Expand Up @@ -516,6 +531,10 @@ def reject_pull_request(
)


# Bitbucket Data Center exposes PR comments through the broader activities feed.
# We fetch the paginated feed here and filter comment-bearing activities during
# normalization so review/merge/rescope lifecycle events are not exposed as
# discussion comments.
def get_pull_request_discussion(config: BitbucketConfig, pull_request_id: str) -> dict[str, Any]:
"""Fetch pull request activities from Bitbucket Data Center."""
project_key = quote_path(require(config.project_key, "BITBUCKET_PROJECT_KEY"))
Expand Down
7 changes: 6 additions & 1 deletion tools/bitbucket/src/magpie_bitbucket/normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,12 @@ def created_pull_request_comment(
) -> dict[str, Any]:
"""Normalize the result of creating one pull request comment."""
comment = raw.get("comment")
normalized = _cloud_comment(comment) if kind == "cloud" and isinstance(comment, dict) else {}
if not isinstance(comment, dict):
normalized = {}
elif kind == "cloud":
normalized = _cloud_comment(comment)
else:
normalized = _datacenter_comment(comment, {}, None)

return {
"ok": bool(normalized),
Expand Down
Loading
Loading