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",
)
crate.spec(
features = ["v4"],
package = "uuid",
version = "1.0",
features = ["v4"],
)
crate.spec(
features = ["bundled"],
package = "rusqlite",
version = "0.31",
features = ["bundled"],
)
crate.spec(
features = ["derive"],
package = "clap",
version = "4.0",
features = ["derive"],
)
crate.spec(
package = "axum",
version = "0.7",
features = ["json"],
package = "axum",
version = "0.7.2",
)
crate.spec(
package = "tower",
version = "0.4",
)
crate.spec(
features = ["cors"],
package = "tower-http",
version = "0.5",
features = ["cors"],
)
crate.spec(
features = ["full"],
package = "hyper",
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()
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",
visibility = ["//visibility:public"],
deps = [
"@crates//:aide",
"@crates//:axum",
"@crates//:axum-jsonschema",
"@crates//:log",
"@crates//:prost",
"@crates//:prost-types",
"@crates//:rusqlite",
"@crates//:schemars",
"@crates//:serde",
"@crates//:serde_json",
"@crates//:tokio",
@ -69,11 +72,14 @@ rust_binary(
visibility = ["//visibility:public"],
deps = [
":databuild",
"@crates//:aide",
"@crates//:axum",
"@crates//:axum-jsonschema",
"@crates//:tokio",
"@crates//:tower",
"@crates//:tower-http",
"@crates//:hyper",
"@crates//:schemars",
"@crates//:serde",
"@crates//:serde_json",
"@crates//:log",

View file

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

View file

@ -1,10 +1,16 @@
use crate::*;
use crate::event_log::{BuildEventLog, BuildEventLogError, create_build_event_log};
use axum::{
routing::{get, post, delete},
Router,
use aide::{
axum::{
routing::{get, post, delete},
ApiRouter,
},
openapi::OpenApi,
};
use axum::Extension;
use axum_jsonschema::Json;
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
@ -31,17 +37,17 @@ pub struct BuildRequestState {
pub updated_at: i64,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildRequest {
pub partitions: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildRequestResponse {
pub build_request_id: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildStatusResponse {
pub build_request_id: String,
pub status: String,
@ -51,7 +57,7 @@ pub struct BuildStatusResponse {
pub events: Vec<BuildEventSummary>,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BuildEventSummary {
pub event_id: String,
pub timestamp: i64,
@ -59,7 +65,7 @@ pub struct BuildEventSummary {
pub message: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct PartitionStatusResponse {
pub partition_ref: String,
pub status: String,
@ -67,23 +73,23 @@ pub struct PartitionStatusResponse {
pub build_requests: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct PartitionEventsResponse {
pub partition_ref: String,
pub events: Vec<BuildEventSummary>,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct AnalyzeRequest {
pub partitions: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct AnalyzeResponse {
pub job_graph: serde_json::Value,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct ErrorResponse {
pub error: String,
}
@ -107,15 +113,50 @@ impl BuildGraphService {
})
}
pub fn create_router(self) -> Router {
Router::new()
.route("/api/v1/builds", post(handlers::submit_build_request))
.route("/api/v1/builds/:id", get(handlers::get_build_status))
.route("/api/v1/builds/:id", delete(handlers::cancel_build_request))
.route("/api/v1/partitions/:ref/status", get(handlers::get_partition_status))
.route("/api/v1/partitions/:ref/events", get(handlers::get_partition_events))
.route("/api/v1/analyze", post(handlers::analyze_build_graph))
pub fn create_router(self) -> axum::Router {
let mut api = OpenApi::default();
let router = ApiRouter::new()
.api_route("/api/v1/builds", post(handlers::submit_build_request))
.api_route("/api/v1/builds/{id}", get(handlers::get_build_status))
.api_route("/api/v1/builds/{id}", delete(handlers::cancel_build_request))
.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))
.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 {

View file

@ -1 +0,0 @@
34