Skip to main content

ephemeris_forge_forgejo/plan/
deploy_keys.rs

1use ephemeris_forge::{Collection, FieldDiff, Report};
2
3use crate::Live;
4use crate::api::request::CreateKeyOption;
5use crate::config::DeployKeys;
6use crate::operation::deploy_keys::Operation;
7
8/// Deletes come before creates, because Forgejo refuses a key that exists
9/// under another title.
10pub(super) fn plan(
11    config: Option<&DeployKeys>,
12    live: &Live,
13    report: &mut Report,
14) -> Vec<Operation> {
15    let Some(config) = config else {
16        return Vec::new();
17    };
18    let mut operations = Collection {
19        noun: "deploy key",
20        mode: config.mode,
21    }
22    .plan(
23        &config.keys,
24        &live.deploy_keys,
25        report,
26        |key, title| key.title.as_deref() == Some(title),
27        |title, desired, actual, _| {
28            let mut diff = FieldDiff::default();
29            diff.check(
30                "key",
31                actual
32                    .is_some_and(|key| key.key.as_deref().is_some_and(|key| desired.matches(key))),
33                &actual.and_then(|key| key.key.as_deref()),
34                &desired.key,
35            );
36            diff.check(
37                "read_only",
38                actual.is_some_and(|key| key.read_only.unwrap_or(false) == desired.read_only),
39                &actual.map(|key| key.read_only.unwrap_or(false)),
40                &desired.read_only,
41            );
42            let mut operations = Vec::new();
43            if diff.has_changes() {
44                operations.extend(actual.map(|actual| Operation::Delete {
45                    id: actual.id,
46                    title: title.to_owned(),
47                }));
48                operations.push(Operation::Create {
49                    body: CreateKeyOption::new(title, desired),
50                });
51            }
52            (diff, operations)
53        },
54        |key, _| {
55            let title = key.title.clone()?;
56            Some((title.clone(), Operation::Delete { id: key.id, title }))
57        },
58    );
59    operations.sort_by_key(|operation| !matches!(operation, Operation::Delete { id: _, title: _ }));
60    operations
61}