1#[macro_export]
2macro_rules! plugin_struct {
3 ($name:ident, $client:ty, $meta:expr $(; $($field:ident: $fty:ty = $init:expr),+ $(,)?)?) => {
4 $crate::plugin_struct!(@define $name, $meta;
5 client: Option<$client> = None,
6 config: ::std::collections::HashMap<String, String> = ::std::collections::HashMap::new()
7 $(, $($field: $fty = $init),+)?
8 );
9
10 impl $name {
11 fn client(&self) -> $crate::PluginResult<&$client> {
12 self.client.as_ref().ok_or_else(|| {
13 $crate::PluginError::Internal("Plugin not initialized".to_string())
14 })
15 }
16 }
17 };
18 (custom $name:ident, $meta:expr; $($field:ident: $fty:ty = $init:expr),+ $(,)?) => {
19 $crate::plugin_struct!(@define $name, $meta; $($field: $fty = $init),+);
20 };
21 (@define $name:ident, $meta:expr; $($field:ident: $fty:ty = $init:expr),*) => {
22 pub struct $name {
23 metadata: $crate::PluginMetadata,
24 $($field: $fty,)*
25 }
26
27 impl Default for $name {
28 fn default() -> Self {
29 Self::new()
30 }
31 }
32
33 impl $name {
34 pub fn new() -> Self {
35 Self {
36 metadata: $meta,
37 $($field: $init,)*
38 }
39 }
40 }
41 };
42}
43
44#[macro_export]
45macro_rules! plugin_impl {
46 ($ty:ident [$($methods:tt)*] { $($items:tt)* }) => {
47 $crate::plugin_impl!(@munch $ty { $($items)* } [$($methods)*] []);
48 };
49 (@munch $ty:ident { $($items:tt)* } [] [$($out:tt)*]) => {
50 #[::async_trait::async_trait]
51 impl $crate::Plugin for $ty {
52 $($items)*
53 $($out)*
54 }
55 };
56 (@munch $ty:ident $items:tt [metadata $(, $($rest:tt)*)?] [$($out:tt)*]) => {
57 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
58 fn metadata(&self) -> &$crate::PluginMetadata {
59 &self.metadata
60 }
61 ]);
62 };
63 (@munch $ty:ident $items:tt [status_source $(, $($rest:tt)*)?] [$($out:tt)*]) => {
64 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
65 fn status_source(&self) -> Option<&$crate::StatusSource> {
66 self.status_source.as_ref()
67 }
68 ]);
69 };
70 (@munch $ty:ident $items:tt [available_from_filtered $(, $($rest:tt)*)?] [$($out:tt)*]) => {
71 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
72 async fn fetch_available_pipelines(
73 &self, params: Option<$crate::PaginationParams>,
74 ) -> $crate::PluginResult<$crate::PaginatedAvailablePipelines> {
75 self.fetch_available_pipelines_filtered(None, None, params).await
76 }
77 ]);
78 };
79 (@munch $ty:ident $items:tt [fetch_available_pipelines $(, $($rest:tt)*)?] [$($out:tt)*]) => {
80 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
81 async fn fetch_available_pipelines(
82 &self, params: Option<$crate::PaginationParams>,
83 ) -> $crate::PluginResult<$crate::PaginatedAvailablePipelines> {
84 self.fetch_available_pipelines_impl(params).await
85 }
86 ]);
87 };
88 (@munch $ty:ident $items:tt [fetch_available_pipelines_filtered $(, $($rest:tt)*)?] [$($out:tt)*]) => {
89 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
90 async fn fetch_available_pipelines_filtered(
91 &self, org: Option<String>, search: Option<String>,
92 params: Option<$crate::PaginationParams>,
93 ) -> $crate::PluginResult<$crate::PaginatedAvailablePipelines> {
94 self.fetch_available_pipelines_filtered_impl(org, search, params).await
95 }
96 ]);
97 };
98 (@munch $ty:ident $items:tt [fetch_organizations $(, $($rest:tt)*)?] [$($out:tt)*]) => {
99 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
100 async fn fetch_organizations(&self) -> $crate::PluginResult<Vec<$crate::Organization>> {
101 self.fetch_organizations_impl().await
102 }
103 ]);
104 };
105 (@munch $ty:ident $items:tt [ids_with_ci $(, $($rest:tt)*)?] [$($out:tt)*]) => {
106 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
107 async fn ids_with_ci(&self, ids: Vec<String>) -> $crate::PluginResult<Vec<String>> {
108 self.ids_with_ci_impl(ids).await
109 }
110 ]);
111 };
112 (@munch $ty:ident $items:tt [fetch_pipelines $(, $($rest:tt)*)?] [$($out:tt)*]) => {
113 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
114 async fn fetch_pipelines(&self) -> $crate::PluginResult<Vec<$crate::Pipeline>> {
115 self.fetch_pipelines_impl().await
116 }
117 ]);
118 };
119 (@munch $ty:ident $items:tt [fetch_run_history $(, $($rest:tt)*)?] [$($out:tt)*]) => {
120 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
121 async fn fetch_run_history(
122 &self, pipeline_id: &str, limit: usize,
123 ) -> $crate::PluginResult<Vec<$crate::PipelineRun>> {
124 self.fetch_run_history_impl(pipeline_id, limit).await
125 }
126 ]);
127 };
128 (@munch $ty:ident $items:tt [fetch_run_details $(, $($rest:tt)*)?] [$($out:tt)*]) => {
129 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
130 async fn fetch_run_details(
131 &self, pipeline_id: &str, run_number: i64,
132 ) -> $crate::PluginResult<$crate::PipelineRun> {
133 self.fetch_run_details_impl(pipeline_id, run_number).await
134 }
135 ]);
136 };
137 (@munch $ty:ident $items:tt [fetch_recent_runs $(, $($rest:tt)*)?] [$($out:tt)*]) => {
138 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
139 async fn fetch_recent_runs(
140 &self, pipeline_ids: &[String], limit: usize,
141 ) -> $crate::PluginResult<
142 ::std::collections::HashMap<String, Vec<$crate::PipelineRun>>,
143 > {
144 self.fetch_recent_runs_impl(pipeline_ids, limit).await
145 }
146 ]);
147 };
148 (@munch $ty:ident $items:tt [fetch_log_nodes $(, $($rest:tt)*)?] [$($out:tt)*]) => {
149 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
150 async fn fetch_log_nodes(
151 &self, run: $crate::RunRef<'_>,
152 ) -> $crate::PluginResult<Vec<$crate::LogNode>> {
153 self.fetch_log_nodes_impl(run).await
154 }
155 ]);
156 };
157 (@munch $ty:ident $items:tt [read_log $(, $($rest:tt)*)?] [$($out:tt)*]) => {
158 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
159 async fn read_log(
160 &self, run: $crate::RunRef<'_>, node_id: &str, from: Option<&$crate::LogCursor>,
161 sink: &mut $crate::LogSink,
162 ) -> $crate::PluginResult<$crate::LogRead> {
163 self.read_log_impl(run, node_id, from, sink).await
164 }
165 ]);
166 };
167 (@munch $ty:ident $items:tt [fetch_workflow_parameters $(, $($rest:tt)*)?] [$($out:tt)*]) => {
168 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
169 async fn fetch_workflow_parameters(
170 &self, workflow_id: &str,
171 ) -> $crate::PluginResult<Vec<$crate::WorkflowParameter>> {
172 self.fetch_workflow_parameters_impl(workflow_id).await
173 }
174 ]);
175 };
176 (@munch $ty:ident $items:tt [trigger_pipeline $(, $($rest:tt)*)?] [$($out:tt)*]) => {
177 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
178 async fn trigger_pipeline(
179 &self, params: $crate::TriggerParams,
180 ) -> $crate::PluginResult<$crate::TriggerResult> {
181 self.trigger_pipeline_impl(params).await
182 }
183 ]);
184 };
185 (@munch $ty:ident $items:tt [cancel_run $(, $($rest:tt)*)?] [$($out:tt)*]) => {
186 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
187 async fn cancel_run(
188 &self, pipeline_id: &str, run_number: i64,
189 ) -> $crate::PluginResult<()> {
190 self.cancel_run_impl(pipeline_id, run_number).await
191 }
192 ]);
193 };
194 (@munch $ty:ident $items:tt [force_cancel_run $(, $($rest:tt)*)?] [$($out:tt)*]) => {
195 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
196 async fn force_cancel_run(
197 &self, pipeline_id: &str, run_number: i64,
198 ) -> $crate::PluginResult<()> {
199 self.force_cancel_run_impl(pipeline_id, run_number).await
200 }
201 ]);
202 };
203 (@munch $ty:ident $items:tt [review_run $(, $($rest:tt)*)?] [$($out:tt)*]) => {
204 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
205 async fn review_run(
206 &self, pipeline_id: &str, run_number: i64, decision: $crate::ReviewDecision,
207 ) -> $crate::PluginResult<()> {
208 self.review_run_impl(pipeline_id, run_number, decision).await
209 }
210 ]);
211 };
212 (@munch $ty:ident $items:tt [rerun_run $(, $($rest:tt)*)?] [$($out:tt)*]) => {
213 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
214 async fn rerun_run(
215 &self, pipeline_id: &str, run_number: i64,
216 ) -> $crate::PluginResult<()> {
217 self.rerun(pipeline_id, run_number, false).await
218 }
219 ]);
220 };
221 (@munch $ty:ident $items:tt [rerun_failed_jobs $(, $($rest:tt)*)?] [$($out:tt)*]) => {
222 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
223 async fn rerun_failed_jobs(
224 &self, pipeline_id: &str, run_number: i64,
225 ) -> $crate::PluginResult<()> {
226 self.rerun(pipeline_id, run_number, true).await
227 }
228 ]);
229 };
230 (@munch $ty:ident $items:tt [enable_pipeline $(, $($rest:tt)*)?] [$($out:tt)*]) => {
231 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
232 async fn enable_pipeline(&self, pipeline_id: &str) -> $crate::PluginResult<()> {
233 self.enable_pipeline_impl(pipeline_id).await
234 }
235 ]);
236 };
237 (@munch $ty:ident $items:tt [check_permissions $(, $($rest:tt)*)?] [$($out:tt)*]) => {
238 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
239 async fn check_permissions(&self) -> $crate::PluginResult<$crate::PermissionStatus> {
240 self.check_permissions_impl().await
241 }
242 ]);
243 };
244 (@munch $ty:ident $items:tt [check_health $(, $($rest:tt)*)?] [$($out:tt)*]) => {
245 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
246 async fn check_health(
247 &self,
248 ) -> $crate::PluginResult<Vec<$crate::ComponentHealth>> {
249 self.check_health_impl().await
250 }
251 ]);
252 };
253 (@munch $ty:ident $items:tt [get_feature_availability $(, $($rest:tt)*)?] [$($out:tt)*]) => {
254 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
255 fn get_feature_availability(
256 &self, status: &$crate::PermissionStatus,
257 ) -> Vec<$crate::FeatureAvailability> {
258 self.get_feature_availability_impl(status)
259 }
260 ]);
261 };
262 (@munch $ty:ident $items:tt [get_field_options $(, $($rest:tt)*)?] [$($out:tt)*]) => {
263 $crate::plugin_impl!(@munch $ty $items [$($($rest)*)?] [$($out)*
264 async fn get_field_options(
265 &self, field_key: &str, config: &::std::collections::HashMap<String, String>,
266 ) -> $crate::PluginResult<Vec<String>> {
267 self.get_field_options_impl(field_key, config).await
268 }
269 ]);
270 };
271}
272
273#[cfg(test)]
274mod tests;