@smbcloud / cli / commits / 77748ad

move process deploy to its own file

Seto committed Sep 20, 2025 at 18:05 UTC 77748adfe9e94158a8e3cc511761d6fbdc9f53f4
3 files changed +28 -237
crates/cli/src/deploy/mod.rs
+1 -214
@@ -1,219 +1,6 @@
1 pub mod config;
2 mod detect_runner;
3 mod git;
4 +pub mod process_deploy;
5 mod remote_messages;
6 mod setup;
6 -
7 -use {
8 - crate::{
9 - account::{lib::is_logged_in, login::process_login},
10 - cli::CommandResult,
11 - deploy::config::check_project,
12 - deploy::detect_runner::detect_runner,
13 - token::get_smb_token,
14 - ui::{fail_message, succeed_message, succeed_symbol},
15 - },
16 - anyhow::{anyhow, Result},
17 - config::check_config,
18 - git::remote_deployment_setup,
19 - git2::{PushOptions, RemoteCallbacks, Repository},
20 - remote_messages::{build_next_app, start_server},
21 - smbcloud_model::project::{DeploymentPayload, DeploymentStatus},
22 - smbcloud_network::environment::Environment,
23 - smbcloud_networking_account::me::me,
24 - smbcloud_networking_project::{
25 - crud_project_deployment_create::create_deployment, crud_project_deployment_update::update,
26 - },
27 - spinners::Spinner,
28 - std::sync::{
29 - atomic::{AtomicBool, Ordering},
30 - Arc,
31 - },
32 -};
33 -
34 -pub async fn process_deploy(env: Environment) -> Result<CommandResult> {
35 - // Check credentials.
36 - if !is_logged_in(env) {
37 - let _ = process_login(env).await;
38 - }
39 -
40 - // Get current token
41 - let access_token = get_smb_token(env).await?;
42 -
43 - // Check config.
44 - let config = check_config(env).await?;
45 -
46 - // Check runner.
47 - let runner = detect_runner().await?;
48 -
49 - // Validate config with project.
50 - check_project(env, &access_token, config.project.id).await?;
51 -
52 - // Check remote repository setup.
53 - let repo = match Repository::open(".") {
54 - Ok(repo) => repo,
55 - Err(_) => {
56 - return Err(anyhow!(fail_message(
57 - "No git repository found. Init with `git init` command."
58 - )))
59 - }
60 - };
61 -
62 - // Get the current branch
63 - let head = match repo.head() {
64 - Ok(head) => head,
65 - Err(_) => {
66 - return Err(anyhow!(fail_message(
67 - "No HEAD reference found. Create a commit with `git commit` command."
68 - )))
69 - }
70 - };
71 -
72 - // Check if we're on the main branch
73 - let branch_name = match head.shorthand() {
74 - Some(name) => name,
75 - None => {
76 - return Err(anyhow!(fail_message(
77 - "Unable to determine current branch name."
78 - )))
79 - }
80 - };
81 -
82 - if branch_name != "main" && branch_name != "master" {
83 - return Err(anyhow!(fail_message(
84 - &format!("Not on main branch. Current branch: '{}'. Switch to main branch with `git checkout main` command.", branch_name)
85 - )));
86 - }
87 -
88 - let main_branch = head;
89 -
90 - let repository = match &config.project.repository {
91 - Some(repo) => repo,
92 - None => return Err(anyhow!(fail_message("Repository not found."))),
93 - };
94 -
95 - let mut origin = remote_deployment_setup(&runner, &repo, repository).await?;
96 -
97 - let commit_hash = match main_branch.resolve() {
98 - Ok(result) => match result.target() {
99 - Some(hash_id) => hash_id,
100 - None => return Err(anyhow!("Should have at least one commit.")),
101 - },
102 - Err(_) => return Err(anyhow!("Cannot resolve main branch.")),
103 - };
104 - let payload = DeploymentPayload {
105 - commit_hash: commit_hash.to_string(),
106 - status: DeploymentStatus::Started,
107 - };
108 -
109 - let created_deployment =
110 - create_deployment(env, &access_token, config.project.id, payload).await?;
111 - let user = me(env, &access_token).await?;
112 -
113 - let mut push_opts = PushOptions::new();
114 - let mut callbacks = RemoteCallbacks::new();
115 -
116 - // For updating status to failed
117 - let deployment_failed_flag = Arc::new(AtomicBool::new(false));
118 - let update_env = env; // Env is Copy
119 - let update_access_token = access_token.clone();
120 - let update_project_id = config.project.id;
121 - let update_deployment_id = created_deployment.id;
122 -
123 - // Set the credentials
124 - callbacks.credentials(config.credentials(user));
125 - callbacks.sideband_progress(|data| {
126 - // Convert bytes to string, print line by line
127 - if let Ok(text) = std::str::from_utf8(data) {
128 - for line in text.lines() {
129 - if line.contains(&build_next_app()) {
130 - println!("Building the app {}", succeed_symbol());
131 - }
132 - if line.contains(&start_server(repository)) {
133 - println!("App restart {}", succeed_symbol());
134 - }
135 - }
136 - }
137 - true // continue receiving.
138 - });
139 - callbacks.push_update_reference({
140 - let flag_clone = deployment_failed_flag.clone();
141 - let access_token_for_update_cb = update_access_token.clone();
142 - let project_id_for_update_cb = update_project_id;
143 - let deployment_id_for_update_cb = update_deployment_id;
144 -
145 - move |_refname, status_message| {
146 - if let Some(e) = status_message {
147 - // Try to set the flag. If it was already true, do nothing.
148 - if !flag_clone.swap(true, Ordering::SeqCst) {
149 - println!(
150 - "Deployment ref update failed: {}. Marking deployment as Failed.",
151 - e
152 - );
153 -
154 - let update_payload = DeploymentPayload {
155 - commit_hash: commit_hash.to_string(),
156 - status: DeploymentStatus::Failed,
157 - };
158 -
159 - // We are in a sync callback, so we need to block on the async task.
160 - let handle = tokio::runtime::Handle::current();
161 - let result = handle.block_on(async {
162 - update(
163 - update_env, // Env is Copy
164 - access_token_for_update_cb.clone(),
165 - project_id_for_update_cb,
166 - deployment_id_for_update_cb,
167 - update_payload,
168 - )
169 - .await
170 - });
171 -
172 - match result {
173 - Ok(_) => println!("Deployment status successfully updated to Failed."),
174 - Err(update_err) => {
175 - eprintln!("Error updating deployment status to Failed: {}", update_err)
176 - }
177 - }
178 - }
179 - }
180 - Ok(()) // Report success for the git callback itself, error is handled above.
181 - }
182 - });
183 - push_opts.remote_callbacks(callbacks);
184 -
185 - let spinner = Spinner::new(
186 - spinners::Spinners::Hamburger,
187 - succeed_message("Deploying > "),
188 - );
189 -
190 - match origin.push(&["refs/heads/main:refs/heads/main"], Some(&mut push_opts)) {
191 - Ok(_) => {
192 - // Update deployment status to Done
193 - let update_payload = DeploymentPayload {
194 - commit_hash: commit_hash.to_string(),
195 - status: DeploymentStatus::Done,
196 - };
197 - let result = update(
198 - env,
199 - access_token.clone(),
200 - config.project.id,
201 - created_deployment.id,
202 - update_payload,
203 - )
204 - .await;
205 - match result {
206 - Ok(_) => println!("App is running {}", succeed_symbol()),
207 - Err(update_err) => {
208 - eprintln!("Error updating deployment status to Done: {}", update_err)
209 - }
210 - }
211 - Ok(CommandResult {
212 - spinner,
213 - symbol: succeed_symbol(),
214 - msg: succeed_message("Deployment complete."),
215 - })
216 - }
217 - Err(e) => Err(anyhow!(fail_message(&e.to_string()))),
218 - }
219 -}
crates/cli/src/deploy/process_deploy.rs
+26 -22
@@ -1,26 +1,30 @@
1 -use crate::deploy::{
2 - account::{lib::is_logged_in, login::process_login},
3 - cli::CommandResult,
4 - config::check_config,
5 - deploy::config::check_project,
6 - detect_runner::detect_runner,
7 - git::remote_deployment_setup,
8 - remote_messages::{build_next_app, start_server},
9 - token::get_smb_token,
10 - ui::{fail_message, succeed_message, succeed_symbol},
11 -};
12 -use anyhow::{anyhow, Result};
13 -use git2::{PushOptions, RemoteCallbacks, Repository};
14 -use smbcloud_model::project::{DeploymentPayload, DeploymentStatus};
15 -use smbcloud_network::environment::Environment;
16 -use smbcloud_networking_account::me::me;
17 -use smbcloud_networking_project::{
18 - crud_project_deployment_create::create_deployment, crud_project_deployment_update::update,
1 +use {
2 + crate::{
3 + account::{lib::is_logged_in, login::process_login},
4 + cli::CommandResult,
5 + deploy::{
6 + config::{check_config, check_project},
7 + detect_runner::detect_runner,
8 + git::remote_deployment_setup,
9 + remote_messages::{build_next_app, start_server},
10 + },
11 + token::get_smb_token,
12 + ui::{fail_message, succeed_message, succeed_symbol},
13 + },
14 + anyhow::{anyhow, Result},
15 + git2::{PushOptions, RemoteCallbacks, Repository},
16 + smbcloud_model::project::{DeploymentPayload, DeploymentStatus},
17 + smbcloud_network::environment::Environment,
18 + smbcloud_networking_account::me::me,
19 + smbcloud_networking_project::{
20 + crud_project_deployment_create::create_deployment, crud_project_deployment_update::update,
21 + },
22 + spinners::Spinner,
23 + std::sync::{
24 + atomic::{AtomicBool, Ordering},
25 + Arc,
26 + },
27 };
20 -use spinners::Spinner;
21 -use std::sync::atomic::AtomicBool;
22 -use std::sync::atomic::Ordering;
23 -use std::sync::Arc;
28
29 pub async fn process_deploy(env: Environment) -> Result<CommandResult> {
30 // Check credentials.
crates/cli/src/main.rs
+1 -1
@@ -5,12 +5,12 @@ use smbcloud_cli::account::login::process_login;
5 use smbcloud_cli::account::logout::process_logout;
6 use smbcloud_cli::account::me::process_me;
7 use smbcloud_cli::cli::CommandResult;
8 +use smbcloud_cli::deploy::process_deploy::process_deploy;
9 use smbcloud_cli::project::crud_create::process_project_init;
10 use smbcloud_cli::project::process::process_project;
11 use smbcloud_cli::{
12 account::process_account,
13 cli::{Cli, Commands},
13 - deploy::process_deploy,
14 };
15 use smbcloud_network::{environment::Environment, network::check_internet_connection};
16 use std::{