Source code for devops_utils.core.azure_devops.pullrequests

"""Pull-request operations against the Azure DevOps REST API.

Commit comments are intentionally absent: Azure DevOps has no documented REST
endpoint for them (the web UI uses an internal API). Comment on the pull
request containing the commit, or on the work item that links it, instead.
"""

from __future__ import annotations

from typing import Any

from devops_utils.core.azure_devops.client import AzureDevOpsClient

# CommentThreadStatus "active" / CommentType "text" as wire integers.
_THREAD_ACTIVE = 1
_COMMENT_TEXT = 1


[docs] def comment_on_pull_request( client: AzureDevOpsClient, project: str, repo: str, pull_request_id: int, text: str, *, thread_id: int | None = None, ) -> dict[str, Any]: """Comment on a pull request. Without ``thread_id`` a new (active) comment thread is created; with it the comment is appended to that existing thread as a reply. Returns a trimmed ``{thread_id, comment_id, status}`` dict. """ base = f"{project}/_apis/git/repositories/{repo}/pullRequests/{pull_request_id}" comment = {"parentCommentId": 0, "content": text, "commentType": _COMMENT_TEXT} if thread_id is None: data = client.request( "POST", f"{base}/threads", json={"comments": [comment], "status": _THREAD_ACTIVE}, ) thread = data if isinstance(data, dict) else {} comments = thread.get("comments") or [{}] return { "thread_id": thread.get("id"), "comment_id": comments[0].get("id"), "status": thread.get("status"), } data = client.request("POST", f"{base}/threads/{thread_id}/comments", json=comment) created = data if isinstance(data, dict) else {} return {"thread_id": thread_id, "comment_id": created.get("id"), "status": None}