Skip to content

Commit

Permalink
added "List comments for a pull request review" https://docs.github.c…
Browse files Browse the repository at this point in the history
  • Loading branch information
dmgorsky committed Mar 17, 2024
1 parent 1a59acc commit 151027a
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/api/pulls/specific_pr/pr_reviews/specific_review.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::models::pulls::{Review, ReviewAction};
use crate::pulls::specific_pr::pr_reviews::specific_review::list_comments::ListReviewCommentsBuilder;
use crate::pulls::PullRequestHandler;

mod list_comments;

#[derive(serde::Serialize)]
pub struct SpecificReviewBuilder<'octo, 'b> {
#[serde(skip)]
Expand Down Expand Up @@ -105,4 +108,10 @@ impl<'octo, 'b> SpecificReviewBuilder<'octo, 'b> {
)
.await
}

///Lists comments for a specific pull request review.
///see https://docs.github.com/en/rest/pulls/reviews?apiVersion=2022-11-28#list-comments-for-a-pull-request-review
pub fn list_comments(&self) -> ListReviewCommentsBuilder<'octo, '_> {
ListReviewCommentsBuilder::new(self.handler, self.pr_number, self.review_id)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use super::*;

#[derive(serde::Serialize)]
pub struct ListReviewCommentsBuilder<'octo, 'b> {
#[serde(skip)]
handler: &'b PullRequestHandler<'octo>,
pr_number: u64,
review_id: u64,
#[serde(skip_serializing_if = "Option::is_none")]
per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<u32>,
}

impl<'octo, 'b> ListReviewCommentsBuilder<'octo, 'b> {
pub(crate) fn new(
handler: &'b PullRequestHandler<'octo>,
pr_number: u64,
review_id: u64,
) -> Self {
Self {
handler,
pr_number,
review_id,
per_page: None,
page: None,
}
}

/// Results per page (max 100).
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.per_page = Some(per_page.into());
self
}

/// Page number of the results to fetch.
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.page = Some(page.into());
self
}

/// Sends the actual request.
pub async fn send(self) -> crate::Result<crate::Page<crate::models::pulls::ReviewComment>> {
let route = format!(
"/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments",
owner = self.handler.owner,
repo = self.handler.repo,
pull_number = self.pr_number,
review_id = self.review_id
);
self.handler.crab.get(route, Some(&self)).await
}
}
1 change: 1 addition & 0 deletions src/models/commits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use super::{reactions::ReactionContent, *};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Comment {
// TODO check actuality comparing with github json schema and pulls::ReviewComment
pub html_url: Url,
pub url: Url,
pub id: CommentId,
Expand Down
48 changes: 48 additions & 0 deletions src/models/pulls.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use crate::models::commits::CommentReactions;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
Expand Down Expand Up @@ -285,6 +286,53 @@ pub struct Comment {
pub side: Option<String>,
}

///Legacy Review Comment
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ReviewComment {
pub url: Url,
pub pull_request_review_id: Option<ReviewId>,
pub id: CommentId,
pub node_id: String,
pub diff_hunk: String,
pub path: String,
pub position: Option<u64>,
pub original_position: Option<u64>,
pub commit_id: String,
pub original_commit_id: String,
#[serde(default)]
pub in_reply_to_id: Option<CommentId>,
pub user: Option<Author>,
pub body: String,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
pub html_url: String,
pub pull_request_url: String,
pub author_association: AuthorAssociation,
#[serde(rename = "_links")]
pub links: Links,
#[serde(skip_serializing_if = "Option::is_none")]
pub body_text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub body_html: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reactions: Option<CommentReactions>,
pub side: Option<Side>,
pub start_side: Option<Side>,
pub line: Option<u64>,
pub original_line: Option<u64>,
pub start_line: Option<u64>,
pub original_start_line: Option<u64>,
}

#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all(serialize = "SCREAMING_SNAKE_CASE"))]
#[non_exhaustive]
pub enum Side {
Left,
Right,
}

/// A Thread in a pull request review
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
Expand Down
27 changes: 26 additions & 1 deletion tests/pull_request_review_operations_test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};

use octocrab::models::pulls::{Review, ReviewAction};
use octocrab::models::pulls::{Review, ReviewAction, ReviewComment};
use octocrab::Octocrab;

use crate::mock_error::setup_error_handler;
Expand All @@ -22,7 +22,12 @@ fn setup_octocrab(uri: &str) -> Octocrab {
async fn should_work_with_specific_review() {
let review_ops_response: Review =
serde_json::from_str(include_str!("resources/get_pull_request_review.json")).unwrap();
let review_comments_response: Vec<ReviewComment> = serde_json::from_str(include_str!(
"resources/get_pull_request_review_comments.json"
))
.unwrap();
let template = ResponseTemplate::new(200).set_body_json(&review_ops_response);
let comments_template = ResponseTemplate::new(200).set_body_json(&review_comments_response);
let mock_server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(format!(
Expand Down Expand Up @@ -59,6 +64,14 @@ async fn should_work_with_specific_review() {
.respond_with(template.clone())
.mount(&mock_server)
.await;
Mock::given(method("GET"))
.and(path(format!(
"/repos/{OWNER}/{REPO}/pulls/{PULL_NUMBER}/reviews/{REVIEW_ID}/comments"
)))
.respond_with(comments_template.clone())
.mount(&mock_server)
.await;

setup_error_handler(
&mock_server,
&format!("request on /repos/{OWNER}/{REPO}/pulls/{PULL_NUMBER}/reviews/{REVIEW_ID} was not received"),
Expand Down Expand Up @@ -106,4 +119,16 @@ async fn should_work_with_specific_review() {
.dismiss("test")
.await;
assert_eq!(result.unwrap(), review_ops_response);

let result = client
.pulls(OWNER, REPO)
.pull_number(PULL_NUMBER)
.reviews()
.review(REVIEW_ID)
.list_comments()
.per_page(15)
.send()
.await;
let result_items = result.unwrap();
assert_eq!(result_items.items, review_comments_response);
}
52 changes: 52 additions & 0 deletions tests/resources/get_pull_request_review_comments.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/1",
"pull_request_review_id": 42,
"id": 10,
"node_id": "MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDEw",
"diff_hunk": "@@ -16,33 +16,40 @@ public class Connection : IConnection...",
"path": "file1.txt",
"position": 1,
"original_position": 4,
"commit_id": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
"original_commit_id": "9c48853fa3dc5c1c3d6f1f1cd1f2743e72652840",
"in_reply_to_id": 8,
"user": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"body": "Great stuff!",
"created_at": "2011-04-14T16:00:49Z",
"updated_at": "2011-04-14T16:00:49Z",
"html_url": "https://github.com/octocat/Hello-World/pull/1#discussion-diff-1",
"pull_request_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1",
"author_association": "NONE",
"_links": {
"self": {
"href": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/1"
},
"html": {
"href": "https://github.com/octocat/Hello-World/pull/1#discussion-diff-1"
},
"pull_request": {
"href": "https://api.github.com/repos/octocat/Hello-World/pulls/1"
}
}
}
]

0 comments on commit 151027a

Please sign in to comment.