gitlab_butler_lib/
entities.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Deserialize, Debug)]
5pub struct User {
6    pub id: usize,
7    pub username: String,
8}
9
10#[derive(Deserialize, Debug)]
11pub struct Pipeline {
12    pub id: usize,
13    pub sha: String,
14    #[serde(rename = "ref")]
15    pub branch: String,
16    pub status: String,
17    pub updated_at: DateTime<Utc>,
18}
19
20#[derive(Deserialize, Debug)]
21pub struct Emoji {
22    pub id: usize,
23    pub name: String,
24    pub user: User,
25    pub awardable_id: usize,
26    pub awardable_type: String,
27}
28
29/// Merge request message from GitLab
30///
31/// See [api/merge_requests](https://docs.gitlab.com/ee/api/merge_requests.html)
32#[derive(Deserialize, Debug)]
33pub struct MergeRequest {
34    pub title: String,
35    pub description: Option<String>,
36    pub project_id: usize,
37    pub iid: usize, // internal id
38    pub work_in_progress: bool,
39    pub author: User,
40    pub merge_status: String,
41    pub source_branch: String,
42    pub target_branch: String,
43    pub sha: String,
44    pub references: Reference,
45    pub web_url: String,
46    pub main_issue: Option<Issue>,
47}
48
49#[derive(Serialize, Debug, Default)]
50pub struct CreateMergeRequest {
51    #[serde(rename = "id")]
52    pub project_id: String,
53    pub source_branch: String,
54    pub target_branch: String,
55    pub title: String,
56    pub milestone_id: Option<usize>,
57    pub description: Option<String>,
58    pub assignee_ids: Vec<usize>,
59    /// Comma separated
60    pub labels: Option<String>,
61}
62
63#[derive(Deserialize, Debug)]
64pub struct MergeRequestDetails {
65    pub title: String,
66    pub project_id: usize,
67    pub iid: usize, // internal id
68    pub work_in_progress: bool,
69    pub author: User,
70    pub merge_status: String,
71    pub source_branch: String,
72    pub target_branch: String,
73    pub sha: Option<String>,
74    // should be there with `include_rebase_in_progress=true`, but sometime is missing
75    pub rebase_in_progress: Option<bool>,
76    pub merge_error: Option<String>,
77    pub pipeline: Option<Pipeline>,
78    // should be there with `include_diverged_commits_count=true`, but perhaps 0 is not shown?
79    pub diverged_commits_count: Option<i32>,
80}
81
82#[derive(Deserialize, Debug)]
83#[serde(rename_all = "lowercase")]
84pub enum MergeRequestState {
85    Opened,
86    Closed,
87    Merged,
88}
89
90impl MergeRequestState {
91    pub fn name(&self) -> &str {
92        match self {
93            MergeRequestState::Opened => "opened",
94            MergeRequestState::Closed => "closed",
95            MergeRequestState::Merged => "merged",
96        }
97    }
98}
99
100impl std::str::FromStr for MergeRequestState {
101    type Err = String;
102    fn from_str(state: &str) -> Result<Self, Self::Err> {
103        match state {
104            "opened" => Ok(MergeRequestState::Opened),
105            "closed" => Ok(MergeRequestState::Closed),
106            "merged" => Ok(MergeRequestState::Merged),
107            other_state => Err(format!(
108                "Invalid state, {} not in [opened, closed, merged]",
109                other_state
110            )
111            .to_string()),
112        }
113    }
114}
115
116#[derive(Deserialize, Debug)]
117pub struct ProjectMilestone {
118    pub title: String,
119    pub id: usize,
120    pub iid: usize,
121    pub project_id: Option<usize>,
122    pub group_id: Option<usize>,
123    pub description: String,
124    pub due_date: Option<String>,
125    pub start_date: Option<String>,
126    pub state: String,
127}
128
129#[derive(Serialize, Debug)]
130pub struct CreateProjectMilestone {
131    #[serde(rename = "id")]
132    pub project_id: usize,
133    pub title: String,
134    pub description: Option<String>,
135}
136
137#[derive(Deserialize, Debug)]
138pub struct Issue {
139    pub title: String,
140    pub iid: usize, // internal id
141    pub state: IssueState,
142    pub description: Option<String>,
143    pub author: User,
144    pub milestone: Option<ProjectMilestone>,
145    pub project_id: usize,
146    pub assignees: Vec<User>,
147    pub web_url: String,
148    pub weight: Option<usize>,
149    pub labels: Vec<String>,
150    pub references: Reference,
151}
152
153#[derive(Deserialize, Debug)]
154pub struct Reference {
155    pub short: String,
156    pub relative: String,
157    pub full: String,
158}
159
160#[derive(Serialize, Debug, Default)]
161pub struct CreateIssue {
162    #[serde(rename = "id")]
163    pub project_id: String,
164    pub title: String,
165    pub description: Option<String>,
166    pub milestone_id: Option<usize>,
167    pub assignee_ids: Vec<usize>,
168    pub weight: Option<usize>,
169    /// Comma separated
170    pub labels: Option<String>,
171}
172
173#[derive(Deserialize, Debug)]
174#[serde(rename_all = "lowercase")]
175pub enum IssueState {
176    All,
177    Opened,
178    Closed,
179}
180
181impl IssueState {
182    pub fn name(&self) -> &str {
183        match self {
184            IssueState::All => "all",
185            IssueState::Closed => "closed",
186            IssueState::Opened => "opened",
187        }
188    }
189}
190
191impl std::str::FromStr for IssueState {
192    type Err = String;
193    fn from_str(state: &str) -> Result<Self, Self::Err> {
194        match state {
195            "all" => Ok(IssueState::All),
196            "closed" => Ok(IssueState::Closed),
197            "opened" => Ok(IssueState::Opened),
198            other_state => Err(format!(
199                "Invalid state, {} not in [all, opened, closed]",
200                other_state
201            )
202            .to_string()),
203        }
204    }
205}
206
207#[derive(Serialize, Debug)]
208pub struct RebaseBranch {
209    pub id: usize,
210    pub merge_request_iid: usize,
211}
212
213impl<'a> From<&'a MergeRequest> for RebaseBranch {
214    fn from(mr: &'a MergeRequest) -> RebaseBranch {
215        RebaseBranch {
216            id: mr.project_id,
217            merge_request_iid: mr.iid,
218        }
219    }
220}
221
222#[derive(Serialize, Debug)]
223pub struct RemoveSourceBranch {
224    pub id: usize,
225    pub merge_request_iid: usize,
226    pub remove_source_branch: bool,
227}
228
229impl<'a> From<&'a MergeRequest> for RemoveSourceBranch {
230    fn from(mr: &'a MergeRequest) -> RemoveSourceBranch {
231        RemoveSourceBranch {
232            id: mr.project_id,
233            merge_request_iid: mr.iid,
234            remove_source_branch: true,
235        }
236    }
237}
238
239#[derive(Serialize, Debug)]
240pub struct ListPipelines {
241    pub id: usize,
242    pub merge_request_iid: usize,
243}
244
245impl<'a> From<&'a MergeRequest> for ListPipelines {
246    fn from(mr: &'a MergeRequest) -> ListPipelines {
247        ListPipelines {
248            id: mr.project_id,
249            merge_request_iid: mr.iid,
250        }
251    }
252}
253
254#[derive(Serialize, Debug)]
255pub struct AcceptMergeRequest {
256    pub id: usize,
257    pub merge_request_iid: usize,
258    pub merge_when_pipeline_succeeds: bool,
259    pub should_remove_source_branch: bool,
260    pub sha: String,
261}
262
263impl<'a> From<&'a MergeRequest> for AcceptMergeRequest {
264    fn from(mr: &'a MergeRequest) -> AcceptMergeRequest {
265        AcceptMergeRequest {
266            id: mr.project_id,
267            merge_request_iid: mr.iid,
268            merge_when_pipeline_succeeds: true,
269            should_remove_source_branch: true,
270            sha: mr.sha.clone(),
271        }
272    }
273}
274
275#[derive(Serialize, Debug)]
276pub struct GetMergeRequestDetails {
277    pub id: usize,
278    pub merge_request_iid: usize,
279    pub include_diverged_commits_count: bool,
280    pub include_rebase_in_progress: bool,
281}
282
283impl GetMergeRequestDetails {
284    pub fn new(project_id: usize, merge_request_iid: usize) -> Self {
285        GetMergeRequestDetails {
286            id: project_id,
287            merge_request_iid,
288            include_diverged_commits_count: true,
289            include_rebase_in_progress: true,
290        }
291    }
292}
293
294impl<'a> From<&'a MergeRequest> for GetMergeRequestDetails {
295    fn from(mr: &'a MergeRequest) -> GetMergeRequestDetails {
296        GetMergeRequestDetails::new(mr.project_id, mr.iid)
297    }
298}
299
300#[derive(Serialize, Debug)]
301pub struct AwardEmoji {
302    pub id: usize,
303    pub awardable_id: usize,
304}
305
306impl<'a> From<&'a MergeRequest> for AwardEmoji {
307    fn from(mr: &'a MergeRequest) -> AwardEmoji {
308        AwardEmoji {
309            id: mr.project_id,
310            awardable_id: mr.iid,
311        }
312    }
313}
314
315#[derive(Deserialize, Debug)]
316pub struct Project {
317    pub id: usize,
318    pub description: Option<String>,
319    pub ssh_url_to_repo: String,
320    pub http_url_to_repo: String,
321    pub web_url: String,
322    pub name: String,
323    pub name_with_namespace: String,
324    pub path: String,
325    pub path_with_namespace: String,
326    pub avatar_url: Option<String>,
327}