qlty_coverage/ci/
circleci.rs

1use crate::{
2    ci::CI,
3    env::{EnvSource, SystemEnv},
4};
5
6#[derive(Debug)]
7pub struct CircleCI {
8    env: Box<dyn EnvSource>,
9}
10
11impl Default for CircleCI {
12    fn default() -> Self {
13        Self {
14            env: Box::<SystemEnv>::default(),
15        }
16    }
17}
18
19impl CI for CircleCI {
20    fn detect(&self) -> bool {
21        self.env.var("CIRCLECI").unwrap_or_default() == "true"
22    }
23
24    fn ci_name(&self) -> String {
25        "CircleCI".to_string()
26    }
27
28    fn ci_url(&self) -> String {
29        // CircleCI doesn't expose a server URL
30        "".to_string()
31    }
32
33    fn branch(&self) -> String {
34        self.env.var("CIRCLE_BRANCH").unwrap_or_default()
35    }
36
37    fn workflow(&self) -> String {
38        self.env.var("CIRCLE_WORKFLOW_ID").unwrap_or_default()
39    }
40
41    fn job(&self) -> String {
42        self.env.var("CIRCLE_JOB").unwrap_or_default()
43    }
44
45    fn build_id(&self) -> String {
46        self.env.var("CIRCLE_BUILD_NUM").unwrap_or_default()
47    }
48
49    fn build_url(&self) -> String {
50        self.env.var("CIRCLE_BUILD_URL").unwrap_or_default()
51    }
52
53    fn pull_number(&self) -> String {
54        if self.pull_url() != "" {
55            self.pull_url()
56                .split('/')
57                .last()
58                .unwrap_or_default()
59                .to_string()
60        } else {
61            "".to_string()
62        }
63    }
64
65    fn repository_name(&self) -> String {
66        self.env.var("CIRCLE_PROJECT_REPONAME").unwrap_or_default()
67    }
68
69    fn repository_url(&self) -> String {
70        self.env.var("CIRCLE_REPOSITORY_URL").unwrap_or_default()
71    }
72
73    fn pull_url(&self) -> String {
74        self.env.var("CIRCLE_PULL_REQUEST").unwrap_or_default()
75    }
76
77    fn commit_sha(&self) -> String {
78        self.env.var("CIRCLE_SHA1").unwrap_or_default()
79    }
80}
81
82#[cfg(test)]
83mod test {
84    use super::*;
85    use std::collections::HashMap;
86
87    #[derive(Debug, Clone, Default)]
88    pub struct HashMapEnv {
89        inner: HashMap<String, String>,
90    }
91
92    impl HashMapEnv {
93        pub fn new(env: HashMap<String, String>) -> Self {
94            Self { inner: env }
95        }
96    }
97
98    impl EnvSource for HashMapEnv {
99        fn var(&self, name: &str) -> Option<String> {
100            self.inner.get(name).cloned()
101        }
102    }
103
104    #[test]
105    fn detect_ci() {
106        let ci = CircleCI {
107            env: Box::new(HashMapEnv::default()),
108        };
109        assert_eq!(ci.detect(), false);
110
111        let mut env: HashMap<String, String> = HashMap::default();
112        env.insert("CIRCLECI".to_string(), "true".to_string());
113        let ci = CircleCI {
114            env: Box::new(HashMapEnv::new(env)),
115        };
116        assert_eq!(ci.detect(), true);
117        assert_eq!(&ci.ci_name(), "CircleCI");
118        assert_eq!(&ci.ci_url(), "");
119    }
120
121    #[test]
122    fn branch() {
123        let mut env: HashMap<String, String> = HashMap::default();
124        env.insert("CIRCLE_BRANCH".to_string(), "main".to_string());
125
126        let ci = CircleCI {
127            env: Box::new(HashMapEnv::new(env)),
128        };
129        assert_eq!(&ci.branch(), "main");
130    }
131
132    #[test]
133    fn workflow() {
134        let mut env: HashMap<String, String> = HashMap::default();
135        env.insert("CIRCLE_WORKFLOW_ID".to_string(), "workflow_id".to_string());
136
137        let ci = CircleCI {
138            env: Box::new(HashMapEnv::new(env)),
139        };
140        assert_eq!(&ci.workflow(), "workflow_id");
141    }
142
143    #[test]
144    fn job() {
145        let mut env: HashMap<String, String> = HashMap::default();
146        env.insert("CIRCLE_JOB".to_string(), "job_name".to_string());
147
148        let ci = CircleCI {
149            env: Box::new(HashMapEnv::new(env)),
150        };
151        assert_eq!(&ci.job(), "job_name");
152    }
153
154    #[test]
155    fn build_id() {
156        let mut env: HashMap<String, String> = HashMap::default();
157        env.insert("CIRCLE_BUILD_NUM".to_string(), "1234".to_string());
158
159        let ci = CircleCI {
160            env: Box::new(HashMapEnv::new(env)),
161        };
162        assert_eq!(&ci.build_id(), "1234");
163    }
164
165    #[test]
166    fn build_url() {
167        let mut env: HashMap<String, String> = HashMap::default();
168        env.insert(
169            "CIRCLE_BUILD_URL".to_string(),
170            "http://example.com/build/1234".to_string(),
171        );
172
173        let ci = CircleCI {
174            env: Box::new(HashMapEnv::new(env)),
175        };
176        assert_eq!(&ci.build_url(), "http://example.com/build/1234");
177    }
178
179    #[test]
180    fn pull_number() {
181        let mut env: HashMap<String, String> = HashMap::default();
182        env.insert(
183            "CIRCLE_PULL_REQUEST".to_string(),
184            "https://github.com/user/repo/pull/42".to_string(),
185        );
186
187        let ci = CircleCI {
188            env: Box::new(HashMapEnv::new(env)),
189        };
190        assert_eq!(&ci.pull_number(), "42");
191    }
192
193    #[test]
194    fn repository_name() {
195        let mut env: HashMap<String, String> = HashMap::default();
196        env.insert(
197            "CIRCLE_PROJECT_REPONAME".to_string(),
198            "repo_name".to_string(),
199        );
200
201        let ci = CircleCI {
202            env: Box::new(HashMapEnv::new(env)),
203        };
204        assert_eq!(&ci.repository_name(), "repo_name");
205    }
206
207    #[test]
208    fn repository_url() {
209        let mut env: HashMap<String, String> = HashMap::default();
210        env.insert(
211            "CIRCLE_REPOSITORY_URL".to_string(),
212            "https://github.com/user/repo".to_string(),
213        );
214
215        let ci = CircleCI {
216            env: Box::new(HashMapEnv::new(env)),
217        };
218        assert_eq!(&ci.repository_url(), "https://github.com/user/repo");
219    }
220
221    #[test]
222    fn commit_sha() {
223        let mut env: HashMap<String, String> = HashMap::default();
224        env.insert("CIRCLE_SHA1".to_string(), "abc123".to_string());
225
226        let ci = CircleCI {
227            env: Box::new(HashMapEnv::new(env)),
228        };
229        assert_eq!(&ci.commit_sha(), "abc123");
230    }
231}