subalfred_core/github/
substrate.rs1use futures::{StreamExt, stream};
5use githuber::api::commits;
6use super::*;
8use crate::prelude::*;
9
10pub enum WatchedLabels {
12 C5High,
14 C7Critical,
16 D2BreaksApi,
18 E0RuntimeMigration,
20 E1DatabaseMigration,
22 E3HostFunctions,
24 E4NodeFirstUpdate,
26 F0BreaksEverything,
28 F1BreaksAuthoring,
30 F2BreaksConsensus,
32 F3BreaksApi,
34}
35impl WatchedLabels {
36 const fn as_str(&self) -> &'static str {
37 use WatchedLabels::*;
39
40 match self {
41 C5High => "C5-high",
42 C7Critical => "C7-critical",
43 D2BreaksApi => "D2-breaksapi",
44 E0RuntimeMigration => "E0-runtime_migration",
45 E1DatabaseMigration => "E1-database_migration",
46 E3HostFunctions => "E3-host_functions",
47 E4NodeFirstUpdate => "E4-node_first_update",
48 F0BreaksEverything => "F0-breaks_everything",
49 F1BreaksAuthoring => "F1-breaks_authoring",
50 F2BreaksConsensus => "F2-breaks_consensus",
51 F3BreaksApi => "F3-breaks_API",
52 }
53 }
54
55 pub fn all() -> Vec<&'static str> {
57 use WatchedLabels::*;
59
60 vec![
61 C5High.as_str(),
62 C7Critical.as_str(),
63 D2BreaksApi.as_str(),
64 E0RuntimeMigration.as_str(),
65 E1DatabaseMigration.as_str(),
66 E3HostFunctions.as_str(),
67 E4NodeFirstUpdate.as_str(),
68 F0BreaksEverything.as_str(),
69 F1BreaksAuthoring.as_str(),
70 F2BreaksConsensus.as_str(),
71 F3BreaksApi.as_str(),
72 ]
73 }
74}
75
76#[derive(Debug, Default)]
78pub struct WatchedPullRequests {
79 c5_high: Vec<PullRequest>,
80 c7_critical: Vec<PullRequest>,
81 d2_breaks_api: Vec<PullRequest>,
82 e0_runtime_migration: Vec<PullRequest>,
83 e1_database_migration: Vec<PullRequest>,
84 e3_host_functions: Vec<PullRequest>,
85 e4_node_first_update: Vec<PullRequest>,
86 f0_breaks_everything: Vec<PullRequest>,
87 f1_breaks_authoring: Vec<PullRequest>,
88 f2_breaks_consensus: Vec<PullRequest>,
89 f3_breaks_api: Vec<PullRequest>,
90}
91impl WatchedPullRequests {
92 fn try_push(&mut self, pull_request: PullRequest) {
93 pull_request.labels.iter().for_each(|l| {
94 for (wl, ps) in WatchedLabels::all().into_iter().zip(self.all_mut()) {
95 if l.name.as_str() == wl {
96 ps.push(pull_request.clone());
97
98 break;
99 }
100 }
101 });
102 }
103
104 fn all_mut(&mut self) -> Vec<&mut Vec<PullRequest>> {
105 vec![
106 &mut self.c5_high,
107 &mut self.c7_critical,
108 &mut self.d2_breaks_api,
109 &mut self.e0_runtime_migration,
110 &mut self.e1_database_migration,
111 &mut self.e3_host_functions,
112 &mut self.e4_node_first_update,
113 &mut self.f0_breaks_everything,
114 &mut self.f1_breaks_authoring,
115 &mut self.f2_breaks_consensus,
116 &mut self.f3_breaks_api,
117 ]
118 }
119
120 pub fn all(self) -> Vec<Vec<PullRequest>> {
122 vec![
123 self.c5_high,
124 self.c7_critical,
125 self.d2_breaks_api,
126 self.e0_runtime_migration,
127 self.e1_database_migration,
128 self.e3_host_functions,
129 self.e4_node_first_update,
130 self.f0_breaks_everything,
131 self.f1_breaks_authoring,
132 self.f2_breaks_consensus,
133 self.f3_breaks_api,
134 ]
135 }
136}
137impl From<Vec<PullRequest>> for WatchedPullRequests {
138 fn from(pull_requests: Vec<PullRequest>) -> Self {
139 let mut w = WatchedPullRequests::default();
140
141 pull_requests.into_iter().for_each(|p| w.try_push(p));
142
143 w
144 }
145}
146
147pub async fn track_updates(owner: &str, repo: &str, basehead: &str) -> Result<Vec<PullRequest>> {
151 let api_client = ApiClient::new()?;
152 let mut request =
153 commits::compare_two_commits(owner, repo, basehead).per_page(ApiClient::PER_PAGE).page(1);
154 let mut commit_shas = Vec::new();
155
156 loop {
157 let response = api_client.request_auto_retry::<_, Commits>(&request).await;
158 let page = request
159 .page
160 .take()
161 .expect("[core::github] `page` has already been set in previous step; qed");
162 let commits_count = response.commits.len() as u8;
163
164 response.commits.into_iter().for_each(|commit| commit_shas.push(commit.sha));
165
166 if commits_count < ApiClient::PER_PAGE {
167 break;
168 }
169
170 request = request.page(page + 1);
171 }
172
173 let mut pull_requests = stream::iter(commit_shas)
174 .enumerate()
175 .map(|(i, commit_sha)| {
176 let api_client = api_client.clone();
177
178 async move {
179 (
180 i,
181 api_client
182 .request_auto_retry::<_, Vec<PullRequest>>(
183 &commits::list_pull_requests_associated_with_a_commit(
184 owner,
185 repo,
186 &commit_sha,
187 ),
188 )
189 .await,
190 )
191 }
192 })
193 .buffer_unordered(64)
195 .collect::<Vec<_>>()
196 .await;
197
198 pull_requests.sort_by_key(|(i, _)| *i);
199
200 Ok(pull_requests.into_iter().flat_map(|(_, pull_request)| pull_request).collect())
201}