Skip to main content

greentic_dev/
toolchain_catalogue.rs

1#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2pub struct ToolchainPackageSpec {
3    pub crate_name: &'static str,
4    pub bins: &'static [&'static str],
5}
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct OciPackageSpec {
9    pub package: &'static str,
10}
11
12pub const GREENTIC_TOOLCHAIN_PACKAGES: &[ToolchainPackageSpec] = &[
13    ToolchainPackageSpec {
14        crate_name: "greentic-dev",
15        bins: &["greentic-dev"],
16    },
17    ToolchainPackageSpec {
18        crate_name: "greentic-operator",
19        bins: &["greentic-operator"],
20    },
21    ToolchainPackageSpec {
22        crate_name: "greentic-bundle",
23        bins: &["greentic-bundle"],
24    },
25    ToolchainPackageSpec {
26        crate_name: "greentic-setup",
27        bins: &["greentic-setup"],
28    },
29    ToolchainPackageSpec {
30        crate_name: "greentic-start",
31        bins: &["greentic-start"],
32    },
33    ToolchainPackageSpec {
34        crate_name: "greentic-deployer",
35        bins: &["greentic-deployer"],
36    },
37    ToolchainPackageSpec {
38        crate_name: "greentic-component",
39        bins: &["greentic-component"],
40    },
41    ToolchainPackageSpec {
42        crate_name: "greentic-flow",
43        bins: &["greentic-flow"],
44    },
45    ToolchainPackageSpec {
46        crate_name: "greentic-pack",
47        bins: &["greentic-pack"],
48    },
49    ToolchainPackageSpec {
50        crate_name: "greentic-runner",
51        bins: &["greentic-runner"],
52    },
53    ToolchainPackageSpec {
54        crate_name: "greentic-gui",
55        bins: &["greentic-gui"],
56    },
57    ToolchainPackageSpec {
58        crate_name: "greentic-secrets",
59        bins: &["greentic-secrets"],
60    },
61    ToolchainPackageSpec {
62        crate_name: "greentic-mcp",
63        bins: &["greentic-mcp"],
64    },
65];
66
67pub const GREENTIC_EXTENSION_PACK_PACKAGES: &[OciPackageSpec] = &[
68    OciPackageSpec {
69        package: "packs/demos/cards-demo",
70    },
71    OciPackageSpec {
72        package: "packs/demos/cloud-deploy-demo-app",
73    },
74    OciPackageSpec {
75        package: "packs/demos/deep-research-demo",
76    },
77    OciPackageSpec {
78        package: "packs/demos/helpdesk-itsm",
79    },
80    OciPackageSpec {
81        package: "packs/demos/hr-onboarding",
82    },
83    OciPackageSpec {
84        package: "packs/demos/incident-demo",
85    },
86    OciPackageSpec {
87        package: "packs/demos/quickstart",
88    },
89    OciPackageSpec {
90        package: "packs/demos/quickstart-event",
91    },
92    OciPackageSpec {
93        package: "packs/demos/redbutton-demo",
94    },
95    OciPackageSpec {
96        package: "packs/demos/sales-crm",
97    },
98    OciPackageSpec {
99        package: "packs/demos/supply-chain",
100    },
101    OciPackageSpec {
102        package: "packs/demos/telco-x",
103    },
104    OciPackageSpec {
105        package: "packs/demos/weather-mcp-demo",
106    },
107    OciPackageSpec {
108        package: "packs/demos/weatherapi-pack",
109    },
110    OciPackageSpec {
111        package: "packs/deployer/greentic.deploy.gcp",
112    },
113    OciPackageSpec {
114        package: "packs/deployer/greentic.deploy.azure",
115    },
116    OciPackageSpec {
117        package: "packs/deployer/greentic.deploy.aws",
118    },
119    OciPackageSpec {
120        package: "packs/deployer/greentic.deploy.helm",
121    },
122    OciPackageSpec {
123        package: "packs/deployer/greentic.deploy.juju-k8s",
124    },
125    OciPackageSpec {
126        package: "packs/deployer/greentic.deploy.juju-machine",
127    },
128    OciPackageSpec {
129        package: "packs/deployer/greentic.deploy.k8s-raw",
130    },
131    OciPackageSpec {
132        package: "packs/deployer/greentic.deploy.serverless",
133    },
134    OciPackageSpec {
135        package: "packs/deployer/greentic.deploy.snap",
136    },
137    OciPackageSpec {
138        package: "packs/deployer/greentic.deploy.terraform",
139    },
140    OciPackageSpec {
141        package: "packs/dw/context/compressor-pack",
142    },
143    OciPackageSpec {
144        package: "packs/dw/context/retrieval-pack",
145    },
146    OciPackageSpec {
147        package: "packs/dw/context/static-pack",
148    },
149    OciPackageSpec {
150        package: "packs/dw/control/basic-policy-pack",
151    },
152    OciPackageSpec {
153        package: "packs/dw/control/delegation-guard-pack",
154    },
155    OciPackageSpec {
156        package: "packs/dw/delegation/capability-match-pack",
157    },
158    OciPackageSpec {
159        package: "packs/dw/delegation/static-router-pack",
160    },
161    OciPackageSpec {
162        package: "packs/dw/engine/default-pack",
163    },
164    OciPackageSpec {
165        package: "packs/dw/engine/router-lite-pack",
166    },
167    OciPackageSpec {
168        package: "packs/dw/memory/short-term-in-memory-pack",
169    },
170    OciPackageSpec {
171        package: "packs/dw/memory/short-term-redis-pack",
172    },
173    OciPackageSpec {
174        package: "packs/dw/observer/basic-audit-pack",
175    },
176    OciPackageSpec {
177        package: "packs/dw/observer/basic-metrics-pack",
178    },
179    OciPackageSpec {
180        package: "packs/dw/planning/llm-outline-pack",
181    },
182    OciPackageSpec {
183        package: "packs/dw/planning/static-pack",
184    },
185    OciPackageSpec {
186        package: "packs/dw/reflection/llm-critic-pack",
187    },
188    OciPackageSpec {
189        package: "packs/dw/reflection/rules-pack",
190    },
191    OciPackageSpec {
192        package: "packs/dw/reflection/schema-check-pack",
193    },
194    OciPackageSpec {
195        package: "packs/dw/state/task-store-in-memory-pack",
196    },
197    OciPackageSpec {
198        package: "packs/dw/state/task-store-redis-pack",
199    },
200    OciPackageSpec {
201        package: "packs/dw/tool/component-adapter-pack",
202    },
203    OciPackageSpec {
204        package: "packs/dw/tool/mcp-adapter-pack",
205    },
206    OciPackageSpec {
207        package: "packs/dw/workspace/fs-pack",
208    },
209    OciPackageSpec {
210        package: "packs/dw/workspace/in-memory-pack",
211    },
212    OciPackageSpec {
213        package: "packs/events/events-dummy",
214    },
215    OciPackageSpec {
216        package: "packs/events/events-email",
217    },
218    OciPackageSpec {
219        package: "packs/events/events-email-sendgrid",
220    },
221    OciPackageSpec {
222        package: "packs/events/events-sms",
223    },
224    OciPackageSpec {
225        package: "packs/events/events-sms-twilio",
226    },
227    OciPackageSpec {
228        package: "packs/events/events-timer",
229    },
230    OciPackageSpec {
231        package: "packs/events/events-webhook",
232    },
233    OciPackageSpec {
234        package: "packs/messaging/messaging-dummy",
235    },
236    OciPackageSpec {
237        package: "packs/messaging/messaging-email",
238    },
239    OciPackageSpec {
240        package: "packs/messaging/messaging-http",
241    },
242    OciPackageSpec {
243        package: "packs/messaging/messaging-slack",
244    },
245    OciPackageSpec {
246        package: "packs/messaging/messaging-teams",
247    },
248    OciPackageSpec {
249        package: "packs/messaging/messaging-telegram",
250    },
251    OciPackageSpec {
252        package: "packs/messaging/messaging-webchat",
253    },
254    OciPackageSpec {
255        package: "packs/messaging/messaging-webchat-gui",
256    },
257    OciPackageSpec {
258        package: "packs/messaging/messaging-webex",
259    },
260    OciPackageSpec {
261        package: "packs/messaging/messaging-websocket",
262    },
263    OciPackageSpec {
264        package: "packs/messaging/messaging-whatsapp",
265    },
266    OciPackageSpec {
267        package: "packs/oauth/oauth-github",
268    },
269    OciPackageSpec {
270        package: "packs/oauth/oauth-google",
271    },
272    OciPackageSpec {
273        package: "packs/oauth/oauth-microsoft-graph",
274    },
275    OciPackageSpec {
276        package: "packs/oauth/oauth-oidc-generic",
277    },
278    OciPackageSpec {
279        package: "packs/oauth/oauth-slack",
280    },
281    OciPackageSpec {
282        package: "packs/secret/greentic.secrets.aws-sm.gtpack",
283    },
284    OciPackageSpec {
285        package: "packs/secret/greentic.secrets.azure-kv.gtpack",
286    },
287    OciPackageSpec {
288        package: "packs/secret/greentic.secrets.gcp-sm.gtpack",
289    },
290    OciPackageSpec {
291        package: "packs/secret/greentic.secrets.k8s.gtpack",
292    },
293    OciPackageSpec {
294        package: "packs/secret/greentic.secrets.providers.gtpack",
295    },
296    OciPackageSpec {
297        package: "packs/secret/greentic.secrets.vault-kv.gtpack",
298    },
299    OciPackageSpec {
300        package: "packs/state-memory",
301    },
302    OciPackageSpec {
303        package: "packs/state-redis",
304    },
305    OciPackageSpec {
306        package: "packs/state/state-memory",
307    },
308    OciPackageSpec {
309        package: "packs/state/state-redis",
310    },
311];
312pub const GREENTIC_COMPONENT_PACKAGES: &[OciPackageSpec] = &[
313    OciPackageSpec {
314        package: "component/component-events2msg",
315    },
316    OciPackageSpec {
317        package: "component/component-http",
318    },
319    OciPackageSpec {
320        package: "component/component-llm-openai",
321    },
322    OciPackageSpec {
323        package: "component/component-msg2events",
324    },
325    OciPackageSpec {
326        package: "component/component-pack2flow",
327    },
328    OciPackageSpec {
329        package: "component/component-sorx-business",
330    },
331    OciPackageSpec {
332        package: "components/component-adaptive-card",
333    },
334    OciPackageSpec {
335        package: "components/component-qa",
336    },
337    OciPackageSpec {
338        package: "components/secrets-provider-inmemory",
339    },
340    OciPackageSpec {
341        package: "components/templates",
342    },
343];
344
345#[cfg(test)]
346mod tests {
347    use super::{
348        GREENTIC_COMPONENT_PACKAGES, GREENTIC_EXTENSION_PACK_PACKAGES, GREENTIC_TOOLCHAIN_PACKAGES,
349        OciPackageSpec,
350    };
351    use std::collections::BTreeSet;
352
353    #[test]
354    fn catalogue_contains_expected_public_toolchain() {
355        let expected = [
356            ("greentic-dev", "greentic-dev"),
357            ("greentic-operator", "greentic-operator"),
358            ("greentic-bundle", "greentic-bundle"),
359            ("greentic-setup", "greentic-setup"),
360            ("greentic-start", "greentic-start"),
361            ("greentic-deployer", "greentic-deployer"),
362            ("greentic-component", "greentic-component"),
363            ("greentic-flow", "greentic-flow"),
364            ("greentic-pack", "greentic-pack"),
365            ("greentic-runner", "greentic-runner"),
366            ("greentic-gui", "greentic-gui"),
367            ("greentic-secrets", "greentic-secrets"),
368            ("greentic-mcp", "greentic-mcp"),
369        ];
370
371        let actual = catalogue_pairs();
372        for pair in expected {
373            assert!(actual.contains(&pair), "missing {pair:?}");
374        }
375    }
376
377    #[test]
378    fn catalogue_has_no_duplicate_crate_bin_pairs() {
379        let mut seen = BTreeSet::new();
380        for package in GREENTIC_TOOLCHAIN_PACKAGES {
381            for bin in package.bins {
382                assert!(
383                    seen.insert((package.crate_name, *bin)),
384                    "duplicate crate/bin pair: {}/{}",
385                    package.crate_name,
386                    bin
387                );
388            }
389        }
390    }
391
392    #[test]
393    fn extension_pack_catalogue_tracks_github_packages() {
394        assert_eq!(GREENTIC_EXTENSION_PACK_PACKAGES.len(), 81);
395        assert_catalogue_has_no_duplicate_packages(GREENTIC_EXTENSION_PACK_PACKAGES);
396        assert!(GREENTIC_EXTENSION_PACK_PACKAGES.iter().all(|package| {
397            package.package.starts_with("packs/") || package.package.starts_with("greentic-bundle/")
398        }));
399        assert!(
400            GREENTIC_EXTENSION_PACK_PACKAGES
401                .iter()
402                .any(|package| package.package == "packs/deployer/greentic.deploy.aws")
403        );
404        assert!(
405            GREENTIC_EXTENSION_PACK_PACKAGES
406                .iter()
407                .any(|package| package.package == "packs/deployer/greentic.deploy.helm")
408        );
409        assert!(GREENTIC_EXTENSION_PACK_PACKAGES.iter().all(|package| {
410            !package
411                .package
412                .starts_with("packs/deployer/greentic.fixture.")
413        }));
414        assert!(
415            GREENTIC_EXTENSION_PACK_PACKAGES
416                .iter()
417                .any(|package| package.package == "packs/messaging/messaging-webchat-gui")
418        );
419        assert!(
420            GREENTIC_EXTENSION_PACK_PACKAGES
421                .iter()
422                .any(|package| package.package == "packs/messaging/messaging-http")
423        );
424        assert!(
425            GREENTIC_EXTENSION_PACK_PACKAGES
426                .iter()
427                .any(|package| package.package == "packs/messaging/messaging-websocket")
428        );
429        assert!(
430            GREENTIC_EXTENSION_PACK_PACKAGES
431                .iter()
432                .any(|package| package.package == "packs/oauth/oauth-microsoft-graph")
433        );
434    }
435
436    #[test]
437    fn component_catalogue_tracks_github_packages() {
438        assert_eq!(GREENTIC_COMPONENT_PACKAGES.len(), 10);
439        assert_catalogue_has_no_duplicate_packages(GREENTIC_COMPONENT_PACKAGES);
440        assert!(GREENTIC_COMPONENT_PACKAGES.iter().all(|package| {
441            package.package.starts_with("component/")
442                || package.package.starts_with("components/")
443                || package.package.starts_with("validators/")
444        }));
445        assert!(
446            GREENTIC_COMPONENT_PACKAGES
447                .iter()
448                .any(|package| package.package == "component/component-llm-openai")
449        );
450        assert!(
451            GREENTIC_COMPONENT_PACKAGES
452                .iter()
453                .any(|package| package.package == "component/component-sorx-business")
454        );
455        assert!(
456            GREENTIC_COMPONENT_PACKAGES
457                .iter()
458                .any(|package| package.package == "components/component-adaptive-card")
459        );
460    }
461
462    fn catalogue_pairs() -> BTreeSet<(&'static str, &'static str)> {
463        GREENTIC_TOOLCHAIN_PACKAGES
464            .iter()
465            .flat_map(|package| {
466                package
467                    .bins
468                    .iter()
469                    .map(move |bin| (package.crate_name, *bin))
470            })
471            .collect()
472    }
473
474    fn assert_catalogue_has_no_duplicate_packages(catalogue: &[OciPackageSpec]) {
475        let mut seen = BTreeSet::new();
476        for package in catalogue {
477            assert!(
478                seen.insert(package.package),
479                "duplicate package: {}",
480                package.package
481            );
482        }
483    }
484}