jinxapi_github/v1_1_4/request/
checks_create.rs

1//! Create a check run
2//! 
3//! **Note:** The Checks API only looks for pushes in the repository where the check suite or check run were created. Pushes to a branch in a forked repository are not detected and return an empty `pull_requests` array.
4//! 
5//! Creates a new check run for a specific commit in a repository. Your GitHub App must have the `checks:write` permission to create check runs.
6//! 
7//! In a check suite, GitHub limits the number of check runs with the same name to 1000. Once these check runs exceed 1000, GitHub will start to automatically delete older check runs.
8//! 
9//! [API method documentation](https://docs.github.com/rest/reference/checks#create-a-check-run)
10
11pub struct Content<Body>
12{
13    body: Body,
14    content_type_value: Option<::std::borrow::Cow<'static, [u8]>>,
15}
16
17impl<Body> Content<Body> {
18    pub fn new(body: Body) -> Self {
19        Self { body, content_type_value: None }
20    }
21
22    #[must_use]
23    pub fn with_content_type(mut self, content_type: impl Into<::std::borrow::Cow<'static, [u8]>>) -> Self {
24        self.content_type_value = Some(content_type.into());
25        self
26    }
27
28    fn content_type(&self) -> Option<&[u8]> {
29        self.content_type_value.as_deref()
30    }
31
32    fn into_body(self) -> Body {
33        self.body
34    }
35}
36
37fn url_string(
38    base_url: &str,
39    p_owner: &str,
40    p_repo: &str,
41) -> Result<String, crate::v1_1_4::ApiError> {
42    let trimmed = if base_url.is_empty() {
43        "https://api.github.com"
44    } else {
45        base_url.trim_end_matches('/')
46    };
47    let mut url = String::with_capacity(trimmed.len() + 37);
48    url.push_str(trimmed);
49    url.push_str("/repos/");
50    ::querylizer::Simple::extend(&mut url, &p_owner, false, &::querylizer::encode_path)?;
51    url.push('/');
52    ::querylizer::Simple::extend(&mut url, &p_repo, false, &::querylizer::encode_path)?;
53    url.push_str("/check-runs");
54    Ok(url)
55}
56
57#[cfg(feature = "hyper")]
58pub fn http_builder(
59    base_url: &str,
60    p_owner: &str,
61    p_repo: &str,
62    h_user_agent: &str,
63    h_accept: ::std::option::Option<&str>,
64) -> Result<::http::request::Builder, crate::v1_1_4::ApiError> {
65    let url = url_string(
66        base_url,
67        p_owner,
68        p_repo,
69    )?;
70    let mut builder = ::http::request::Request::post(url);
71    builder = builder.header(
72        "User-Agent",
73        &::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?
74    );
75    if let Some(value) = &h_accept {
76        builder = builder.header(
77            "Accept",
78            &::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?
79        );
80    }
81    Ok(builder)
82}
83
84#[cfg(feature = "hyper")]
85pub fn hyper_request(
86    mut builder: ::http::request::Builder,
87    content: Content<::hyper::Body>,
88) -> Result<::http::request::Request<::hyper::Body>, crate::v1_1_4::ApiError>
89{
90    if let Some(content_type) = content.content_type() {
91        builder = builder.header(::http::header::CONTENT_TYPE, content_type);
92    }
93    Ok(builder.body(content.into_body())?)
94}
95
96#[cfg(feature = "hyper")]
97impl From<::hyper::Body> for Content<::hyper::Body> {
98    fn from(body: ::hyper::Body) -> Self {
99        Self::new(body)
100    }
101}
102
103#[cfg(feature = "reqwest")]
104pub fn reqwest_builder(
105    base_url: &str,
106    p_owner: &str,
107    p_repo: &str,
108    h_user_agent: &str,
109    h_accept: ::std::option::Option<&str>,
110) -> Result<::reqwest::Request, crate::v1_1_4::ApiError> {
111    let url = url_string(
112        base_url,
113        p_owner,
114        p_repo,
115    )?;
116    let reqwest_url = ::reqwest::Url::parse(&url)?;
117    let mut request = ::reqwest::Request::new(::reqwest::Method::POST, reqwest_url);
118    let headers = request.headers_mut();
119    headers.append(
120        "User-Agent",
121        ::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?.try_into()?
122    );
123    if let Some(value) = &h_accept {
124        headers.append(
125            "Accept",
126            ::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?.try_into()?
127        );
128    }
129    Ok(request)
130}
131
132#[cfg(feature = "reqwest")]
133pub fn reqwest_request(
134    mut builder: ::reqwest::Request,
135    content: Content<::reqwest::Body>,
136) -> Result<::reqwest::Request, crate::v1_1_4::ApiError> {
137    if let Some(content_type) = content.content_type() {
138        builder.headers_mut().append(
139            ::reqwest::header::HeaderName::from_static("content-type"),
140            ::reqwest::header::HeaderValue::try_from(content_type)?,
141        );
142    }
143    *builder.body_mut() = Some(content.into_body());
144    Ok(builder)
145}
146
147#[cfg(feature = "reqwest")]
148impl From<::reqwest::Body> for Content<::reqwest::Body> {
149    fn from(body: ::reqwest::Body) -> Self {
150        Self::new(body)
151    }
152}
153
154#[cfg(feature = "reqwest-blocking")]
155pub fn reqwest_blocking_builder(
156    base_url: &str,
157    p_owner: &str,
158    p_repo: &str,
159    h_user_agent: &str,
160    h_accept: ::std::option::Option<&str>,
161) -> Result<::reqwest::blocking::Request, crate::v1_1_4::ApiError> {
162    let url = url_string(
163        base_url,
164        p_owner,
165        p_repo,
166    )?;
167    let reqwest_url = ::reqwest::Url::parse(&url)?;
168    let mut request = ::reqwest::blocking::Request::new(::reqwest::Method::POST, reqwest_url);
169    let headers = request.headers_mut();
170    headers.append(
171        "User-Agent",
172        ::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?.try_into()?
173    );
174    if let Some(value) = &h_accept {
175        headers.append(
176            "Accept",
177            ::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?.try_into()?
178        );
179    }
180    Ok(request)
181}
182
183#[cfg(feature = "reqwest-blocking")]
184pub fn reqwest_blocking_request(
185    mut builder: ::reqwest::blocking::Request,
186    content: Content<::reqwest::blocking::Body>,
187) -> Result<::reqwest::blocking::Request, crate::v1_1_4::ApiError> {
188    if let Some(content_type) = content.content_type() {
189        builder.headers_mut().append(
190            ::reqwest::header::HeaderName::from_static("content-type"),
191            ::reqwest::header::HeaderValue::try_from(content_type)?,
192        );
193    }
194    *builder.body_mut() = Some(content.into_body());
195    Ok(builder)
196}
197
198#[cfg(feature = "reqwest-blocking")]
199impl From<::reqwest::blocking::Body> for Content<::reqwest::blocking::Body> {
200    fn from(body: ::reqwest::blocking::Body) -> Self {
201        Self::new(body)
202    }
203}
204
205/// Types for body parameter in [`super::checks_create`]
206pub mod body {
207    #[allow(non_snake_case)]
208    #[derive(Clone, Eq, PartialEq, Debug, Default, ::serde::Serialize, ::serde::Deserialize)]
209    pub struct Json<'a> {
210        /// The name of the check. For example, "code-coverage".
211        pub name: ::std::borrow::Cow<'a, str>,
212
213        /// The SHA of the commit.
214        pub head_sha: ::std::borrow::Cow<'a, str>,
215
216        /// The URL of the integrator's site that has the full details of the check. If the integrator does not provide this, then the homepage of the GitHub app is used.
217        #[serde(skip_serializing_if = "Option::is_none", default)]
218        pub details_url: ::std::option::Option<::std::borrow::Cow<'a, str>>,
219
220        /// A reference for the run on the integrator's system.
221        #[serde(skip_serializing_if = "Option::is_none", default)]
222        pub external_id: ::std::option::Option<::std::borrow::Cow<'a, str>>,
223
224        /// The current status. Can be one of `queued`, `in_progress`, or `completed`.
225        #[serde(skip_serializing_if = "Option::is_none", default)]
226        pub status: ::std::option::Option<::std::borrow::Cow<'a, str>>,
227
228        /// The time that the check run began. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.
229        #[serde(skip_serializing_if = "Option::is_none", default)]
230        pub started_at: ::std::option::Option<::std::borrow::Cow<'a, str>>,
231
232        /// **Required if you provide `completed_at` or a `status` of `completed`**. The final conclusion of the check. Can be one of `action_required`, `cancelled`, `failure`, `neutral`, `success`, `skipped`, `stale`, or `timed_out`. When the conclusion is `action_required`, additional details should be provided on the site specified by `details_url`.  
233        /// **Note:** Providing `conclusion` will automatically set the `status` parameter to `completed`. You cannot change a check run conclusion to `stale`, only GitHub can set this.
234        #[serde(skip_serializing_if = "Option::is_none", default)]
235        pub conclusion: ::std::option::Option<::std::borrow::Cow<'a, str>>,
236
237        /// The time the check completed. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.
238        #[serde(skip_serializing_if = "Option::is_none", default)]
239        pub completed_at: ::std::option::Option<::std::borrow::Cow<'a, str>>,
240
241        #[serde(skip_serializing_if = "Option::is_none", default)]
242        pub output: ::std::option::Option<crate::v1_1_4::request::checks_create::body::json::Output<'a>>,
243
244        /// Displays a button on GitHub that can be clicked to alert your app to do additional tasks. For example, a code linting app can display a button that automatically fixes detected errors. The button created in this object is displayed after the check run completes. When a user clicks the button, GitHub sends the [`check_run.requested_action` webhook](https://docs.github.com/webhooks/event-payloads/#check_run) to your app. Each action includes a `label`, `identifier` and `description`. A maximum of three actions are accepted. See the [`actions` object](https://docs.github.com/rest/reference/checks#actions-object) description. To learn more about check runs and requested actions, see "[Check runs and requested actions](https://docs.github.com/rest/reference/checks#check-runs-and-requested-actions)."
245        #[serde(skip_serializing_if = "Option::is_none", default)]
246        pub actions: ::std::option::Option<::std::borrow::Cow<'a, [crate::v1_1_4::request::checks_create::body::json::Actions<'a>]>>,
247
248        #[serde(flatten)]
249        pub additionalProperties: ::std::collections::HashMap<::std::borrow::Cow<'a, str>, ::serde_json::value::Value>
250    }
251
252    /// Types for fields in [`Json`]
253    pub mod json {
254        /// Check runs can accept a variety of data in the `output` object, including a `title` and `summary` and can optionally provide descriptive details about the run. See the [`output` object](https://docs.github.com/rest/reference/checks#output-object) description.
255        #[allow(non_snake_case)]
256        #[derive(Clone, Eq, PartialEq, Debug, Default, ::serde::Serialize, ::serde::Deserialize)]
257        pub struct Output<'a> {
258            /// The title of the check run.
259            pub title: ::std::borrow::Cow<'a, str>,
260
261            /// The summary of the check run. This parameter supports Markdown.
262            pub summary: ::std::borrow::Cow<'a, str>,
263
264            /// The details of the check run. This parameter supports Markdown.
265            #[serde(skip_serializing_if = "Option::is_none", default)]
266            pub text: ::std::option::Option<::std::borrow::Cow<'a, str>>,
267
268            /// Adds information from your analysis to specific lines of code. Annotations are visible on GitHub in the **Checks** and **Files changed** tab of the pull request. The Checks API limits the number of annotations to a maximum of 50 per API request. To create more than 50 annotations, you have to make multiple requests to the [Update a check run](https://docs.github.com/rest/reference/checks#update-a-check-run) endpoint. Each time you update the check run, annotations are appended to the list of annotations that already exist for the check run. For details about how you can view annotations on GitHub, see "[About status checks](https://docs.github.com/articles/about-status-checks#checks)". See the [`annotations` object](https://docs.github.com/rest/reference/checks#annotations-object) description for details about how to use this parameter.
269            #[serde(skip_serializing_if = "Option::is_none", default)]
270            pub annotations: ::std::option::Option<::std::borrow::Cow<'a, [crate::v1_1_4::request::checks_create::body::json::output::Annotations<'a>]>>,
271
272            /// Adds images to the output displayed in the GitHub pull request UI. See the [`images` object](https://docs.github.com/rest/reference/checks#images-object) description for details.
273            #[serde(skip_serializing_if = "Option::is_none", default)]
274            pub images: ::std::option::Option<::std::borrow::Cow<'a, [crate::v1_1_4::request::checks_create::body::json::output::Images<'a>]>>,
275
276            #[serde(flatten)]
277            pub additionalProperties: ::std::collections::HashMap<::std::borrow::Cow<'a, str>, ::serde_json::value::Value>
278        }
279
280        /// Types for fields in [`Output`]
281        pub mod output {
282            #[allow(non_snake_case)]
283            #[derive(Clone, Eq, PartialEq, Debug, Default, ::serde::Serialize, ::serde::Deserialize)]
284            pub struct Annotations<'a> {
285                /// The path of the file to add an annotation to. For example, `assets/css/main.css`.
286                pub path: ::std::borrow::Cow<'a, str>,
287
288                /// The start line of the annotation.
289                pub start_line: i64,
290
291                /// The end line of the annotation.
292                pub end_line: i64,
293
294                /// The start column of the annotation. Annotations only support `start_column` and `end_column` on the same line. Omit this parameter if `start_line` and `end_line` have different values.
295                #[serde(skip_serializing_if = "Option::is_none", default)]
296                pub start_column: ::std::option::Option<i64>,
297
298                /// The end column of the annotation. Annotations only support `start_column` and `end_column` on the same line. Omit this parameter if `start_line` and `end_line` have different values.
299                #[serde(skip_serializing_if = "Option::is_none", default)]
300                pub end_column: ::std::option::Option<i64>,
301
302                /// The level of the annotation. Can be one of `notice`, `warning`, or `failure`.
303                pub annotation_level: ::std::borrow::Cow<'a, str>,
304
305                /// A short description of the feedback for these lines of code. The maximum size is 64 KB.
306                pub message: ::std::borrow::Cow<'a, str>,
307
308                /// The title that represents the annotation. The maximum size is 255 characters.
309                #[serde(skip_serializing_if = "Option::is_none", default)]
310                pub title: ::std::option::Option<::std::borrow::Cow<'a, str>>,
311
312                /// Details about this annotation. The maximum size is 64 KB.
313                #[serde(skip_serializing_if = "Option::is_none", default)]
314                pub raw_details: ::std::option::Option<::std::borrow::Cow<'a, str>>,
315
316                #[serde(flatten)]
317                pub additionalProperties: ::std::collections::HashMap<::std::borrow::Cow<'a, str>, ::serde_json::value::Value>
318            }
319
320            #[allow(non_snake_case)]
321            #[derive(Clone, Eq, PartialEq, Debug, Default, ::serde::Serialize, ::serde::Deserialize)]
322            pub struct Images<'a> {
323                /// The alternative text for the image.
324                pub alt: ::std::borrow::Cow<'a, str>,
325
326                /// The full URL of the image.
327                pub image_url: ::std::borrow::Cow<'a, str>,
328
329                /// A short image description.
330                #[serde(skip_serializing_if = "Option::is_none", default)]
331                pub caption: ::std::option::Option<::std::borrow::Cow<'a, str>>,
332
333                #[serde(flatten)]
334                pub additionalProperties: ::std::collections::HashMap<::std::borrow::Cow<'a, str>, ::serde_json::value::Value>
335            }
336        }
337
338        #[allow(non_snake_case)]
339        #[derive(Clone, Eq, PartialEq, Debug, Default, ::serde::Serialize, ::serde::Deserialize)]
340        pub struct Actions<'a> {
341            /// The text to be displayed on a button in the web UI. The maximum size is 20 characters.
342            pub label: ::std::borrow::Cow<'a, str>,
343
344            /// A short explanation of what this action would do. The maximum size is 40 characters.
345            pub description: ::std::borrow::Cow<'a, str>,
346
347            /// A reference for the action on the integrator's system. The maximum size is 20 characters.
348            pub identifier: ::std::borrow::Cow<'a, str>,
349
350            #[serde(flatten)]
351            pub additionalProperties: ::std::collections::HashMap<::std::borrow::Cow<'a, str>, ::serde_json::value::Value>
352        }
353    }
354
355    #[cfg(feature = "hyper")]
356    impl<'a> TryFrom<&Json<'a>> for super::Content<::hyper::Body> {
357        type Error = crate::v1_1_4::ApiError;
358
359        fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
360            Ok(
361                Self::new(::serde_json::to_vec(value)?.into())
362                .with_content_type(&b"application/json"[..])
363            )
364        }
365    }
366
367    #[cfg(feature = "reqwest")]
368    impl<'a> TryFrom<&Json<'a>> for super::Content<::reqwest::Body> {
369        type Error = crate::v1_1_4::ApiError;
370
371        fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
372            Ok(
373                Self::new(::serde_json::to_vec(value)?.into())
374                .with_content_type(&b"application/json"[..])
375            )
376        }
377    }
378
379    #[cfg(feature = "reqwest-blocking")]
380    impl<'a> TryFrom<&Json<'a>> for super::Content<::reqwest::blocking::Body> {
381        type Error = crate::v1_1_4::ApiError;
382
383        fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
384            Ok(
385                Self::new(::serde_json::to_vec(value)?.into())
386                .with_content_type(&b"application/json"[..])
387            )
388        }
389    }
390}