Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added missing /repos/{owner}/{repo}/pulls/... handlers (#546) #605

Merged
merged 12 commits into from
Jul 29, 2024
Merged
1 change: 0 additions & 1 deletion src/api/checks.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use chrono::{DateTime, Utc};
use hyper::body::Body;

use crate::models::checks::{AutoTriggerCheck, CheckSuite, CheckSuitePreferences};
use crate::models::{AppId, CheckRunId, CheckSuiteId};
Expand Down
103 changes: 96 additions & 7 deletions src/api/pulls.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
//! The pull request API.

mod comment;
mod create;
mod list;
mod merge;
mod update;

use http::request::Builder;
use http::{Method, Uri};

use serde_json::json;
use snafu::ResultExt;

use crate::error::HttpSnafu;
use crate::models::pulls::ReviewComment;
use crate::models::CommentId;
use crate::pulls::specific_pr::pr_reviews::specific_review::SpecificReviewBuilder;
use crate::pulls::specific_pr::SpecificPullRequestBuilder;
use crate::{Octocrab, Page};

pub use self::{
create::CreatePullRequestBuilder, list::ListPullRequestsBuilder,
update::UpdatePullRequestBuilder,
};

mod comment;
mod create;
mod list;
mod merge;
mod specific_pr;
mod update;

/// A client to GitHub's pull request API.
///
/// Created with [`Octocrab::pulls`].
Expand Down Expand Up @@ -369,6 +374,90 @@ impl<'octo> PullRequestHandler<'octo> {
comment::ListCommentsBuilder::new(self, pr)
}

///creates a new `CommentBuilder` for GET/PATCH/DELETE requests
/// to the `/repos/{owner}/{repo}/pulls/{pr}/comments/{comment_id}` endpoint
/// ```no_run
/// use octocrab::models::CommentId;
/// use octocrab::models::pulls::Comment;
/// async fn run() -> octocrab::Result<Comment> {
/// let octocrab = octocrab::Octocrab::default();
/// let _ = octocrab.pulls("owner", "repo").comment(CommentId(21)).delete();
/// let _ = octocrab.pulls("owner", "repo").comment(CommentId(42)).update("new comment");
/// let comment = octocrab.pulls("owner", "repo").comment(CommentId(42)).get().await;
///
/// comment
/// }
/// ```
pub fn comment(&self, comment_id: CommentId) -> comment::CommentBuilder {
comment::CommentBuilder::new(self, comment_id)
}

/// creates a builder for the `/repos/{owner}/{repo}/pulls/{pull_number}/......` endpoint
/// working with particular pull request, e.g.
/// * /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events
/// * /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}
/// * /repos/{owner}/{repo}/pulls/{pull_number}/commits
/// * /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments
/// * /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals
/// * /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies
///
#[deprecated(
since = "0.34.4",
note = "specific PR builder transitioned to pr_review_actions, reply_to_comment, reply_to_comment"
)]
//FIXME: remove?
pub fn pull_number(&self, pull_nr: u64) -> SpecificPullRequestBuilder {
SpecificPullRequestBuilder::new(self, pull_nr)
}

// /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events
// /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}
// repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments
// repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals
pub fn pr_review_actions(
&self,
pull_nr: u64,
review_id: u64,
) -> SpecificReviewBuilder<'octo, '_> {
SpecificReviewBuilder::new(self, pull_nr, review_id)
}

/// /repos/{owner}/{repo}/pulls/{pull_number}/commits
// pub fn pr_commits(&self, pull_nr: u64) -> SpecificPullRequestCommentBuilder<'octo, '_> {
// SpecificPullRequestCommentBuilder::new(self, pull_nr, 0)
// }
Comment on lines +425 to +428
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please take a look at #680


// /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies
/// Creates a reply to a specific comment of a pull request specified in the first argument
/// ```no_run
/// # use octocrab::models::CommentId;
/// async fn run() -> octocrab::Result<()> {
/// # let octocrab = octocrab::Octocrab::default();
/// use octocrab::params;
///
/// let page = octocrab.pulls("owner", "repo").reply_to_comment(142, CommentId(24), "This is my reply")
/// .await?;
/// # Ok(())
/// # }
/// ```
pub async fn reply_to_comment(
&self,
pull_nr: u64,
comment_id: CommentId,
comment: impl Into<String>,
) -> crate::Result<ReviewComment> {
let route = format!(
"/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies",
owner = self.owner,
repo = self.repo,
pull_number = pull_nr,
comment_id = comment_id
);
self.crab
.post(route, Some(&json!({ "body": comment.into() })))
.await
}

/// Creates a new `MergePullRequestsBuilder` that can be configured used to
/// merge a pull request.
/// ```no_run
Expand Down
74 changes: 74 additions & 0 deletions src/api/pulls/comment.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use serde_json::json;

use crate::models::pulls::Comment;

use super::*;

/// A builder pattern struct for listing comments.
Expand Down Expand Up @@ -84,6 +88,76 @@ impl<'octo, 'b> ListCommentsBuilder<'octo, 'b> {
}
}

/// A builder pattern struct for working with specific comment.
///
/// created by [`PullRequestHandler::comment`]
///
/// [`PullRequestHandler::comment`]: ./struct.PullRequestHandler.html#method.comment
#[derive(serde::Serialize)]
pub struct CommentBuilder<'octo, 'b> {
#[serde(skip)]
handler: &'b PullRequestHandler<'octo>,
comment_id: CommentId,
}

impl<'octo, 'b> CommentBuilder<'octo, 'b> {
pub(crate) fn new(handler: &'b PullRequestHandler<'octo>, comment_id: CommentId) -> Self {
Self {
handler,
comment_id,
}
}

///https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#get-a-review-comment-for-a-pull-request
pub async fn get(self) -> crate::Result<Comment> {
self.handler
.crab
.get(
format!(
"/repos/{owner}/{repo}/pulls/comments/{comment_id}",
owner = self.handler.owner,
repo = self.handler.repo,
comment_id = self.comment_id
),
None::<&Comment>,
)
.await
}

///https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#update-a-review-comment-for-a-pull-request
pub async fn update(self, comment: &str) -> crate::Result<Comment> {
self.handler
.crab
.patch(
format!(
"/repos/{owner}/{repo}/pulls/comments/{comment_id}",
owner = self.handler.owner,
repo = self.handler.repo,
comment_id = self.comment_id
),
Some(&json!({ "body": comment })),
)
.await
}

///https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#delete-a-review-comment-for-a-pull-request
pub async fn delete(self) -> crate::Result<()> {
self.handler
.crab
._delete(
format!(
"/repos/{owner}/{repo}/pulls/comments/{comment_id}",
owner = self.handler.owner,
repo = self.handler.repo,
comment_id = self.comment_id
),
None::<&()>,
)
.await?;
Ok(())
}
}

#[cfg(test)]
mod tests {
#[tokio::test]
Expand Down
101 changes: 101 additions & 0 deletions src/api/pulls/specific_pr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use crate::models::repos::RepoCommit;
use crate::models::CommentId;
use crate::pulls::specific_pr::pr_comment::SpecificPullRequestCommentBuilder;
use crate::pulls::specific_pr::pr_reviews::ReviewsBuilder;
use crate::pulls::PullRequestHandler;
use crate::Page;

mod pr_comment;
pub(crate) mod pr_reviews;
/// A builder pattern struct for working with a specific pull request data,
/// e.g. reviews, commits, comments, etc.
///
/// created by [`PullRequestHandler::pull_number`]
///
/// [`PullRequestHandler::pull_number`]: ./struct.PullRequestHandler.html#method.pull_number
#[derive(serde::Serialize)]
pub struct SpecificPullRequestBuilder<'octo, 'b> {
#[serde(skip)]
handler: &'b PullRequestHandler<'octo>,
pr_number: 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> SpecificPullRequestBuilder<'octo, 'b> {
pub(crate) fn new(handler: &'b PullRequestHandler<'octo>, pr_number: u64) -> Self {
Self {
handler,
pr_number,
per_page: None,
page: None,
}
}

/// Results per page (max: 100, default: 30).
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. (default: 1)
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.page = Some(page.into());
self
}

///Lists a maximum of 250 commits for a pull request.
/// To receive a complete commit list for pull requests with more than 250 commits,
/// use the [List commits](https://docs.github.com/rest/commits/commits#list-commits) endpoint.
pub async fn commits(&self) -> crate::Result<Page<RepoCommit>> {
let route = format!(
"/repos/{owner}/{repo}/pulls/{pr_number}/commits",
owner = self.handler.owner,
repo = self.handler.repo,
pr_number = self.pr_number
);
self.handler.crab.get(route, Some(&self)).await
}

/// Creates a new `ReviewsBuilder`
/// ```no_run
/// # use octocrab::models::CommentId;
/// async fn run() -> octocrab::Result<()> {
/// # let octocrab = octocrab::Octocrab::default();
/// use octocrab::params;
///
/// let _ = octocrab.pulls("owner", "repo")
/// .pull_number(42)
/// .reviews()
/// .review(42)
/// .get()
/// .await;
/// Ok(())
/// }
/// ```
pub fn reviews(&self) -> ReviewsBuilder<'octo, '_> {
ReviewsBuilder::new(self.handler, self.pr_number)
}

/// Creates a new `SpecificPullRequestCommentBuilder`
/// ```no_run
/// # use octocrab::models::CommentId;
/// async fn run() -> octocrab::Result<()> {
/// # let octocrab = octocrab::Octocrab::default();
/// use octocrab::params;
///
/// let _ = octocrab.pulls("owner", "repo")
/// .pull_number(42)
/// .comment(CommentId(42))
/// .reply("new comment")
/// .await;
/// Ok(())
/// }
/// ```
pub fn comment(&self, comment_id: CommentId) -> SpecificPullRequestCommentBuilder {
SpecificPullRequestCommentBuilder::new(self.handler, self.pr_number, comment_id)
}
}
41 changes: 41 additions & 0 deletions src/api/pulls/specific_pr/pr_comment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use serde_json::json;

use crate::models::pulls::ReviewComment;
use crate::models::CommentId;
use crate::pulls::PullRequestHandler;

#[derive(serde::Serialize)]
pub struct SpecificPullRequestCommentBuilder<'octo, 'b> {
#[serde(skip)]
handler: &'b PullRequestHandler<'octo>,
pr_number: u64,
comment_id: CommentId,
}

impl<'octo, 'b> SpecificPullRequestCommentBuilder<'octo, 'b> {
pub(crate) fn new(
handler: &'b PullRequestHandler<'octo>,
pr_number: u64,
comment_id: CommentId,
) -> Self {
Self {
handler,
comment_id,
pr_number,
}
}

pub async fn reply(&self, comment: impl Into<String>) -> crate::Result<ReviewComment> {
let route = format!(
"/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies",
owner = self.handler.owner,
repo = self.handler.repo,
pull_number = self.pr_number,
comment_id = self.comment_id
);
self.handler
.crab
.post(route, Some(&json!({ "body": comment.into() })))
.await
}
}
Loading
Loading