feature/gresiq-v1
claude/smbcloud-github-app-k9641p
development
feature/apps
feature/build-release
feature/ci-docs
feature/ci-ruby-gems
feature/cicd
feature/completion
feature/dist-nuget
feature/fix-ci-sdk-pypi-rubygem
feature/fix-clippy-on-stable-channel
feature/fix-deployment-script
feature/github-email
feature/gresiq-v1
feature/project-new-structure
feature/rsync-deploy
feature/ruby-runner
feature/sdk-npm
feature/sdk-workflows
feature/smbcloud-cli-release-npm
feature/smbcloud-deploy
feature/wasm
main
release/v0.7.4
| 1 | use { |
| 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 | path::PathBuf, |
| 8 | }, |
| 9 | }; |
| 10 | |
| 11 | #[derive(Debug, Deserialize_repr, Serialize_repr, Clone, Copy, PartialEq, Default)] |
| 12 | #[repr(u8)] |
| 13 | #[tsync::tsync] |
| 14 | pub enum Runner { |
| 15 | #[default] |
| 16 | NodeJs = 0, |
| 17 | /// A pure static site: no app process on the server, nginx serves files |
| 18 | /// directly. Always deployed via rsync — git push has no build step to run. |
| 19 | Static = 1, |
| 20 | Ruby = 2, |
| 21 | Swift = 3, |
| 22 | Monorepo = 255, |
| 23 | } |
| 24 | |
| 25 | impl Display for Runner { |
| 26 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
| 27 | match self { |
| 28 | Runner::NodeJs => write!(f, "NodeJs"), |
| 29 | Runner::Static => write!(f, "Static"), |
| 30 | Runner::Ruby => write!(f, "Ruby"), |
| 31 | Runner::Swift => write!(f, "Swift"), |
| 32 | Runner::Monorepo => write!(f, "Monorepo"), |
| 33 | } |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | #[derive(Debug, Serialize, Deserialize)] |
| 38 | #[tsync::tsync] |
| 39 | pub enum NodeJsFramework { |
| 40 | NextJs, |
| 41 | Astro, |
| 42 | } |
| 43 | |
| 44 | #[derive(Debug, Serialize, Deserialize)] |
| 45 | #[tsync::tsync] |
| 46 | pub enum RubyFramework { |
| 47 | Rails, |
| 48 | } |
| 49 | |
| 50 | #[derive(Debug, Serialize, Deserialize)] |
| 51 | #[tsync::tsync] |
| 52 | pub enum SwiftFramework { |
| 53 | Vapor, |
| 54 | } |
| 55 | |
| 56 | impl Runner { |
| 57 | pub fn from(repo_path: &PathBuf) -> Result<Runner, ErrorResponse> { |
| 58 | // Any package.json-driven app belongs on the NodeJs runner. |
| 59 | // Framework-specific checks are not reliable because modern Next.js apps |
| 60 | // do not need a next.config.* file at all. |
| 61 | if repo_path.join("package.json").exists() { |
| 62 | return Ok(Runner::NodeJs); |
| 63 | } |
| 64 | |
| 65 | if repo_path.join("Gemfile").exists() { |
| 66 | return Ok(Runner::Ruby); |
| 67 | } |
| 68 | if repo_path.join("Package.swift").exists() { |
| 69 | return Ok(Runner::Swift); |
| 70 | } |
| 71 | // See if we have a monorepo setup. |
| 72 | non_framework_runner() |
| 73 | } |
| 74 | |
| 75 | pub fn git_host(&self) -> String { |
| 76 | format!("git@{}.smbcloud.xyz", self.api()) |
| 77 | } |
| 78 | |
| 79 | /// Returns the explicit hostname used for rsync SSH connections. |
| 80 | /// e.g. `api.smbcloud.xyz` or `api-1.smbcloud.xyz` |
| 81 | pub fn rsync_host(&self) -> String { |
| 82 | format!("{}.smbcloud.xyz", self.api()) |
| 83 | } |
| 84 | |
| 85 | fn api(&self) -> &str { |
| 86 | match self { |
| 87 | Runner::Monorepo => "monorepo", |
| 88 | // Static sites and NodeJs projects share the same lightweight tier |
| 89 | Runner::NodeJs | Runner::Static => "api", |
| 90 | Runner::Ruby | Runner::Swift => "api-1", |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | fn non_framework_runner() -> Result<Runner, ErrorResponse> { |
| 96 | Err(ErrorResponse::Error { |
| 97 | error_code: UnsupportedRunner, |
| 98 | message: UnsupportedRunner.message(None).to_string(), |
| 99 | }) |
| 100 | } |