pr_01m47d24b0e6n91zwymwxg0vpx/services/work/src/rows.rs

229 lines6,541 bytesCodeBlame
1//! Rows as they come out of D1, and their conversion to contract types.
2
3use g1t_contracts::User;
4use g1t_contracts::repos::RepoPath;
5use g1t_contracts::work::{
6 CheckStatus, Comment, CommentKind, Issue, IssueReason, Pull, PullStatus, Runtime, SessionEntry,
7 SessionEntryKind, State, Verdict,
8};
9use serde::Deserialize;
10
11pub(crate) fn user(id: String, username: String) -> User {
12 User {
13 id,
14 username,
15 ..User::default()
16 }
17}
18
19#[derive(Deserialize)]
20pub struct IssueRow {
21 pub id: String,
22 pub repo_id: String,
23 pub number: u32,
24 pub title: String,
25 pub body: String,
26 /// JSON array of label names.
27 pub labels: String,
28 /// JSON array of commands.
29 pub checks: String,
30 pub state: State,
31 pub reason: Option<IssueReason>,
32 pub resolved_by: Option<u32>,
33 pub author_id: String,
34 pub author_name: String,
35 pub created_at: String,
36 pub updated_at: String,
37 pub closed_at: Option<String>,
38 pub pull_count: u32,
39 pub comment_count: u32,
40 /// JSON array of usernames.
41 pub assignees: String,
42 /// JSON array of issue numbers.
43 pub blocked_by: String,
44 /// JSON of who queued it for a g1t agent, if anyone has.
45 pub queued_by: Option<String>,
46 pub agent: Option<String>,
47}
48
49impl From<IssueRow> for Issue {
50 fn from(row: IssueRow) -> Self {
51 Issue {
52 id: row.id,
53 repo_id: row.repo_id,
54 number: row.number,
55 title: row.title,
56 body: row.body,
57 labels: serde_json::from_str(&row.labels).unwrap_or_default(),
58 checks: serde_json::from_str(&row.checks).unwrap_or_default(),
59 state: row.state,
60 reason: row.reason,
61 resolved_by: row.resolved_by,
62 author: user(row.author_id, row.author_name),
63 created_at: row.created_at,
64 updated_at: row.updated_at,
65 closed_at: row.closed_at,
66 pull_count: row.pull_count,
67 comment_count: row.comment_count,
68 assignees: serde_json::from_str(&row.assignees).unwrap_or_default(),
69 blocked_by: serde_json::from_str(&row.blocked_by).unwrap_or_default(),
70 queued: row.queued_by.is_some(),
71 agent: row.agent,
72 }
73 }
74}
75
76/// The remembered assessment of a pull request, read beside its row.
77#[derive(Deserialize)]
78pub struct Snapshot {
79 pub stage: Option<g1t_contracts::work::Stage>,
80 pub stage_detail: Option<String>,
81 #[serde(default)]
82 pub revisions: u32,
83 /// Whether g1t is seeing it through at all.
84 #[serde(default)]
85 pub managed: u32,
86}
87
88#[derive(Deserialize)]
89pub struct PullRow {
90 pub id: String,
91 pub repo_id: String,
92 pub number: u32,
93 pub issue_number: Option<u32>,
94 pub title: String,
95 pub body: Option<String>,
96 pub agent: String,
97 pub runtime: Runtime,
98 pub status: PullStatus,
99 pub fork_repo_id: Option<String>,
100 pub fork_namespace: Option<String>,
101 pub fork_name: Option<String>,
102 pub source_branch: Option<String>,
103 pub head_commit: Option<String>,
104 pub merge_base: Option<String>,
105 pub merged_by: Option<String>,
106 pub merged_at: Option<String>,
107 pub superseded_by: Option<u32>,
108 pub check_status: Option<CheckStatus>,
109 /// JSON array of changed files; `None` until first worked out.
110 pub files: Option<String>,
111 /// JSON arrays of usernames.
112 pub assignees: String,
113 pub reviewers: String,
114 pub author_id: String,
115 pub author_name: String,
116 pub created_at: String,
117 pub updated_at: String,
118}
119
120impl From<PullRow> for Pull {
121 fn from(row: PullRow) -> Self {
122 Pull {
123 id: row.id,
124 repo_id: row.repo_id,
125 number: row.number,
126 issue: row.issue_number,
127 title: row.title,
128 body: row.body,
129 agent: row.agent,
130 runtime: row.runtime,
131 status: row.status,
132 fork: row
133 .fork_namespace
134 .zip(row.fork_name)
135 .map(|(namespace, name)| RepoPath { namespace, name }),
136 fork_repo_id: row.fork_repo_id,
137 branch: row.source_branch,
138 head_commit: row.head_commit,
139 merge_base: row.merge_base,
140 merged_by: row.merged_by,
141 merged_at: row.merged_at,
142 superseded_by: row.superseded_by,
143 check_status: row.check_status,
144 files: row
145 .files
146 .as_deref()
147 .and_then(|files| serde_json::from_str(files).ok())
148 .unwrap_or_default(),
149 assignees: serde_json::from_str(&row.assignees).unwrap_or_default(),
150 reviewers: serde_json::from_str(&row.reviewers).unwrap_or_default(),
151 author: user(row.author_id, row.author_name),
152 created_at: row.created_at,
153 updated_at: row.updated_at,
154 }
155 }
156}
157
158#[derive(Deserialize)]
159pub struct CommentRow {
160 pub id: String,
161 pub kind: CommentKind,
162 pub author_id: String,
163 pub author_name: String,
164 pub body: String,
165 pub path: Option<String>,
166 pub line: Option<u32>,
167 pub verdict: Option<Verdict>,
168 pub created_at: String,
169}
170
171impl From<CommentRow> for Comment {
172 fn from(row: CommentRow) -> Self {
173 Comment {
174 id: row.id,
175 kind: row.kind,
176 author: user(row.author_id, row.author_name),
177 body: row.body,
178 path: row.path,
179 line: row.line,
180 verdict: row.verdict,
181 created_at: row.created_at,
182 }
183 }
184}
185
186#[derive(Deserialize)]
187pub struct SessionRow {
188 pub seq: u32,
189 pub kind: SessionEntryKind,
190 pub text: String,
191 pub tool: Option<String>,
192 pub commit: Option<String>,
193 pub at: String,
194}
195
196impl From<SessionRow> for SessionEntry {
197 fn from(row: SessionRow) -> Self {
198 SessionEntry {
199 seq: row.seq,
200 kind: row.kind,
201 text: row.text,
202 tool: row.tool,
203 commit: row.commit,
204 at: row.at,
205 }
206 }
207}
208
209/// A pull request whose head a push moved.
210#[derive(Deserialize)]
211pub struct MovedRow {
212 pub id: String,
213 pub repo_id: String,
214 pub number: u32,
215 pub issue_number: Option<u32>,
216 pub status: PullStatus,
217}
218
219/// A single number selected as `n`.
220#[derive(Deserialize)]
221pub struct NumberRow {
222 pub n: u32,
223}
224
225/// A single string selected as `value`.
226#[derive(Deserialize)]
227pub struct ValueRow {
228 pub value: String,
229}