ephemeris_forge_github/plan/
webhooks.rs1use ephemeris_forge::{Collection, FieldDiff, Limitation, NameSet, Report};
2
3use crate::Webhooks;
4use crate::api::model;
5use crate::operation::webhooks::Operation;
6
7const WEB: &str = "web";
8
9pub(super) fn plan(
10 config: Option<&Webhooks>,
11 live: &[model::Webhook],
12 report: &mut Report,
13) -> Vec<Operation> {
14 let Some(config) = config else {
15 return Vec::new();
16 };
17 for hook in live.iter().filter(|hook| hook.name != WEB) {
18 report.limitations.push(Limitation::WebhookKindLeftAlone {
19 id: hook.id,
20 kind: hook.name.clone(),
21 });
22 }
23 let managed: Vec<&model::Webhook> = live.iter().filter(|hook| hook.name == WEB).collect();
24 Collection {
25 noun: "webhook",
26 mode: config.mode,
27 }
28 .plan(
29 &config.webhooks,
30 &managed,
31 report,
32 |hook, url| hook.config.url.as_deref() == Some(url),
33 |url, desired, actual, report| {
34 let mut diff = FieldDiff::default();
35 let mut config_changed = diff.check(
36 "content_type",
37 actual.is_some_and(|actual| {
38 actual.config.content_type.as_deref() == Some(desired.content_type.as_str())
39 }),
40 &actual.and_then(|actual| actual.config.content_type.as_deref()),
41 &desired.content_type,
42 );
43 config_changed |= diff.check(
44 "insecure_ssl",
45 actual.is_some_and(|actual| actual.config.insecure() == desired.insecure_ssl),
46 &actual.map(|actual| actual.config.insecure()),
47 &desired.insecure_ssl,
48 );
49 if config_changed && actual.is_some_and(|actual| actual.config.secret.is_some()) {
50 report.limitations.push(Limitation::WebhookSecretKept {
51 url: url.to_owned(),
52 });
53 config_changed = false;
54 }
55 let mut changed = config_changed;
56 let events = actual.map(|actual| NameSet::new(actual.events.clone()));
57 changed |= diff
58 .want_set(
59 "events",
60 &NameSet::new(desired.events.clone()),
61 events.as_ref(),
62 )
63 .is_some();
64 changed |= diff.compare(
65 "active",
66 actual.map(|actual| &actual.active),
67 &desired.active,
68 );
69 let url = url.to_owned();
70 let webhook = desired.clone();
71 let operation = match actual {
72 _ if !changed => None,
73 Some(actual) => Some(Operation::Update {
74 url,
75 id: actual.id,
76 webhook,
77 config_changed,
78 }),
79 None => Some(Operation::Create { url, webhook }),
80 };
81 (diff, operation.into_iter().collect())
82 },
83 |hook, _| {
84 let url = hook
85 .config
86 .url
87 .clone()
88 .unwrap_or_else(|| format!("#{}", hook.id));
89 Some((url.clone(), Operation::Delete { url, id: hook.id }))
90 },
91 )
92}