github_actions_models/workflow/
event.rs1use indexmap::IndexMap;
4use serde::{Deserialize, Serialize};
5
6use crate::common::EnvValue;
7
8#[derive(Deserialize, PartialEq, Eq, Hash)]
17#[serde(rename_all = "snake_case")]
18pub enum BareEvent {
19 BranchProtectionRule,
20 CheckRun,
21 CheckSuite,
22 Create,
23 Delete,
24 Deployment,
25 DeploymentStatus,
26 Discussion,
27 DiscussionComment,
28 Fork,
29 Gollum,
30 IssueComment,
31 Issues,
32 Label,
33 MergeGroup,
34 Milestone,
35 PageBuild,
36 Project,
37 ProjectCard,
38 ProjectColumn,
39 Public,
40 PullRequest,
41 PullRequestComment,
42 PullRequestReview,
43 PullRequestReviewComment,
44 PullRequestTarget,
45 Push,
46 RegistryPackage,
47 Release,
48 RepositoryDispatch,
49 Status,
51 Watch,
52 WorkflowCall,
53 WorkflowDispatch,
54 WorkflowRun,
55}
56
57#[derive(Default, Deserialize, Serialize)]
61#[serde(default, rename_all = "snake_case")]
62pub struct Events {
63 pub branch_protection_rule: OptionalBody<GenericEvent>,
64 pub check_run: OptionalBody<GenericEvent>,
65 pub check_suite: OptionalBody<GenericEvent>,
66 pub discussion: OptionalBody<GenericEvent>,
69 pub discussion_comment: OptionalBody<GenericEvent>,
70 pub issue_comment: OptionalBody<GenericEvent>,
72 pub issues: OptionalBody<GenericEvent>,
73 pub label: OptionalBody<GenericEvent>,
74 pub merge_group: OptionalBody<GenericEvent>,
75 pub milestone: OptionalBody<GenericEvent>,
76 pub project: OptionalBody<GenericEvent>,
78 pub project_card: OptionalBody<GenericEvent>,
79 pub project_column: OptionalBody<GenericEvent>,
80 pub pull_request: OptionalBody<PullRequest>,
82 pub pull_request_comment: OptionalBody<GenericEvent>,
83 pub pull_request_review: OptionalBody<GenericEvent>,
84 pub pull_request_review_comment: OptionalBody<GenericEvent>,
85 pub pull_request_target: OptionalBody<PullRequest>,
87 pub push: OptionalBody<Push>,
88 pub registry_package: OptionalBody<GenericEvent>,
89 pub release: OptionalBody<GenericEvent>,
90 pub repository_dispatch: OptionalBody<GenericEvent>,
91 pub schedule: OptionalBody<Vec<Cron>>,
92 pub watch: OptionalBody<GenericEvent>,
94 pub workflow_call: OptionalBody<WorkflowCall>,
95 pub workflow_dispatch: OptionalBody<WorkflowDispatch>,
97 pub workflow_run: OptionalBody<WorkflowRun>,
98}
99
100impl Events {
101 pub fn count(&self) -> u32 {
105 let mut count = 0;
108
109 macro_rules! count_if_present {
110 ($($field:ident),*) => {
111 $(
112 if !matches!(self.$field, OptionalBody::Missing) {
113 count += 1;
114 }
115 )*
116 };
117 }
118
119 count_if_present!(
120 branch_protection_rule,
121 check_run,
122 check_suite,
123 discussion,
124 discussion_comment,
125 issue_comment,
126 issues,
127 label,
128 merge_group,
129 milestone,
130 project,
131 project_card,
132 project_column,
133 pull_request,
134 pull_request_comment,
135 pull_request_review,
136 pull_request_review_comment,
137 pull_request_target,
138 push,
139 registry_package,
140 release,
141 repository_dispatch,
142 schedule,
143 watch,
144 workflow_call,
145 workflow_dispatch,
146 workflow_run
147 );
148
149 count
150 }
151}
152
153#[derive(Default, Serialize)]
161pub enum OptionalBody<T> {
162 Default,
163 #[default]
164 Missing,
165 Body(T),
166}
167
168impl<'de, T> Deserialize<'de> for OptionalBody<T>
169where
170 T: Deserialize<'de>,
171{
172 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
173 where
174 D: serde::Deserializer<'de>,
175 {
176 Option::deserialize(deserializer).map(Into::into)
177 }
178}
179
180impl<T> From<Option<T>> for OptionalBody<T> {
181 fn from(value: Option<T>) -> Self {
182 match value {
183 Some(v) => OptionalBody::Body(v),
184 None => OptionalBody::Default,
185 }
186 }
187}
188
189#[derive(Deserialize, Serialize)]
191#[serde(rename_all = "kebab-case")]
192pub struct GenericEvent {
193 #[serde(default, deserialize_with = "crate::common::scalar_or_vector")]
194 pub types: Vec<String>,
195}
196
197#[derive(Deserialize, Serialize)]
199#[serde(rename_all = "kebab-case")]
200pub struct PullRequest {
201 #[serde(default)]
202 pub types: Vec<String>,
203
204 #[serde(flatten)]
205 pub branch_filters: Option<BranchFilters>,
206
207 #[serde(flatten)]
208 pub path_filters: Option<PathFilters>,
209}
210
211#[derive(Deserialize, Serialize)]
213#[serde(rename_all = "kebab-case")]
214pub struct Push {
215 #[serde(flatten)]
216 pub branch_filters: Option<BranchFilters>,
217
218 #[serde(flatten)]
219 pub path_filters: Option<PathFilters>,
220
221 #[serde(flatten)]
222 pub tag_filters: Option<TagFilters>,
223}
224
225#[derive(Deserialize, Serialize)]
227#[serde(rename_all = "kebab-case")]
228pub struct Cron {
229 pub cron: String,
230}
231
232#[derive(Deserialize, Serialize)]
234#[serde(rename_all = "kebab-case")]
235pub struct WorkflowCall {
236 #[serde(default)]
237 pub inputs: IndexMap<String, WorkflowCallInput>,
238 #[serde(default)]
239 pub outputs: IndexMap<String, WorkflowCallOutput>,
240 #[serde(default)]
241 pub secrets: IndexMap<String, Option<WorkflowCallSecret>>,
242}
243
244#[derive(Deserialize, Serialize)]
246#[serde(rename_all = "kebab-case")]
247pub struct WorkflowCallInput {
248 pub description: Option<String>,
249 #[serde(default)]
251 pub required: bool,
252 pub r#type: String,
253}
254
255#[derive(Deserialize, Serialize)]
257#[serde(rename_all = "kebab-case")]
258pub struct WorkflowCallOutput {
259 pub description: Option<String>,
260 pub value: String,
261}
262
263#[derive(Deserialize, Serialize)]
265#[serde(rename_all = "kebab-case")]
266pub struct WorkflowCallSecret {
267 pub description: Option<String>,
268 pub required: bool,
269}
270
271#[derive(Deserialize, Serialize)]
273#[serde(rename_all = "kebab-case")]
274pub struct WorkflowDispatch {
275 #[serde(default)]
276 pub inputs: IndexMap<String, WorkflowDispatchInput>, }
278
279#[derive(Deserialize, Serialize)]
281#[serde(rename_all = "kebab-case")]
282pub struct WorkflowDispatchInput {
283 pub description: Option<String>,
284 #[serde(default)]
286 pub required: bool,
287 pub r#type: Option<String>,
289 #[serde(default)]
291 pub options: Vec<EnvValue>,
292}
293
294#[derive(Deserialize, Serialize)]
296#[serde(rename_all = "kebab-case")]
297pub struct WorkflowRun {
298 pub workflows: Vec<String>,
299 #[serde(default)]
300 pub types: Vec<String>,
301 #[serde(flatten)]
302 pub branch_filters: Option<BranchFilters>,
303}
304
305#[derive(Deserialize, Serialize)]
307#[serde(rename_all = "kebab-case")]
308pub enum BranchFilters {
309 Branches(Vec<String>),
310 BranchesIgnore(Vec<String>),
311}
312
313#[derive(Deserialize, Serialize)]
315#[serde(rename_all = "kebab-case")]
316pub enum TagFilters {
317 Tags(Vec<String>),
318 TagsIgnore(Vec<String>),
319}
320
321#[derive(Deserialize, Serialize)]
323#[serde(rename_all = "kebab-case")]
324pub enum PathFilters {
325 Paths(Vec<String>),
326 PathsIgnore(Vec<String>),
327}
328
329#[cfg(test)]
330mod tests {
331 #[test]
332 fn test_events_count() {
333 let events = "
334push:
335pull_request:
336workflow_dispatch:
337issue_comment:";
338
339 let events = serde_yaml::from_str::<super::Events>(events).unwrap();
340 assert_eq!(events.count(), 4);
341 }
342}