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

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