Skip to main content

git_bot_feedback/comments/
review_comments.rs

1#[cfg(feature = "pyo3")]
2use pyo3::prelude::*;
3
4use super::DEFAULT_MARKER;
5
6/// A struct to describe a Pull Request review.
7///
8/// Each review is considered to be about the PR event's changes.
9/// There is no support for posting reviews on older/outdated PR events.
10#[derive(Debug, PartialEq, Eq, Clone)]
11#[cfg_attr(
12    feature = "pyo3",
13    pyclass(module = "git_bot_feedback", from_py_object, get_all, set_all)
14)]
15pub struct ReviewOptions {
16    /// The course of action that the PR review suggests.
17    pub action: ReviewAction,
18
19    /// A summary of the PR review.
20    ///
21    /// This is an overview of the review's comments.
22    pub summary: String,
23
24    /// A list of comments for changes to the PR.
25    pub comments: Vec<ReviewComment>,
26
27    /// A string used to mark/identify each comment (and [`Self::summary`]) as a
28    /// comment submitted by this software.
29    ///
30    /// User comments may be indistinguishable from bot/generated comments if
31    /// this value is not unique enough.
32    ///
33    /// If the git server employs Markdown syntax for comments, then
34    /// it is recommended to set this to an HTML comment that is unique to
35    /// your CI application:
36    ///
37    /// ``<!-- my-cool-CI-app-name -->``
38    ///
39    /// The default value for this is an HTML comment generated from
40    /// this crate's name and version along with the compile-tome's datetime.
41    /// For example:
42    ///
43    /// ``<!-- git-bot-feedback/0.1.0/Jul-14-2025_17-00 -->``
44    pub marker: String,
45
46    /// Allow posting reviews on draft Pull Requests?
47    pub allow_draft: bool,
48
49    /// Allow posting reviews on closed Pull Requests?
50    pub allow_closed: bool,
51
52    /// Permanently delete PR review outdated comments instead of hiding them.
53    ///
54    /// Here be dragons!
55    /// Use with extreme caution when asserting this flag.
56    /// Setting this flag as `true` will permanently
57    /// delete PR review comments that may be pivotal to a thread of discussion.
58    ///
59    /// Note, this does not apply to PR review summary comments nor threads of
60    /// discussion within a review.
61    pub delete_review_comments: bool,
62}
63
64impl Default for ReviewOptions {
65    fn default() -> Self {
66        Self {
67            action: ReviewAction::default(),
68            summary: Default::default(),
69            comments: Default::default(),
70            marker: DEFAULT_MARKER.to_string(),
71            allow_draft: false,
72            allow_closed: false,
73            delete_review_comments: false,
74        }
75    }
76}
77
78#[cfg(feature = "pyo3")]
79#[pymethods]
80impl ReviewOptions {
81    /// Create a new review options instance.
82    #[new]
83    #[pyo3(
84        signature = (
85            comments,
86            action=None,
87            summary=None,
88            marker=None,
89            allow_draft=None,
90            allow_closed=None,
91            delete_review_comments=None
92        ),
93        text_signature = "(comments: list[ReviewComment], action: ReviewAction | None = None, summary: str | None = None, marker: str | None = None, allow_draft: bool = False, allow_closed: bool = False, delete_review_comments: bool = False)"
94    )]
95    pub fn new(
96        comments: Vec<ReviewComment>,
97        action: Option<ReviewAction>,
98        summary: Option<String>,
99        marker: Option<String>,
100        allow_draft: Option<bool>,
101        allow_closed: Option<bool>,
102        delete_review_comments: Option<bool>,
103    ) -> Self {
104        Self {
105            action: action.unwrap_or_default(),
106            summary: summary.unwrap_or_default(),
107            comments,
108            marker: marker.unwrap_or_else(|| DEFAULT_MARKER.to_string()),
109            allow_draft: allow_draft.unwrap_or(false),
110            allow_closed: allow_closed.unwrap_or(false),
111            delete_review_comments: delete_review_comments.unwrap_or(false),
112        }
113    }
114}
115
116/// An enumeration of possible recommended actions for a Pull Request review.
117#[derive(Debug, PartialEq, Eq, Clone, Default)]
118#[cfg_attr(feature = "pyo3", pyclass(module = "git_bot_feedback", from_py_object))]
119pub enum ReviewAction {
120    /// Approve the current Pull Request's changes.
121    Approve,
122
123    /// Request changes to the current Pull Request's proposal.
124    RequestChanges,
125
126    /// Comment on the current Pull Request's changes without explicitly approving or requesting changes.
127    #[default]
128    Comment,
129}
130
131/// A struct to describe a single comment in a Pull Request review.
132#[derive(Debug, PartialEq, Eq, Clone, Hash)]
133#[cfg_attr(
134    feature = "pyo3",
135    pyclass(module = "git_bot_feedback", from_py_object, get_all, set_all)
136)]
137pub struct ReviewComment {
138    /// The file's line number in the diff that begins the the focus of the comment's concerns.
139    pub line_start: Option<u32>,
140
141    /// The file's line number in the diff that ends the focus of the comment's concerns.
142    pub line_end: u32,
143
144    /// The actual comment.
145    ///
146    /// This text can include a code block that demonstrates a suggested change(s).
147    ///
148    /// Typically, the comment should not begin with the [`ReviewOptions::marker`] value.
149    /// That is managed by the git-bot-feedback library.
150    pub comment: String,
151
152    /// The file that this comment pertains to.
153    pub path: String,
154}
155
156#[cfg(feature = "pyo3")]
157#[pymethods]
158impl ReviewComment {
159    /// Create a new review comment instance.
160    #[new]
161    #[pyo3(
162        signature = (path, comment, line_end, line_start=None),
163        text_signature = "(path: str, comment: str, line_end: int, line_start: int | None = None)"
164    )]
165    pub fn new_py(path: String, comment: String, line_end: u32, line_start: Option<u32>) -> Self {
166        Self {
167            line_start,
168            line_end,
169            comment,
170            path,
171        }
172    }
173}