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 MissingDescription(String),
28 MissingTags(String),
29}
30
31impl std::error::Error for OsedaCheckError {}
32
33impl std::fmt::Display for OsedaCheckError {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match self {
37 Self::MissingConfig(msg) => write!(f, "Missing config file: {}", msg),
38 Self::BadConfig(msg) => write!(f, "Bad config file: {}", msg),
39 Self::BadGitCredentials(msg) => write!(f, "Missing git credentials: {}", msg),
40 Self::DirectoryNameMismatch(msg) => {
41 write!(f, "Project name does not match directory: {}", msg)
42 }
43 Self::CouldNotPingLocalPresentation(msg) => {
44 write!(f, "Could not ping localhost after project was ran: {}", msg)
45 }
46 Self::MissingDescription(msg) => {
47 write!(f, "Config file is missing description: {}", msg)
48 }
49 Self::MissingTags(msg) => {
50 write!(f, "No tags detected: {}", msg)
51 }
52 }
53 }
54}
55
56pub fn check(opts: CheckOptions) -> Result<(), OsedaCheckError> {
65 match verify_project(opts.port) {
68 OsedaProjectStatus::DeployReady => Ok(()),
69 OsedaProjectStatus::NotDeploymentReady(err) => Err(err),
70 }
71}
72
73pub enum OsedaProjectStatus {
75 DeployReady,
76 NotDeploymentReady(OsedaCheckError),
77}
78
79fn verify_project(port_num: u16) -> OsedaProjectStatus {
89 let _conf = match config::read_and_validate_config() {
90 Ok(conf) => conf,
91 Err(err) => return OsedaProjectStatus::NotDeploymentReady(err),
92 };
93
94 let _run_handle = std::thread::spawn(run::run);
95
96 std::thread::sleep(Duration::from_millis(10000));
97
98 let addr = format!("http://localhost:{}", port_num);
99 let status = match net::get_status(&addr) {
100 Ok(status) => status,
101 Err(_) => {
102 return OsedaProjectStatus::NotDeploymentReady(
103 OsedaCheckError::CouldNotPingLocalPresentation(
104 "Could not ping presentation".to_owned(),
105 ),
106 );
107 }
108 };
109
110 if status != StatusCode::OK {
111 return OsedaProjectStatus::NotDeploymentReady(
112 OsedaCheckError::CouldNotPingLocalPresentation(
113 "Presentation returned non 200 error status code".to_owned(),
114 ),
115 );
116 }
117
118 println!("Project returned status code {:?}", status);
119
120 if kill_port(port_num).is_err() {
128 println!("Warning: could not kill process on port, project could still be running");
129 } else {
130 println!("Project process sucessfully terminated");
131 }
132
133 OsedaProjectStatus::DeployReady
134}