Repository navigation
fix(bitbucket): send inline comment ranges with start_to - #3384
IsmaelMartinez merged 1 commit into
Conversation
publish_code_suggestions already computes the span of a suggestion, but
publish_inline_comments kept only start_line and dropped the end, so every
multi-line suggestion was posted against its first line. The POST body now
moves into a private _post_inline_comment helper that emits
{"start_to": from, "to": to} when there is a real span and the existing
single-line {"to": ...} form otherwise, which keeps the public
publish_inline_comment signature identical to the base contract. An equal or
inverted range is not a span, so it is posted as a single line. Bitbucket Data
Center is untouched because its API really does anchor inline comments to one
line.
PR Summary by QodoAnchor Bitbucket inline comments to multi-line ranges
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo
1. Two range comments use narration
|
IsmaelMartinez
left a comment
There was a problem hiding this comment.
Thanks for scoping this exactly as asked on #3285 and for going back to the API for the field names. Approving.
A 10 to 16 span now goes out as {"start_to": 10, "to": 16}, single-line comments send the same JSON as before, and both range tests go red against main. The helper split is the right call given the provider signature contract.
Qodo's one finding is its own imperative-phrasing rule rather than a repository one, so nothing to change. This lands first of the three Bitbucket PRs; #3386 and #3387 merge cleanly on top.
Fixes #3285.
What
pr_agent/git_providers/bitbucket_provider.py:publish_inline_commentsnow carries the end line of a multi-line comment through to the POST. The request body moved into a new private_post_inline_comment, which sends{"start_to": <start>, "to": <end>}when there is a real span and the existing{"to": <line>}when there is not.publish_inline_commentkeeps its signature and its line-text resolution and calls the same helper. Truncation tomax_comment_lengthmoved into the helper, so the split does not duplicate it across the two entry points. The stale comment claiming Bitbucket has no range support is gone, and the error log names the range it failed to post.tests/unittest/test_bitbucket_provider.py: seven new tests onTestBitbucketProvider, from four test functions. One asserts the exact range payload for a 10 to 16 suggestion, one asserts the single-line payload byte for byte, one is parametrized over the four non-span cases (end equal to start, end below start, end null, end key absent), and one pins the comment-length truncation on the multi-line path._code_suggestiongained an optionalend_line.Why
On main the end line reaches
publish_inline_commentsin the comment dict and is never read:and the payload can only express one line (
bitbucket_provider.py:451). The end line exists one call earlier:publish_code_suggestionsbuilds"line": relevant_lines_end, "start_line": relevant_lines_startatbitbucket_provider.py:203-208.So a suggestion about lines 10 to 16 is posted as a comment on line 10, and a remark about a whole function reads as a remark about its signature. This is the default path on Bitbucket Cloud, not an opt-in one:
pr_code_suggestions.py:336-337renders the markdown table only whengfm_markdownis supported, andBitbucketProvider.is_supportedreturns False for it (bitbucket_provider.py:226-228), so stock/improvealways takes the inline path there.The community thread cited in that comment is from 2022 and was accurate then: a comment anchored to its single
fromline. Atlassian closed BCLOUD-5547 "Multi-line comments & code suggestions" on 24 September 2025 with the statement that Bitbucket Cloud now supports multi-line comments and multi-line code suggestions in pull requests, so the comment is out of date. #3285 reports checking thestart_toandtopayload against a live pull request on 2026-09-10 and seeing the comment render across the range; that check is the reporter's; every test here mocksrequests.request.What this leaves alone. Bitbucket Data Center really does anchor an inline comment to a single line, so
bitbucket_server_provider.pyis untouched and keeps its own note.publish_inline_commentkeeps exactly the parameters the base contract check intests/unittest/test_git_provider_method_contract.pycompares, so no provider signature widens. Single-line comments still send the same JSON string with the same key order. An inverted or zero-width range is not a span, so it is posted as a single line;publish_code_suggestionsalready drops end < start atbitbucket_provider.py:194-200, so the remaining case is end equal to start. The return contract ofpublish_inline_commentsis unchanged, and the truncation tomax_comment_lengthstill applies on both paths.Testing
PYTHONPATH=. uv run pytest tests/unittest/test_bitbucket_provider.pyon this branch: 105 passed. Main is 98.The same file with only the change to
pr_agent/git_providers/bitbucket_provider.pyreverted: 2 failed, 103 passed. The two aretest_publish_code_suggestions_anchors_a_multi_line_suggestion_to_the_whole_rangeandtest_publish_inline_comments_truncates_a_multi_line_body, both sending{"to": <start>, "path": ...}where{"start_to": <start>, "to": <end>, "path": ...}was expected. The other five pass on main by design; they pin behaviour this change must not move.PYTHONPATH=. uv run pytest tests/unittest: 8263 passed, 33 skipped, 1 xfailed in 97.6s.uv run ruff check --fix pr_agent/git_providers/bitbucket_provider.py tests/unittest/test_bitbucket_provider.py: all checks passed, nothing to fix. pre-commit was not run locally; the hook-relevant checks were done by hand on both files: LF line endings, no trailing whitespace, exactly one final newline, and no added line over 120 characters.