Skip to main content

lean_ctx/core/providers/
config.rs

1use std::env;
2
3#[derive(Debug, Clone)]
4pub struct GitLabConfig {
5    pub host: String,
6    pub token: String,
7    pub project_path: Option<String>,
8}
9
10impl GitLabConfig {
11    pub fn from_env() -> Result<Self, String> {
12        let token = env::var("LEAN_CTX_GITLAB_TOKEN")
13            .or_else(|_| env::var("GITLAB_TOKEN"))
14            .or_else(|_| env::var("CI_JOB_TOKEN"))
15            .map_err(|_| {
16                "No GitLab token found. Set GITLAB_TOKEN or LEAN_CTX_GITLAB_TOKEN.".to_string()
17            })?;
18
19        let host = env::var("GITLAB_HOST")
20            .or_else(|_| env::var("CI_SERVER_HOST"))
21            .unwrap_or_else(|_| "gitlab.com".to_string());
22
23        let project_path = env::var("CI_PROJECT_PATH")
24            .ok()
25            .or_else(|| detect_project_from_git_remote(&host));
26
27        Ok(Self {
28            host,
29            token,
30            project_path,
31        })
32    }
33
34    pub fn api_url(&self, endpoint: &str) -> String {
35        format!("https://{}/api/v4{}", self.host, endpoint)
36    }
37}
38
39fn detect_project_from_git_remote(host: &str) -> Option<String> {
40    let output = std::process::Command::new("git")
41        .args(["remote", "get-url", "origin"])
42        .output()
43        .ok()?;
44    if !output.status.success() {
45        return None;
46    }
47    let url = String::from_utf8_lossy(&output.stdout).trim().to_string();
48
49    // Handle SSH: git@gitlab.com:group/project.git
50    if let Some(rest) = url.strip_prefix(&format!("git@{host}:")) {
51        return Some(rest.trim_end_matches(".git").to_string());
52    }
53    // Handle HTTPS: https://gitlab.com/group/project.git
54    if let Some(rest) = url.strip_prefix(&format!("https://{host}/")) {
55        return Some(rest.trim_end_matches(".git").to_string());
56    }
57    None
58}