omni_orchestrator/schemas/v1/api/helpers/
release.rs

1use rocket::data::Data;
2use rocket::http::ContentType;
3use rocket::http::Status;
4use rocket_multipart_form_data::{
5    MultipartFormData, MultipartFormDataField, MultipartFormDataOptions,
6};
7use std::fs;
8
9pub async fn release<'a>(
10    app_id: String,
11    release_version: String,
12    content_type: &ContentType,
13    data: Data<'a>,
14) -> Result<Status, Status> {
15    println!("Starting deploy handler");
16    println!("Content-Type: {:?}", content_type);
17
18    println!("Build started for app: {:#?}", app_id);
19
20    let mut options = MultipartFormDataOptions::new();
21
22    // Add multiple possible field names to help debug
23    options
24        .allowed_fields
25        .push(MultipartFormDataField::file("media").size_limit(5 * 1024 * 1024 * 1024));
26    options
27        .allowed_fields
28        .push(MultipartFormDataField::file("file").size_limit(5 * 1024 * 1024 * 1024));
29    options
30        .allowed_fields
31        .push(MultipartFormDataField::file("upload").size_limit(5 * 1024 * 1024 * 1024));
32
33    // Parse form data with detailed error handling
34    let form_data = match MultipartFormData::parse(content_type, data, options).await {
35        Ok(form) => {
36            println!("Successfully parsed form data");
37            form
38        }
39        Err(e) => {
40            println!("Error parsing form data: {:?}", e);
41            return Err(Status::new(400));
42        }
43    };
44
45    // Print ALL available fields for debugging
46    println!("Available fields in form_data:");
47    println!("Raw fields: {:#?}", form_data.raw);
48    println!("Text fields: {:#?}", form_data.texts);
49    println!("Files: {:#?}", form_data.files);
50
51    // Check each possible file field for compatibility with CLI and third-party tools
52    for field_name in ["media", "file", "upload"] {
53        // if the field is found to have data accept the file and save it
54        if let Some(files) = form_data.files.get(field_name) {
55            println!("Found files in field '{}': {:?}", field_name, files);
56
57            // Check if the file is valid, if so, process it
58            if let Some(file) = files.first() {
59                println!("Processing file:");
60                println!("  Path: {:?}", file.path);
61                println!("  Filename: {:?}", file.file_name);
62                println!("  Content-Type: {:?}", file.content_type);
63
64                let mut release_version = release_version.clone();
65
66                // Create App directory
67                if release_version.is_empty() {
68                    release_version = uuid::Uuid::new_v4().to_string();
69                }
70
71                // Handle the case where the directory does not exist
72                match fs::create_dir_all(format!("./Apps/{}/{}", app_id, release_version)) {
73                    Ok(_) => {
74                        let dir = std::path::PathBuf::from(format!(
75                            "./Apps/{}/{}",
76                            app_id, release_version
77                        ));
78                        let canon_dir = dir.canonicalize().unwrap();
79                        log::info!("Created Directory at {}", canon_dir.display())
80                    }
81                    Err(_) => {
82                        return Err::<Status, Status>(Status::new(500));
83                    }
84                }
85
86                // Copy file with size verification
87                let source_size = fs::metadata(&file.path)
88                    .map_err(|_| Err::<Status, Status>(Status::new(500)))
89                    .unwrap()
90                    .len();
91
92                println!("Source file size: {} bytes", source_size);
93
94                match fs::copy(
95                    &file.path,
96                    format!("./Apps/{}/{}/release.tar.gz", app_id, release_version),
97                ) {
98                    Ok(bytes_written) => {
99                        println!("Successfully wrote {} bytes", bytes_written);
100                        if bytes_written == source_size {
101                            return Ok(Status::new(200));
102                        } else {
103                            return Err(Status::new(500));
104                        }
105                    }
106                    Err(e) => {
107                        println!("Error copying file: {:?}", e);
108                        return Err(Status::new(500));
109                    }
110                }
111            } else {
112                println!("No valid file found in request");
113                return Err(Status::new(500));
114            }
115        }
116    }
117    Ok::<Status, Status>(Status::new(200))
118}