1use crate::utils::{get_json, url};
2use crate::Result;
3use reqwest;
4use serde_derive::Deserialize;
5use std::collections::BTreeMap;
6
7#[derive(Debug, Deserialize)]
8pub struct ChecksResponse {
9 pub total_count: u64,
10 pub check_runs: Vec<CheckRun>,
11}
12
13#[derive(Debug, Deserialize)]
14pub struct CheckRun {
15 pub id: u64,
16 pub head_sha: String,
17 pub node_id: String,
18 pub external_id: Option<String>,
19 pub url: String,
20 pub html_url: Option<String>,
21 pub details_url: Option<String>,
22 pub status: RunStatus,
23 pub conclusion: Option<RunConclusion>, pub started_at: Option<String>,
25 pub completed_at: Option<String>,
26 pub output: CheckOutput,
27 pub name: String,
28 pub check_suite: Option<CheckSuite>,
29 pub app: Option<GithubApp>,
30 pub pull_requests: Vec<PullRequestMinimal>,
31}
32
33#[derive(Debug, Deserialize)]
34#[serde(rename_all = "snake_case")]
35pub enum RunStatus {
36 Queued,
37 InProgress,
38 Completed,
39}
40
41#[derive(Debug, Deserialize)]
42#[serde(rename_all = "snake_case")]
43pub enum RunConclusion {
44 Success,
45 Failure,
46 Neutral,
47 Cancelled,
48 Skipped,
49 TimedOut,
50 ActionRequired,
51}
52
53#[derive(Debug, Deserialize)]
54pub struct CheckOutput {
55 pub title: Option<String>,
56 pub summary: Option<String>,
57 pub text: Option<String>,
58 pub annotations_count: u64,
59 pub annotations_url: String,
60}
61
62#[derive(Debug, Deserialize)]
63pub struct CheckSuite {
64 pub id: u64,
65}
66
67#[derive(Debug, Deserialize)]
68pub struct GithubApp {
69 pub id: u64,
70 pub slug: String,
71 pub node_id: String,
72 pub owner: Option<SimpleUser>,
73 pub name: String,
74 pub description: Option<String>,
75 pub external_url: String,
76 pub html_url: String,
77 pub created_at: String,
78 pub updated_at: String,
79 pub permissions: BTreeMap<String, String>,
80 pub events: Vec<String>,
81}
82
83#[derive(Debug, Deserialize)]
84pub struct SimpleUser {
85 pub login: String,
86 pub id: u64,
87 pub node_id: String,
88 pub url: String,
89 pub repos_url: String,
90 pub events_url: String,
91 pub avatar_url: String,
92 pub gravatar_id: Option<String>,
93 pub html_url: String,
94 pub followers_url: String,
95 pub following_url: String,
96 pub gists_url: String,
97 pub starred_url: String,
98 pub subscriptions_url: String,
99 pub organizations_url: String,
100 pub received_events_url: String,
101 #[serde(rename = "type")]
102 pub user_type: String,
103 pub site_admin: bool,
104 pub starred_at: Option<String>,
105}
106
107#[derive(Debug, Deserialize)]
108pub struct Permissions {
109 pub metadata: String, pub contents: String, pub issues: String, pub single_file: String, }
114
115#[derive(Debug, Deserialize)]
116pub struct PullRequestMinimal {
117 pub url: String,
118 pub id: u64,
119 pub number: u64,
120 pub head: Ref,
121}
122
123#[derive(Debug, Deserialize)]
124pub struct Ref {
125 #[serde(rename = "ref")]
126 pub ref_name: String,
127 pub sha: String,
128 pub repo: Repo,
129}
130
131#[derive(Debug, Deserialize)]
132pub struct Repo {
133 pub id: u64,
134 pub url: String,
135 pub name: String,
136}
137
138pub fn get_checks(
139 client: &reqwest::blocking::Client,
140 owner: &str,
141 repo: &str,
142 sha1: &str,
143) -> Result<Vec<CheckRun>> {
144 let url_suffix = format!("repos/{}/{}/commits/{}/check-runs", owner, repo, sha1);
145 let mut page = 0;
146 let mut checks = Vec::new();
147 let mut checks_total: Option<u64> = None;
148 while checks_total.is_none() || checks_total != Some(checks.len() as u64) {
149 page += 1;
150 let base_url = &url("https://api.github.com/", &url_suffix);
151 let mut query = vec![
152 ("per_page".into(), "100".into()),
153 ("filter".into(), "all".into()),
154 ];
155 if page > 1 {
156 query.push(("page".into(), page.to_string()));
157 }
158 let checks_resp: ChecksResponse = get_json(
159 client,
160 base_url,
161 Some(query),
162 Some(vec![
163 ("user-agent".to_string(), "tcfetch/0.4".to_string()),
164 (
165 "Accept".to_string(),
166 "application/vnd.github+json".to_string(),
167 ),
168 ("X-GitHub-Api-Version".to_string(), "2022-11-28".to_string()),
169 ]),
170 )?;
171 checks_total = Some(checks_resp.total_count);
172 checks.extend(checks_resp.check_runs.into_iter())
173 }
174 Ok(checks)
175}