This commit is contained in:
Stuart Axelbrooke 2025-07-08 21:00:50 -07:00
parent d1d1f2c8b6
commit 232e0583f2
6 changed files with 1139 additions and 51 deletions

View file

@ -71,38 +71,56 @@ crate.spec(
version = "0.1", version = "0.1",
) )
crate.spec( crate.spec(
features = ["v4"],
package = "uuid", package = "uuid",
version = "1.0", version = "1.0",
features = ["v4"],
) )
crate.spec( crate.spec(
features = ["bundled"],
package = "rusqlite", package = "rusqlite",
version = "0.31", version = "0.31",
features = ["bundled"],
) )
crate.spec( crate.spec(
features = ["derive"],
package = "clap", package = "clap",
version = "4.0", version = "4.0",
features = ["derive"],
) )
crate.spec( crate.spec(
package = "axum",
version = "0.7",
features = ["json"], features = ["json"],
package = "axum",
version = "0.7.2",
) )
crate.spec( crate.spec(
package = "tower", package = "tower",
version = "0.4", version = "0.4",
) )
crate.spec( crate.spec(
features = ["cors"],
package = "tower-http", package = "tower-http",
version = "0.5", version = "0.5",
features = ["cors"],
) )
crate.spec( crate.spec(
features = ["full"],
package = "hyper", package = "hyper",
version = "1.0", version = "1.0",
features = ["full"], )
crate.spec(
features = ["axum"],
package = "aide",
version = "0.13.0",
)
crate.spec(
features = [
"uuid1",
"derive",
],
package = "schemars",
version = "0.8.16",
)
crate.spec(
features = ["aide"],
package = "axum-jsonschema",
version = "0.8.0",
) )
crate.from_specs() crate.from_specs()
use_repo(crate, "crates") use_repo(crate, "crates")

File diff suppressed because one or more lines are too long

View file

@ -46,11 +46,14 @@ rust_library(
edition = "2021", edition = "2021",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"@crates//:aide",
"@crates//:axum", "@crates//:axum",
"@crates//:axum-jsonschema",
"@crates//:log", "@crates//:log",
"@crates//:prost", "@crates//:prost",
"@crates//:prost-types", "@crates//:prost-types",
"@crates//:rusqlite", "@crates//:rusqlite",
"@crates//:schemars",
"@crates//:serde", "@crates//:serde",
"@crates//:serde_json", "@crates//:serde_json",
"@crates//:tokio", "@crates//:tokio",
@ -69,11 +72,14 @@ rust_binary(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":databuild", ":databuild",
"@crates//:aide",
"@crates//:axum", "@crates//:axum",
"@crates//:axum-jsonschema",
"@crates//:tokio", "@crates//:tokio",
"@crates//:tower", "@crates//:tower",
"@crates//:tower-http", "@crates//:tower-http",
"@crates//:hyper", "@crates//:hyper",
"@crates//:schemars",
"@crates//:serde", "@crates//:serde",
"@crates//:serde_json", "@crates//:serde_json",
"@crates//:log", "@crates//:log",

View file

@ -3,8 +3,8 @@ use crate::event_log::{current_timestamp_nanos, create_build_event};
use axum::{ use axum::{
extract::{Path, State}, extract::{Path, State},
http::StatusCode, http::StatusCode,
response::Json,
}; };
use axum_jsonschema::Json;
use log::{error, info}; use log::{error, info};
use std::process::Command; use std::process::Command;
use std::env; use std::env;

View file

@ -1,10 +1,16 @@
use crate::*; use crate::*;
use crate::event_log::{BuildEventLog, BuildEventLogError, create_build_event_log}; use crate::event_log::{BuildEventLog, BuildEventLogError, create_build_event_log};
use axum::{ use aide::{
routing::{get, post, delete}, axum::{
Router, routing::{get, post, delete},
ApiRouter,
},
openapi::OpenApi,
}; };
use axum::Extension;
use axum_jsonschema::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use schemars::JsonSchema;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
@ -31,17 +37,17 @@ pub struct BuildRequestState {
pub updated_at: i64, pub updated_at: i64,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildRequest { pub struct BuildRequest {
pub partitions: Vec<String>, pub partitions: Vec<String>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildRequestResponse { pub struct BuildRequestResponse {
pub build_request_id: String, pub build_request_id: String,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildStatusResponse { pub struct BuildStatusResponse {
pub build_request_id: String, pub build_request_id: String,
pub status: String, pub status: String,
@ -51,7 +57,7 @@ pub struct BuildStatusResponse {
pub events: Vec<BuildEventSummary>, pub events: Vec<BuildEventSummary>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildEventSummary { pub struct BuildEventSummary {
pub event_id: String, pub event_id: String,
pub timestamp: i64, pub timestamp: i64,
@ -59,7 +65,7 @@ pub struct BuildEventSummary {
pub message: String, pub message: String,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct PartitionStatusResponse { pub struct PartitionStatusResponse {
pub partition_ref: String, pub partition_ref: String,
pub status: String, pub status: String,
@ -67,23 +73,23 @@ pub struct PartitionStatusResponse {
pub build_requests: Vec<String>, pub build_requests: Vec<String>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct PartitionEventsResponse { pub struct PartitionEventsResponse {
pub partition_ref: String, pub partition_ref: String,
pub events: Vec<BuildEventSummary>, pub events: Vec<BuildEventSummary>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct AnalyzeRequest { pub struct AnalyzeRequest {
pub partitions: Vec<String>, pub partitions: Vec<String>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct AnalyzeResponse { pub struct AnalyzeResponse {
pub job_graph: serde_json::Value, pub job_graph: serde_json::Value,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct ErrorResponse { pub struct ErrorResponse {
pub error: String, pub error: String,
} }
@ -107,15 +113,50 @@ impl BuildGraphService {
}) })
} }
pub fn create_router(self) -> Router { pub fn create_router(self) -> axum::Router {
Router::new() let mut api = OpenApi::default();
.route("/api/v1/builds", post(handlers::submit_build_request))
.route("/api/v1/builds/:id", get(handlers::get_build_status)) let router = ApiRouter::new()
.route("/api/v1/builds/:id", delete(handlers::cancel_build_request)) .api_route("/api/v1/builds", post(handlers::submit_build_request))
.route("/api/v1/partitions/:ref/status", get(handlers::get_partition_status)) .api_route("/api/v1/builds/{id}", get(handlers::get_build_status))
.route("/api/v1/partitions/:ref/events", get(handlers::get_partition_events)) .api_route("/api/v1/builds/{id}", delete(handlers::cancel_build_request))
.route("/api/v1/analyze", post(handlers::analyze_build_graph)) .api_route("/api/v1/partitions/{ref}/status", get(handlers::get_partition_status))
.api_route("/api/v1/partitions/{ref}/events", get(handlers::get_partition_events))
.api_route("/api/v1/analyze", post(handlers::analyze_build_graph))
.route("/api/v1/openapi.json", get(Self::openapi_spec))
.with_state(Arc::new(self)) .with_state(Arc::new(self))
.finish_api(&mut api);
router
.layer(Extension(api))
.layer(axum::middleware::from_fn(Self::cors_middleware))
}
pub async fn openapi_spec(Extension(api): Extension<OpenApi>) -> Json<OpenApi> {
Json(api)
}
pub async fn cors_middleware(
request: axum::http::Request<axum::body::Body>,
next: axum::middleware::Next,
) -> axum::response::Response {
let response = next.run(request).await;
let (mut parts, body) = response.into_parts();
parts.headers.insert(
axum::http::header::ACCESS_CONTROL_ALLOW_ORIGIN,
axum::http::HeaderValue::from_static("*"),
);
parts.headers.insert(
axum::http::header::ACCESS_CONTROL_ALLOW_METHODS,
axum::http::HeaderValue::from_static("GET, POST, DELETE, OPTIONS"),
);
parts.headers.insert(
axum::http::header::ACCESS_CONTROL_ALLOW_HEADERS,
axum::http::HeaderValue::from_static("Content-Type, Authorization"),
);
axum::response::Response::from_parts(parts, body)
} }
pub fn generate_build_request_id() -> String { pub fn generate_build_request_id() -> String {

View file

@ -1 +0,0 @@
34