automatons_github/task/
update_check_run.rs

1use anyhow::Context;
2use chrono::{DateTime, Utc};
3use serde::Serialize;
4use url::Url;
5
6use automatons::Error;
7
8use crate::client::GitHubClient;
9use crate::resource::{
10    CheckRun, CheckRunConclusion, CheckRunId, CheckRunName, CheckRunStatus, Login, RepositoryName,
11};
12use crate::task::CheckRunOutputArgs;
13
14/// Update a check run
15///
16/// Updates a check run for a specific commit in a repository. The GitHub App must have the
17/// `checks:write` permission to edit check runs.
18///
19/// https://docs.github.com/en/rest/checks/runs#update-a-check-run
20#[derive(Copy, Clone, Debug)]
21pub struct UpdateCheckRun<'a> {
22    github_client: &'a GitHubClient,
23    owner: &'a Login,
24    repository: &'a RepositoryName,
25    check_run_args: &'a UpdateCheckRunArgs,
26}
27
28/// Input for update check run task
29///
30/// The input for the task that updates a check run represents the different parameters that
31/// GitHub's API accepts.
32///
33/// https://docs.github.com/en/rest/checks/runs#update-a-check-run
34#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize)]
35pub struct UpdateCheckRunArgs {
36    /// The unique identifier of the check run.
37    pub check_run_id: CheckRunId,
38
39    /// The name of the check. For example, "code-coverage".
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub name: Option<CheckRunName>,
42
43    /// The URL of the integrator's site that has the full details of the check.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub details_url: Option<Url>,
46
47    /// A reference for the run on the integrator's system.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub external_id: Option<String>,
50
51    /// The time that the check run began.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub started_at: Option<DateTime<Utc>>,
54
55    /// The current status.
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub status: Option<CheckRunStatus>,
58
59    /// The final conclusion of the check.
60    ///
61    /// Required if you provide `completed_at` or a status of `completed`. Providing a conclusion
62    /// will automatically set the status parameter to `completed`. You cannot change a check run
63    /// conclusion to `stale`, only GitHub can set this.
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub conclusion: Option<CheckRunConclusion>,
66
67    /// The time the check completed.
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub completed_at: Option<DateTime<Utc>>,
70
71    /// Check runs can accept a variety of data in the output object, including a title and summary
72    /// and can optionally provide descriptive details about the run.
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub output: Option<CheckRunOutputArgs>,
75}
76
77impl<'a> UpdateCheckRun<'a> {
78    /// Initializes the task
79    pub fn new(
80        github_client: &'a GitHubClient,
81        owner: &'a Login,
82        repository: &'a RepositoryName,
83        check_run_input: &'a UpdateCheckRunArgs,
84    ) -> Self {
85        Self {
86            github_client,
87            owner,
88            repository,
89            check_run_args: check_run_input,
90        }
91    }
92
93    /// Update a check run
94    ///
95    /// Updates a check run for a specific commit in a repository.
96    pub async fn execute(&self) -> Result<CheckRun, Error> {
97        let url = format!(
98            "/repos/{}/{}/check-runs/{}",
99            self.owner.get(),
100            self.repository.get(),
101            self.check_run_args.check_run_id
102        );
103
104        let check_run = self
105            .github_client
106            .patch(&url, Some(self.check_run_args))
107            .await
108            .context("failed to update check run")?;
109
110        Ok(check_run)
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use crate::resource::{CheckRunId, CheckRunName, Login, RepositoryName};
117    use crate::testing::check_run::mock_update_check_run;
118    use crate::testing::client::github_client;
119    use crate::testing::token::mock_installation_access_tokens;
120
121    use super::{UpdateCheckRun, UpdateCheckRunArgs};
122
123    fn input() -> UpdateCheckRunArgs {
124        UpdateCheckRunArgs {
125            check_run_id: CheckRunId::new(4),
126            name: Some(CheckRunName::new("mighty_readme")),
127            details_url: None,
128            external_id: None,
129            status: None,
130            started_at: None,
131            conclusion: None,
132            completed_at: None,
133            output: None,
134        }
135    }
136
137    #[tokio::test]
138    async fn task_returns_updated_check_run() {
139        let _token_mock = mock_installation_access_tokens();
140        let _content_mock = mock_update_check_run();
141
142        let github_client = github_client();
143        let login = Login::new("github");
144        let repository = RepositoryName::new("hello-world");
145        let input = input();
146
147        let task = UpdateCheckRun::new(&github_client, &login, &repository, &input);
148
149        let check_run = task.execute().await.unwrap();
150
151        assert_eq!("mighty_readme", check_run.name().get());
152    }
153
154    #[test]
155    fn trait_send() {
156        fn assert_send<T: Send>() {}
157        assert_send::<UpdateCheckRun>();
158    }
159
160    #[test]
161    fn trait_sync() {
162        fn assert_sync<T: Sync>() {}
163        assert_sync::<UpdateCheckRun>();
164    }
165}