Skip to main content

ephemeris_forge_forgejo/
reconcile.rs

1//! Forgejo branch protection and repository reconciliation over the
2//! [`Api`].
3
4mod access;
5mod actions_variables;
6mod branch_rules;
7mod deploy_keys;
8mod labels;
9mod repository;
10mod tag_protection;
11mod webhooks;
12
13use ephemeris_forge::{Backend, Planned, RepoRef};
14
15use crate::api::{Api, ForgeError};
16use crate::operation::Operation;
17use crate::{ActionsVariables, Config, Live, plan};
18
19/// A typed Forgejo backend over an injected [`Api`] implementation.
20#[derive(Clone, Debug)]
21pub struct Client<A> {
22    api: A,
23}
24
25impl<A> Client<A> {
26    /// Construct a backend.
27    pub const fn new(api: A) -> Self {
28        Self { api }
29    }
30}
31
32impl<A: Api> Backend for Client<A> {
33    type Config = Config;
34    type Error = ForgeError;
35    type Live = Live;
36    type Operation = Operation;
37
38    fn validate(config: &Config) -> Result<(), Self::Error> {
39        config
40            .actions_variables
41            .as_ref()
42            .map_or(Ok(()), ActionsVariables::validate)
43            .map_err(ForgeError::from)
44    }
45
46    async fn read(&self, repository: &RepoRef, config: &Config) -> Result<Live, Self::Error> {
47        let mut live = Live::default();
48        self.read_repository(repository, &mut live).await?;
49        self.read_branch_rules(repository, config.branch_rules.as_ref(), &mut live)
50            .await?;
51        self.read_topics(repository, config.repository.topics.as_ref(), &mut live)
52            .await?;
53        self.read_access(repository, config.access.as_ref(), &mut live)
54            .await?;
55        self.read_labels(repository, config.labels.as_ref(), &mut live)
56            .await?;
57        self.read_tag_protection(repository, config.tag_protection.as_ref(), &mut live)
58            .await?;
59        self.read_webhooks(repository, config.webhooks.as_ref(), &mut live)
60            .await?;
61        self.read_deploy_keys(repository, config.deploy_keys.as_ref(), &mut live)
62            .await?;
63        self.read_actions_variables(repository, config.actions_variables.as_ref(), &mut live)
64            .await?;
65        Ok(live)
66    }
67
68    fn plan(config: &Config, live: &Live) -> Planned<Operation> {
69        plan::plan(config, live)
70    }
71
72    async fn apply(&self, repository: &RepoRef, operation: &Operation) -> Result<(), Self::Error> {
73        match operation {
74            Operation::Repository(operation) => self.apply_repository(repository, operation).await,
75            Operation::BranchRules(operation) => {
76                self.apply_branch_rules(repository, operation).await
77            }
78            Operation::Access(operation) => self.apply_access(repository, operation).await,
79            Operation::Labels(operation) => self.apply_labels(repository, operation).await,
80            Operation::TagProtection(operation) => {
81                self.apply_tag_protection(repository, operation).await
82            }
83            Operation::Webhooks(operation) => self.apply_webhooks(repository, operation).await,
84            Operation::DeployKeys(operation) => self.apply_deploy_keys(repository, operation).await,
85            Operation::ActionsVariables(operation) => {
86                self.apply_actions_variables(repository, operation).await
87            }
88        }
89    }
90}