1use clap::Args;
2use reqwest::StatusCode;
3use std::{error::Error, ffi::OsString, fs, io::stdout, path, time::Duration};
4
5use crate::cmd::init;
6use crate::cmd::run;
7use crate::config;
8
9use crate::{
10 categories::Category,
11 github,
12 net::{self, kill_port},
13};
14
15#[derive(Args, Debug)]
16pub struct CheckOptions {
17 #[arg(long, default_value_t = 3000)]
18 port: u16,
19}
20
21#[derive(Debug)]
22pub enum OsedaCheckError {
23 MissingConfig(String),
24 BadConfig(String),
25 BadGitCredentials(String),
26 DirectoryNameMismatch(String),
27 CouldNotPingLocalPresentation(String),
28}
29
30impl std::error::Error for OsedaCheckError {}
31
32impl 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> {
49 match verify_project(opts.port) {
52 OsedaProjectStatus::DeployReady => return Ok(()),
53 OsedaProjectStatus::NotDeploymentReady(err) => return Err(err),
54 }
55}
56
57pub enum OsedaProjectStatus {
58 DeployReady,
59 NotDeploymentReady(OsedaCheckError),
60}
61
62pub fn verify_project(port_num: u16) -> OsedaProjectStatus {
63 let conf = match config::read_and_validate_config() {
66 Ok(conf) => conf,
67 Err(err) => return OsedaProjectStatus::NotDeploymentReady(err),
68 };
69
70 let run_handle = std::thread::spawn(move || run::run());
71
72 std::thread::sleep(Duration::from_millis(5000));
73
74 let addr = format!("http://localhost:{}", port_num);
75 let status = match net::get_status(&addr) {
76 Ok(status) => status,
77 Err(_) => {
78 return OsedaProjectStatus::NotDeploymentReady(
79 OsedaCheckError::CouldNotPingLocalPresentation(
80 "Could not ping presentation".to_owned(),
81 ),
82 );
83 }
84 };
85
86 if status != StatusCode::OK {
87 return OsedaProjectStatus::NotDeploymentReady(
88 OsedaCheckError::CouldNotPingLocalPresentation(
89 "Presentation returned non 200 error status code".to_owned(),
90 ),
91 );
92 }
93
94 println!("Project returned status code {:?}", status);
95
96 if kill_port(port_num).is_err() {
104 println!("Warning: could not kill process on port, project could still be running");
105 } else {
106 println!("Project process sucessfully terminated");
107 }
108
109 return OsedaProjectStatus::DeployReady;
110}