interprex_test/
code_hosting.rs1use async_trait::async_trait;
2use interprex::{
3 AppliedSourceRequirements, AppliedSourceRequirementsProvider, CodeHostingProvider, CommitRange,
4 ProviderError, Repository, RepositoryFacts, RepositorySettings, Result,
5 SourceCodeConfigurationProvider,
6};
7use secrecy::SecretString;
8
9use crate::state::{FakeProvider, missing};
10
11#[async_trait]
12impl CodeHostingProvider for FakeProvider {
13 async fn repository(&self, repository: &Repository) -> Result<RepositoryFacts> {
14 self.state
15 .read()
16 .await
17 .repositories
18 .get(repository)
19 .map(|(facts, _)| facts.clone())
20 .ok_or_else(|| missing(repository.to_string()))
21 }
22
23 async fn settings(&self, repository: &Repository) -> Result<RepositorySettings> {
24 self.state
25 .read()
26 .await
27 .repositories
28 .get(repository)
29 .map(|(_, settings)| settings.clone())
30 .ok_or_else(|| missing(repository.to_string()))
31 }
32
33 async fn apply_settings(
34 &self,
35 repository: &Repository,
36 settings: &RepositorySettings,
37 ) -> Result<RepositorySettings> {
38 let mut state = self.state.write().await;
39 let (_, current) = state
40 .repositories
41 .get_mut(repository)
42 .ok_or_else(|| missing(repository.to_string()))?;
43 *current = settings.clone();
44 Ok(settings.clone())
45 }
46
47 async fn put_secret(
48 &self,
49 repository: &Repository,
50 name: &str,
51 _value: SecretString,
52 ) -> Result<()> {
53 self.state
54 .write()
55 .await
56 .secret_names
57 .entry(repository.clone())
58 .or_default()
59 .push(name.to_owned());
60 Ok(())
61 }
62}
63
64#[async_trait]
65impl SourceCodeConfigurationProvider for FakeProvider {
66 type Ruleset = serde_json::Value;
67
68 async fn read_rulesets(&self, _repository: &Repository) -> Result<Vec<Self::Ruleset>> {
69 Err(unsupported("read source rulesets"))
70 }
71
72 async fn apply_ruleset(
73 &self,
74 _repository: &Repository,
75 _ruleset: &Self::Ruleset,
76 ) -> Result<Self::Ruleset> {
77 Err(unsupported("apply source ruleset"))
78 }
79}
80
81#[async_trait]
82impl AppliedSourceRequirementsProvider for FakeProvider {
83 async fn applied_requirements(
84 &self,
85 repository: &Repository,
86 target_branch: &str,
87 commit_range: &CommitRange,
88 ) -> Result<AppliedSourceRequirements> {
89 for (value, field) in [
90 (target_branch, "target branch"),
91 (&commit_range.base_sha, "base sha"),
92 (&commit_range.head_sha, "head sha"),
93 ] {
94 if value.is_empty() {
95 return Err(ProviderError::InvalidInput {
96 provider: "fake",
97 fact: format!("{field} must not be empty"),
98 });
99 }
100 }
101 let key = (
102 repository.clone(),
103 target_branch.to_owned(),
104 commit_range.base_sha.clone(),
105 commit_range.head_sha.clone(),
106 );
107 let state = self.state.read().await;
108 if let Some(error) = state.applied_requirement_errors.get(&key) {
109 return Err(error.clone());
110 }
111 state
112 .applied_requirements
113 .get(&key)
114 .cloned()
115 .ok_or_else(|| ProviderError::NotFound {
116 entity: format!(
117 "applied requirements for {repository}:{target_branch} at {}..{}",
118 commit_range.base_sha, commit_range.head_sha
119 ),
120 })
121 }
122}
123
124fn unsupported(operation: &'static str) -> ProviderError {
125 ProviderError::Unsupported {
126 provider: "fake",
127 operation,
128 }
129}