smbcloud_model/
runner.rs

1use {
2    crate::error_codes::{ErrorCode::UnsupportedRunner, ErrorResponse},
3    serde::{Deserialize, Serialize},
4    serde_repr::{Deserialize_repr, Serialize_repr},
5    std::{
6        fmt::{self, Display, Formatter},
7        fs,
8        path::PathBuf,
9    },
10};
11
12#[derive(Debug, Deserialize_repr, Serialize_repr, Clone, Copy, PartialEq)]
13#[repr(u8)]
14#[tsync::tsync]
15pub enum Runner {
16    NodeJs,
17    Ruby,
18    Swift,
19    Monorepo = 255,
20}
21
22impl Display for Runner {
23    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
24        write!(f, "{:?}", self)
25    }
26}
27
28#[derive(Debug, Serialize, Deserialize)]
29#[tsync::tsync]
30pub enum NodeJsFramework {
31    NextJs,
32    Astro,
33}
34
35#[derive(Debug, Serialize, Deserialize)]
36#[tsync::tsync]
37pub enum RubyFramework {
38    Rails,
39}
40
41#[derive(Debug, Serialize, Deserialize)]
42#[tsync::tsync]
43pub enum SwiftFramework {
44    Vapor,
45}
46
47impl Runner {
48    pub fn from(repo_path: &PathBuf) -> Result<Runner, ErrorResponse> {
49        // See if we have a framework-based config.
50        if repo_path.join("package.json").exists()
51            && (next_config_exists(repo_path) || astro_config_exists(repo_path))
52        {
53            return Ok(Runner::NodeJs);
54        }
55
56        if repo_path.join("Gemfile").exists() {
57            return Ok(Runner::Ruby);
58        }
59        if repo_path.join("Package.swift").exists() {
60            return Ok(Runner::Swift);
61        }
62        // See if we have a monorepo setup.
63        non_framework_runner()
64    }
65
66    pub fn git_host(&self) -> String {
67        format!("git@{}.smbcloud.xyz", self.api())
68    }
69
70    fn api(&self) -> &str {
71        match self {
72            Runner::Monorepo => "monorepo",
73            Runner::NodeJs => "api",
74            Runner::Ruby | Runner::Swift => "api-1",
75        }
76    }
77}
78
79fn non_framework_runner() -> Result<Runner, ErrorResponse> {
80    Err(ErrorResponse::Error {
81        error_code: UnsupportedRunner,
82        message: UnsupportedRunner.message(None).to_string(),
83    })
84}
85
86// Helper function to detect any next.config.* file
87fn next_config_exists(repo_path: &PathBuf) -> bool {
88    if let Ok(entries) = fs::read_dir(repo_path) {
89        for entry in entries.flatten() {
90            let filename = entry.file_name();
91            let filename_str = filename.to_string_lossy();
92            if filename_str.starts_with("next.config.") {
93                return true;
94            }
95        }
96    }
97    false
98}
99
100// Helper function to detect any astro.config.* file
101fn astro_config_exists(repo_path: &PathBuf) -> bool {
102    if let Ok(entries) = fs::read_dir(repo_path) {
103        for entry in entries.flatten() {
104            let filename = entry.file_name();
105            let filename_str = filename.to_string_lossy();
106            if filename_str.starts_with("astro.config.") {
107                return true;
108            }
109        }
110    }
111    false
112}