1use crate::{
2 HookBeforeRunStepResult, HookNoopResult, HookResolveActionResult, JobRunResult, Plugin,
3 RunJobEvent, RunStepEvent, RunWorkflowEvent, Step, StepRunResult, UserActionStep, WorkflowLog,
4 WorkflowRunResult, WorkflowStateEvent,
5};
6
7type OnStateChange = dyn Fn(WorkflowStateEvent) -> HookNoopResult + Send + Sync;
8type OnLog = dyn Fn(WorkflowLog) -> HookNoopResult + Send + Sync;
9type OnRunWorkflow = dyn Fn(RunWorkflowEvent) -> HookNoopResult + Send + Sync;
10type OnRunJob = dyn Fn(RunJobEvent) -> HookNoopResult + Send + Sync;
11type OnRunStep = dyn Fn(RunStepEvent) -> HookNoopResult + Send + Sync;
12type OnWorkflowComplete = dyn Fn(WorkflowRunResult) -> HookNoopResult + Send + Sync;
13type OnJobComplete = dyn Fn(JobRunResult) -> HookNoopResult + Send + Sync;
14type OnStepComplete = dyn Fn(StepRunResult) -> HookNoopResult + Send + Sync;
15type OnResolveDynamicAction = dyn Fn(UserActionStep) -> HookResolveActionResult + Send + Sync;
16type OnBeforeRunStep = dyn Fn(Step) -> HookBeforeRunStepResult + Send + Sync;
17
18pub struct PluginBuilder {
19 name: &'static str,
20 on_resolve_dynamic_action: Option<Box<OnResolveDynamicAction>>,
21 on_run_workflow: Option<Box<OnRunWorkflow>>,
22 on_run_job: Option<Box<OnRunJob>>,
23 on_before_run_step: Option<Box<OnBeforeRunStep>>,
24 on_run_step: Option<Box<OnRunStep>>,
25 on_state_change: Option<Box<OnStateChange>>,
26 on_log: Option<Box<OnLog>>,
27 on_step_completed: Option<Box<OnStepComplete>>,
28 on_job_completed: Option<Box<OnJobComplete>>,
29 on_workflow_completed: Option<Box<OnWorkflowComplete>>,
30}
31
32impl PluginBuilder {
33 fn new(name: &'static str) -> Self {
34 PluginBuilder {
35 name,
36 on_resolve_dynamic_action: None,
37 on_state_change: None,
38 on_log: None,
39 on_run_workflow: None,
40 on_run_job: None,
41 on_before_run_step: None,
42 on_run_step: None,
43 on_step_completed: None,
44 on_job_completed: None,
45 on_workflow_completed: None,
46 }
47 }
48
49 pub fn on_state_change<T>(mut self, on_state_change: T) -> Self
50 where
51 T: Fn(WorkflowStateEvent) -> HookNoopResult + 'static + Send + Sync,
52 {
53 self.on_state_change = Some(Box::new(on_state_change));
54 self
55 }
56
57 pub fn on_log<T>(mut self, on_log: T) -> Self
58 where
59 T: Fn(WorkflowLog) -> HookNoopResult + 'static + Send + Sync,
60 {
61 self.on_log = Some(Box::new(on_log));
62 self
63 }
64
65 pub fn on_run_workflow<T>(mut self, on_run_workflow: T) -> Self
66 where
67 T: Fn(RunWorkflowEvent) -> HookNoopResult + 'static + Send + Sync,
68 {
69 self.on_run_workflow = Some(Box::new(on_run_workflow));
70 self
71 }
72
73 pub fn on_run_job<T>(mut self, on_run_job: T) -> Self
74 where
75 T: Fn(RunJobEvent) -> HookNoopResult + 'static + Send + Sync,
76 {
77 self.on_run_job = Some(Box::new(on_run_job));
78 self
79 }
80
81 pub fn on_run_step<T>(mut self, on_run_step: T) -> Self
82 where
83 T: Fn(RunStepEvent) -> HookNoopResult + 'static + Send + Sync,
84 {
85 self.on_run_step = Some(Box::new(on_run_step));
86 self
87 }
88
89 pub fn on_workflow_completed<T>(mut self, on_workflow_completed: T) -> Self
90 where
91 T: Fn(WorkflowRunResult) -> HookNoopResult + Send + Sync + 'static,
92 {
93 self.on_workflow_completed = Some(Box::new(on_workflow_completed));
94
95 self
96 }
97
98 pub fn on_job_completed<T>(mut self, on_job_completed: T) -> Self
99 where
100 T: Fn(JobRunResult) -> HookNoopResult + Send + Sync + 'static,
101 {
102 self.on_job_completed = Some(Box::new(on_job_completed));
103
104 self
105 }
106
107 pub fn on_step_completed<T>(mut self, on_step_completed: T) -> Self
108 where
109 T: Fn(StepRunResult) -> HookNoopResult + Send + Sync + 'static,
110 {
111 self.on_step_completed = Some(Box::new(on_step_completed));
112
113 self
114 }
115
116 pub fn on_resolve_dynamic_action<T>(mut self, on_resolve_dynamic_action: T) -> Self
117 where
118 T: Fn(UserActionStep) -> HookResolveActionResult + Send + Sync + 'static,
119 {
120 self.on_resolve_dynamic_action = Some(Box::new(on_resolve_dynamic_action));
121
122 self
123 }
124
125 pub fn on_before_run_step<T>(mut self, on_before_run_step: T) -> Self
126 where
127 T: Fn(Step) -> HookBeforeRunStepResult + Send + Sync + 'static,
128 {
129 self.on_before_run_step = Some(Box::new(on_before_run_step));
130
131 self
132 }
133
134 pub fn build(self) -> AstroRunPlugin {
135 AstroRunPlugin {
136 name: self.name,
137 on_state_change: self.on_state_change,
138 on_log: self.on_log,
139 on_run_workflow: self.on_run_workflow,
140 on_run_job: self.on_run_job,
141 on_run_step: self.on_run_step,
142 on_workflow_completed: self.on_workflow_completed,
143 on_job_completed: self.on_job_completed,
144 on_step_completed: self.on_step_completed,
145 on_resolve_dynamic_action: self.on_resolve_dynamic_action,
146 on_before_run_step: self.on_before_run_step,
147 }
148 }
149}
150
151pub struct AstroRunPlugin {
154 name: &'static str,
155 on_resolve_dynamic_action: Option<Box<OnResolveDynamicAction>>,
156 on_run_workflow: Option<Box<OnRunWorkflow>>,
157 on_run_job: Option<Box<OnRunJob>>,
158 on_before_run_step: Option<Box<OnBeforeRunStep>>,
159 on_run_step: Option<Box<OnRunStep>>,
160 on_state_change: Option<Box<OnStateChange>>,
161 on_log: Option<Box<OnLog>>,
162 on_step_completed: Option<Box<OnStepComplete>>,
163 on_job_completed: Option<Box<OnJobComplete>>,
164 on_workflow_completed: Option<Box<OnWorkflowComplete>>,
165}
166
167impl AstroRunPlugin {
168 pub fn builder(name: &'static str) -> PluginBuilder {
169 PluginBuilder::new(name)
170 }
171}
172
173#[async_trait::async_trait]
174impl Plugin for AstroRunPlugin {
175 fn name(&self) -> &'static str {
176 self.name
177 }
178
179 async fn on_state_change(&self, event: WorkflowStateEvent) -> HookNoopResult {
180 if let Some(on_state_change) = &self.on_state_change {
181 on_state_change(event)?;
182 }
183
184 Ok(())
185 }
186
187 async fn on_log(&self, log: WorkflowLog) -> HookNoopResult {
188 if let Some(on_log) = &self.on_log {
189 on_log(log)?;
190 }
191
192 Ok(())
193 }
194
195 async fn on_run_workflow(&self, event: RunWorkflowEvent) -> HookNoopResult {
196 if let Some(on_run_workflow) = &self.on_run_workflow {
197 on_run_workflow(event)?;
198 }
199
200 Ok(())
201 }
202
203 async fn on_run_job(&self, event: RunJobEvent) -> HookNoopResult {
204 if let Some(on_run_job) = &self.on_run_job {
205 on_run_job(event)?;
206 }
207
208 Ok(())
209 }
210
211 async fn on_run_step(&self, event: RunStepEvent) -> HookNoopResult {
212 if let Some(on_run_step) = &self.on_run_step {
213 on_run_step(event)?;
214 }
215
216 Ok(())
217 }
218
219 async fn on_workflow_completed(&self, result: WorkflowRunResult) -> HookNoopResult {
220 if let Some(on_workflow_completed) = &self.on_workflow_completed {
221 on_workflow_completed(result)?;
222 }
223
224 Ok(())
225 }
226
227 async fn on_job_completed(&self, result: JobRunResult) -> HookNoopResult {
228 if let Some(on_job_completed) = &self.on_job_completed {
229 on_job_completed(result)?;
230 }
231
232 Ok(())
233 }
234
235 async fn on_step_completed(&self, result: StepRunResult) -> HookNoopResult {
236 if let Some(on_step_completed) = &self.on_step_completed {
237 on_step_completed(result)?;
238 }
239
240 Ok(())
241 }
242
243 async fn on_before_run_step(&self, step: Step) -> HookBeforeRunStepResult {
244 let mut step = step;
245
246 if let Some(on_before_run_step) = &self.on_before_run_step {
247 match on_before_run_step(step.clone()) {
248 Ok(new_step) => {
249 step = new_step;
250 }
251 Err(err) => return Err(err),
252 }
253 }
254
255 Ok(step)
256 }
257
258 async fn on_resolve_dynamic_action(&self, step: UserActionStep) -> HookResolveActionResult {
259 if let Some(on_resolve_dynamic_action) = &self.on_resolve_dynamic_action {
260 return on_resolve_dynamic_action(step);
261 }
262
263 Ok(None)
264 }
265}