flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/services/work/src/rows.rs

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