1use std::time::Duration;
2
3use clap::Args;
4use reqwest::StatusCode;
5
6use crate::cmd::run;
7use crate::config;
8
9use crate::net::{self, kill_port};
10
11#[derive(Args, Debug)]
13pub struct CheckOptions {
14 #[arg(long, default_value_t = 3000)]
17 port: u16,
18}
19#[derive(Debug)]
21pub enum OsedaCheckError {
22 MissingConfig(String),
23 BadConfig(String),
24 BadGitCredentials(String),
25 DirectoryNameMismatch(String),
26 CouldNotPingLocalPresentation(String),
27}
28
29impl std::error::Error for OsedaCheckError {}
30
31impl std::fmt::Display for OsedaCheckError {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 match self {
35 Self::MissingConfig(msg) => write!(f, "Missing config file {}", msg),
36 Self::BadConfig(msg) => write!(f, "Bad config file {}", msg),
37 Self::BadGitCredentials(msg) => write!(f, "Missing git credentials {}", msg),
38 Self::DirectoryNameMismatch(msg) => {
39 write!(f, "Project name does not match directory {}", msg)
40 }
41 Self::CouldNotPingLocalPresentation(msg) => {
42 write!(f, "Could not ping localhost after project was ran {}", msg)
43 }
44 }
45 }
46}
47
48pub fn check(opts: CheckOptions) -> Result<(), OsedaCheckError> {
57 match verify_project(opts.port) {
60 OsedaProjectStatus::DeployReady => Ok(()),
61 OsedaProjectStatus::NotDeploymentReady(err) => Err(err),
62 }
63}
64
65pub enum OsedaProjectStatus {
67 DeployReady,
68 NotDeploymentReady(OsedaCheckError),
69}
70
71fn verify_project(port_num: u16) -> OsedaProjectStatus {
81 let _conf = match config::read_and_validate_config() {
84 Ok(conf) => conf,
85 Err(err) => return OsedaProjectStatus::NotDeploymentReady(err),
86 };
87
88 let _run_handle = std::thread::spawn(run::run);
89
90 std::thread::sleep(Duration::from_millis(5000));
91
92 let addr = format!("http://localhost:{}", port_num);
93 let status = match net::get_status(&addr) {
94 Ok(status) => status,
95 Err(_) => {
96 return OsedaProjectStatus::NotDeploymentReady(
97 OsedaCheckError::CouldNotPingLocalPresentation(
98 "Could not ping presentation".to_owned(),
99 ),
100 );
101 }
102 };
103
104 if status != StatusCode::OK {
105 return OsedaProjectStatus::NotDeploymentReady(
106 OsedaCheckError::CouldNotPingLocalPresentation(
107 "Presentation returned non 200 error status code".to_owned(),
108 ),
109 );
110 }
111
112 println!("Project returned status code {:?}", status);
113
114 if kill_port(port_num).is_err() {
122 println!("Warning: could not kill process on port, project could still be running");
123 } else {
124 println!("Project process sucessfully terminated");
125 }
126
127 OsedaProjectStatus::DeployReady
128}