Skip to main content

ephemeris_forge_github/
reconcile.rs

1//! GitHub reconciliation over the GitHub API.
2
3mod access;
4mod actions;
5mod autolinks;
6mod custom_properties;
7mod environments;
8mod labels;
9mod pages;
10mod repository;
11mod rulesets;
12mod security;
13mod variables;
14mod webhooks;
15
16use ephemeris_forge::{Backend, Caller, Planned, RepoRef};
17
18use crate::api::{Api, ForgeError};
19use crate::operation::Operation;
20use crate::{Autolinks, Config, Environments, Live, Rulesets, Variables, Webhooks, plan};
21
22/// A typed GitHub backend over an injected API implementation.
23#[derive(Clone, Debug)]
24pub struct Client<A> {
25    api: A,
26    caller: Option<Caller>,
27}
28
29impl<A> Client<A> {
30    /// Construct a backend.
31    pub const fn new(api: A) -> Self {
32        Self { api, caller: None }
33    }
34
35    /// Act as `caller` instead of asking the API who the token belongs to.
36    #[must_use]
37    pub fn acting_as(mut self, caller: Caller) -> Self {
38        self.caller = Some(caller);
39        self
40    }
41}
42
43impl<A: Api> Backend for Client<A> {
44    type Config = Config;
45    type Error = ForgeError;
46    type Live = Live;
47    type Operation = Operation;
48
49    fn validate(config: &Config) -> Result<(), Self::Error> {
50        config
51            .rulesets
52            .as_ref()
53            .map_or(Ok(()), Rulesets::validate)?;
54        config
55            .environments
56            .as_ref()
57            .map_or(Ok(()), Environments::validate)?;
58        config
59            .variables
60            .as_ref()
61            .map_or(Ok(()), Variables::validate)?;
62        config
63            .autolinks
64            .as_ref()
65            .map_or(Ok(()), Autolinks::validate)?;
66        config
67            .webhooks
68            .as_ref()
69            .map_or(Ok(()), Webhooks::validate)?;
70        Ok(())
71    }
72
73    async fn read(&self, repository: &RepoRef, config: &Config) -> Result<Live, Self::Error> {
74        let mut live = Live::default();
75        self.read_repository(repository, &config.repository, &mut live)
76            .await?;
77        live.access.caller.clone_from(&self.caller);
78        self.read_rulesets(repository, config.rulesets.as_ref(), &mut live)
79            .await?;
80        self.read_access(repository, config.access.as_ref(), &mut live)
81            .await?;
82        self.read_security(repository, &config.security, &mut live)
83            .await?;
84        self.read_pages(repository, config.pages.as_ref(), &mut live)
85            .await?;
86        self.read_environments(repository, config.environments.as_ref(), &mut live)
87            .await?;
88        self.read_actions(repository, config.actions.as_ref(), &mut live)
89            .await?;
90        self.read_variables(
91            repository,
92            config.variables.as_ref(),
93            config.environments.as_ref(),
94            &mut live,
95        )
96        .await?;
97        self.read_autolinks(repository, config.autolinks.as_ref(), &mut live)
98            .await?;
99        self.read_labels(repository, config.labels.as_ref(), &mut live)
100            .await?;
101        self.read_custom_properties(repository, config.custom_properties.as_ref(), &mut live)
102            .await?;
103        self.read_webhooks(repository, config.webhooks.as_ref(), &mut live)
104            .await?;
105        Ok(live)
106    }
107
108    fn plan(config: &Config, live: &Live) -> Planned<Operation> {
109        plan::plan(config, live)
110    }
111
112    async fn apply(&self, repository: &RepoRef, operation: &Operation) -> Result<(), Self::Error> {
113        match operation {
114            Operation::Repository(operation) => self.apply_repository(repository, operation).await,
115            Operation::Rulesets(operation) => self.apply_rulesets(repository, operation).await,
116            Operation::Access(operation) => self.apply_access(repository, operation).await,
117            Operation::Security(operation) => self.apply_security(repository, operation).await,
118            Operation::Pages(operation) => self.apply_pages(repository, operation).await,
119            Operation::Environments(operation) => {
120                self.apply_environments(repository, operation).await
121            }
122            Operation::Actions(operation) => self.apply_actions(repository, operation).await,
123            Operation::Autolinks(operation) => self.apply_autolinks(repository, operation).await,
124            Operation::Variables(operation) => self.apply_variables(repository, operation).await,
125            Operation::Labels(operation) => self.apply_labels(repository, operation).await,
126            Operation::CustomProperties(operation) => {
127                self.apply_custom_properties(repository, operation).await
128            }
129            Operation::Webhooks(operation) => self.apply_webhooks(repository, operation).await,
130        }
131    }
132}