mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-24 02:38:06 +02:00
Add OpenAPI spec generation via utoipa with /openapi.json endpoint
Integrate utoipa 5 to auto-generate an OpenAPI 3.1 spec from the existing Axum handlers and serde types. All 16 endpoints are annotated with path metadata, request/response schemas, security requirements, and tags. A public /openapi.json endpoint serves the spec without requiring auth. Includes 59 tests covering path completeness, HTTP methods, schema fields, enum variants, security scheme, path/query parameters, request bodies, response references, and endpoint integration. https://claude.ai/code/session_01NfoPVx21rZUQned1f7WpXY
This commit is contained in:
parent
e7658836a8
commit
859ec9faa8
6 changed files with 1199 additions and 31 deletions
|
|
@ -7,8 +7,25 @@ use omnigraph_compiler::SchemaMigrationStep;
|
|||
use omnigraph_compiler::result::QueryResult;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
/// Shadow enum for documenting [`LoadMode`] in the OpenAPI schema.
|
||||
#[derive(ToSchema)]
|
||||
#[schema(as = LoadMode)]
|
||||
#[allow(dead_code)]
|
||||
enum LoadModeSchema {
|
||||
/// Overwrite existing data.
|
||||
#[schema(rename = "overwrite")]
|
||||
Overwrite,
|
||||
/// Append to existing data.
|
||||
#[schema(rename = "append")]
|
||||
Append,
|
||||
/// Merge by id key (upsert).
|
||||
#[schema(rename = "merge")]
|
||||
Merge,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SnapshotTableOutput {
|
||||
pub table_key: String,
|
||||
pub table_path: String,
|
||||
|
|
@ -17,14 +34,14 @@ pub struct SnapshotTableOutput {
|
|||
pub row_count: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SnapshotOutput {
|
||||
pub branch: String,
|
||||
pub manifest_version: u64,
|
||||
pub tables: Vec<SnapshotTableOutput>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct RunOutput {
|
||||
pub run_id: String,
|
||||
pub target_branch: String,
|
||||
|
|
@ -39,18 +56,18 @@ pub struct RunOutput {
|
|||
pub updated_at: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct RunListOutput {
|
||||
pub runs: Vec<RunOutput>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct BranchCreateRequest {
|
||||
pub from: Option<String>,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct BranchCreateOutput {
|
||||
pub uri: String,
|
||||
pub from: String,
|
||||
|
|
@ -58,25 +75,25 @@ pub struct BranchCreateOutput {
|
|||
pub actor_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct BranchListOutput {
|
||||
pub branches: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct BranchDeleteOutput {
|
||||
pub uri: String,
|
||||
pub name: String,
|
||||
pub actor_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct BranchMergeRequest {
|
||||
pub source: String,
|
||||
pub target: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BranchMergeOutcome {
|
||||
AlreadyUpToDate,
|
||||
|
|
@ -104,7 +121,7 @@ impl BranchMergeOutcome {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct BranchMergeOutput {
|
||||
pub source: String,
|
||||
pub target: String,
|
||||
|
|
@ -112,7 +129,7 @@ pub struct BranchMergeOutput {
|
|||
pub actor_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum MergeConflictKindOutput {
|
||||
DivergentInsert,
|
||||
|
|
@ -152,7 +169,7 @@ impl From<MergeConflictKind> for MergeConflictKindOutput {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct MergeConflictOutput {
|
||||
pub table_key: String,
|
||||
pub row_id: Option<String>,
|
||||
|
|
@ -171,13 +188,13 @@ impl From<&MergeConflict> for MergeConflictOutput {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ReadTargetOutput {
|
||||
pub branch: Option<String>,
|
||||
pub snapshot: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ReadOutput {
|
||||
pub query_name: String,
|
||||
pub target: ReadTargetOutput,
|
||||
|
|
@ -187,7 +204,7 @@ pub struct ReadOutput {
|
|||
pub rows: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ChangeOutput {
|
||||
pub branch: String,
|
||||
pub query_name: String,
|
||||
|
|
@ -196,24 +213,25 @@ pub struct ChangeOutput {
|
|||
pub actor_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct IngestTableOutput {
|
||||
pub table_key: String,
|
||||
pub rows_loaded: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct IngestOutput {
|
||||
pub uri: String,
|
||||
pub branch: String,
|
||||
pub base_branch: String,
|
||||
pub branch_created: bool,
|
||||
#[schema(value_type = LoadModeSchema)]
|
||||
pub mode: LoadMode,
|
||||
pub tables: Vec<IngestTableOutput>,
|
||||
pub actor_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct CommitOutput {
|
||||
pub graph_commit_id: String,
|
||||
pub manifest_branch: Option<String>,
|
||||
|
|
@ -224,12 +242,12 @@ pub struct CommitOutput {
|
|||
pub created_at: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct CommitListOutput {
|
||||
pub commits: Vec<CommitOutput>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ReadRequest {
|
||||
pub query_source: String,
|
||||
pub query_name: Option<String>,
|
||||
|
|
@ -238,7 +256,7 @@ pub struct ReadRequest {
|
|||
pub snapshot: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ChangeRequest {
|
||||
pub query_source: String,
|
||||
pub query_name: Option<String>,
|
||||
|
|
@ -246,30 +264,32 @@ pub struct ChangeRequest {
|
|||
pub branch: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SchemaApplyRequest {
|
||||
pub schema_source: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SchemaApplyOutput {
|
||||
pub uri: String,
|
||||
pub supported: bool,
|
||||
pub applied: bool,
|
||||
pub step_count: usize,
|
||||
pub manifest_version: u64,
|
||||
#[schema(value_type = Vec<Value>)]
|
||||
pub steps: Vec<SchemaMigrationStep>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct IngestRequest {
|
||||
pub branch: Option<String>,
|
||||
pub from: Option<String>,
|
||||
#[schema(value_type = Option<LoadModeSchema>)]
|
||||
pub mode: Option<LoadMode>,
|
||||
pub data: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ExportRequest {
|
||||
pub branch: Option<String>,
|
||||
#[serde(default)]
|
||||
|
|
@ -278,17 +298,17 @@ pub struct ExportRequest {
|
|||
pub table_keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize, IntoParams)]
|
||||
pub struct SnapshotQuery {
|
||||
pub branch: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize, IntoParams)]
|
||||
pub struct CommitListQuery {
|
||||
pub branch: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct HealthOutput {
|
||||
pub status: String,
|
||||
pub version: String,
|
||||
|
|
@ -296,7 +316,7 @@ pub struct HealthOutput {
|
|||
pub source_version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ErrorCode {
|
||||
Unauthorized,
|
||||
|
|
@ -307,7 +327,7 @@ pub enum ErrorCode {
|
|||
Internal,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ErrorOutput {
|
||||
pub error: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
|
|
|||
|
|
@ -47,6 +47,50 @@ use tokio::sync::{RwLock, mpsc};
|
|||
use tower_http::trace::TraceLayer;
|
||||
use tracing::{error, info};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use utoipa::OpenApi;
|
||||
use utoipa::openapi::security::{Http, HttpAuthScheme, SecurityScheme};
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
info(
|
||||
title = "Omnigraph API",
|
||||
description = "HTTP API for the Omnigraph graph database",
|
||||
),
|
||||
paths(
|
||||
server_health,
|
||||
server_snapshot,
|
||||
server_read,
|
||||
server_export,
|
||||
server_change,
|
||||
server_schema_apply,
|
||||
server_ingest,
|
||||
server_branch_list,
|
||||
server_branch_create,
|
||||
server_branch_delete,
|
||||
server_branch_merge,
|
||||
server_run_list,
|
||||
server_run_show,
|
||||
server_run_publish,
|
||||
server_run_abort,
|
||||
server_commit_list,
|
||||
server_commit_show,
|
||||
),
|
||||
modifiers(&SecurityAddon),
|
||||
)]
|
||||
pub struct ApiDoc;
|
||||
|
||||
struct SecurityAddon;
|
||||
|
||||
impl utoipa::Modify for SecurityAddon {
|
||||
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
|
||||
if let Some(components) = openapi.components.as_mut() {
|
||||
components.add_security_scheme(
|
||||
"bearer_token",
|
||||
SecurityScheme::Http(Http::new(HttpAuthScheme::Bearer)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_REQUEST_BODY_LIMIT_BYTES: usize = 1_048_576;
|
||||
const INGEST_REQUEST_BODY_LIMIT_BYTES: usize = 32 * 1024 * 1024;
|
||||
|
|
@ -386,6 +430,7 @@ pub fn build_app(state: AppState) -> Router {
|
|||
|
||||
Router::new()
|
||||
.route("/healthz", get(server_health))
|
||||
.route("/openapi.json", get(server_openapi))
|
||||
.merge(protected)
|
||||
.layer(DefaultBodyLimit::max(DEFAULT_REQUEST_BODY_LIMIT_BYTES))
|
||||
.layer(TraceLayer::new_for_http())
|
||||
|
|
@ -415,6 +460,14 @@ async fn shutdown_signal() {
|
|||
info!("shutdown signal received");
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/healthz",
|
||||
tag = "health",
|
||||
responses(
|
||||
(status = 200, description = "Server is healthy", body = HealthOutput),
|
||||
),
|
||||
)]
|
||||
async fn server_health() -> Json<HealthOutput> {
|
||||
Json(HealthOutput {
|
||||
status: "ok".to_string(),
|
||||
|
|
@ -423,6 +476,10 @@ async fn server_health() -> Json<HealthOutput> {
|
|||
})
|
||||
}
|
||||
|
||||
async fn server_openapi() -> Json<utoipa::openapi::OpenApi> {
|
||||
Json(ApiDoc::openapi())
|
||||
}
|
||||
|
||||
async fn require_bearer_auth(
|
||||
State(state): State<AppState>,
|
||||
mut request: Request,
|
||||
|
|
@ -486,6 +543,18 @@ fn authorize_request(
|
|||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/snapshot",
|
||||
tag = "snapshots",
|
||||
params(SnapshotQuery),
|
||||
responses(
|
||||
(status = 200, description = "Database snapshot", body = api::SnapshotOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_snapshot(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -514,6 +583,19 @@ async fn server_snapshot(
|
|||
Ok(Json(snapshot_payload(&branch, &snapshot)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/read",
|
||||
tag = "queries",
|
||||
request_body = ReadRequest,
|
||||
responses(
|
||||
(status = 200, description = "Query results", body = ReadOutput),
|
||||
(status = 400, description = "Bad request", body = ErrorOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_read(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -570,6 +652,19 @@ async fn server_read(
|
|||
Ok(Json(api::read_output(selected_name, &target, result)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/export",
|
||||
tag = "queries",
|
||||
request_body = ExportRequest,
|
||||
responses(
|
||||
(status = 200, description = "Exported data as NDJSON", content_type = "application/x-ndjson"),
|
||||
(status = 400, description = "Bad request", body = ErrorOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_export(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -615,6 +710,20 @@ async fn server_export(
|
|||
.into_response())
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/change",
|
||||
tag = "mutations",
|
||||
request_body = ChangeRequest,
|
||||
responses(
|
||||
(status = 200, description = "Mutation results", body = ChangeOutput),
|
||||
(status = 400, description = "Bad request", body = ErrorOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 409, description = "Merge conflict", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_change(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -659,6 +768,19 @@ async fn server_change(
|
|||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/schema/apply",
|
||||
tag = "mutations",
|
||||
request_body = SchemaApplyRequest,
|
||||
responses(
|
||||
(status = 200, description = "Schema apply results", body = SchemaApplyOutput),
|
||||
(status = 400, description = "Bad request", body = ErrorOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_schema_apply(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -684,6 +806,19 @@ async fn server_schema_apply(
|
|||
Ok(Json(schema_apply_output(state.uri(), result)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/ingest",
|
||||
tag = "mutations",
|
||||
request_body = IngestRequest,
|
||||
responses(
|
||||
(status = 200, description = "Ingest results", body = IngestOutput),
|
||||
(status = 400, description = "Bad request", body = ErrorOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_ingest(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -740,6 +875,17 @@ async fn server_ingest(
|
|||
)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/branches",
|
||||
tag = "branches",
|
||||
responses(
|
||||
(status = 200, description = "List of branches", body = BranchListOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_branch_list(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -765,6 +911,20 @@ async fn server_branch_list(
|
|||
Ok(Json(BranchListOutput { branches }))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/branches",
|
||||
tag = "branches",
|
||||
request_body = BranchCreateRequest,
|
||||
responses(
|
||||
(status = 200, description = "Branch created", body = BranchCreateOutput),
|
||||
(status = 400, description = "Bad request", body = ErrorOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 409, description = "Branch already exists", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_branch_create(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -798,6 +958,21 @@ async fn server_branch_create(
|
|||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
path = "/branches/{branch}",
|
||||
tag = "branches",
|
||||
params(
|
||||
("branch" = String, Path, description = "Branch name to delete"),
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Branch deleted", body = BranchDeleteOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 404, description = "Branch not found", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_branch_delete(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -827,6 +1002,20 @@ async fn server_branch_delete(
|
|||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/branches/merge",
|
||||
tag = "branches",
|
||||
request_body = BranchMergeRequest,
|
||||
responses(
|
||||
(status = 200, description = "Branches merged", body = BranchMergeOutput),
|
||||
(status = 400, description = "Bad request", body = ErrorOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 409, description = "Merge conflict", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_branch_merge(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -858,6 +1047,17 @@ async fn server_branch_merge(
|
|||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/runs",
|
||||
tag = "runs",
|
||||
responses(
|
||||
(status = 200, description = "List of runs", body = RunListOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_run_list(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -884,6 +1084,21 @@ async fn server_run_list(
|
|||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/runs/{run_id}",
|
||||
tag = "runs",
|
||||
params(
|
||||
("run_id" = String, Path, description = "Run identifier"),
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Run details", body = api::RunOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 404, description = "Run not found", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_run_show(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -911,6 +1126,21 @@ async fn server_run_show(
|
|||
Ok(Json(api::run_output(&run)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/runs/{run_id}/publish",
|
||||
tag = "runs",
|
||||
params(
|
||||
("run_id" = String, Path, description = "Run identifier"),
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Run published", body = api::RunOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 404, description = "Run not found", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_run_publish(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -945,6 +1175,21 @@ async fn server_run_publish(
|
|||
Ok(Json(api::run_output(&run)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/runs/{run_id}/abort",
|
||||
tag = "runs",
|
||||
params(
|
||||
("run_id" = String, Path, description = "Run identifier"),
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Run aborted", body = api::RunOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 404, description = "Run not found", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_run_abort(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -978,6 +1223,18 @@ async fn server_run_abort(
|
|||
Ok(Json(api::run_output(&run)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/commits",
|
||||
tag = "commits",
|
||||
params(CommitListQuery),
|
||||
responses(
|
||||
(status = 200, description = "List of commits", body = CommitListOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_commit_list(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
@ -1007,6 +1264,21 @@ async fn server_commit_list(
|
|||
}))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/commits/{commit_id}",
|
||||
tag = "commits",
|
||||
params(
|
||||
("commit_id" = String, Path, description = "Commit identifier"),
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Commit details", body = api::CommitOutput),
|
||||
(status = 401, description = "Unauthorized", body = ErrorOutput),
|
||||
(status = 403, description = "Forbidden", body = ErrorOutput),
|
||||
(status = 404, description = "Commit not found", body = ErrorOutput),
|
||||
),
|
||||
security(("bearer_token" = [])),
|
||||
)]
|
||||
async fn server_commit_show(
|
||||
State(state): State<AppState>,
|
||||
actor: Option<Extension<AuthenticatedActor>>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue