zlayer_types/api/syncs.rs
1//! Sync DTOs.
2//!
3//! Wire types for the sync CRUD + diff/apply endpoints. A sync resource
4//! points at a directory within a project's git checkout that contains
5//! `ZLayer` resource YAMLs. The diff endpoint scans the directory and
6//! reports what would change; the apply endpoint actually reconciles.
7
8use serde::{Deserialize, Serialize};
9use utoipa::ToSchema;
10
11/// Body for `POST /api/v1/syncs`.
12#[derive(Debug, Serialize, Deserialize, ToSchema)]
13pub struct CreateSyncRequest {
14 /// Display name for this sync.
15 pub name: String,
16 /// Linked project id.
17 #[serde(default)]
18 pub project_id: Option<String>,
19 /// Path within the project's checkout to scan for resource YAMLs.
20 pub git_path: String,
21 /// Whether the sync should automatically apply on pull.
22 #[serde(default)]
23 pub auto_apply: Option<bool>,
24 /// Whether `apply` should delete resources on the API that are missing
25 /// from the manifest directory. Defaults to `false` (the safer choice).
26 #[serde(default)]
27 pub delete_missing: Option<bool>,
28}
29
30/// Result of reconciling a single resource during apply.
31#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
32pub struct SyncResourceResult {
33 /// The source manifest path (or remote resource name for deletions).
34 pub resource: String,
35 /// Resource kind: `"deployment"`, `"job"`, `"cron"`, or other.
36 pub kind: String,
37 /// Action taken: `"create"`, `"update"`, `"delete"`, or `"skip"`.
38 pub action: String,
39 /// Outcome status: `"ok"` or `"error"`.
40 pub status: String,
41 /// Optional error message (`status == "error"`) or skip reason
42 /// (`action == "skip"`). Omitted on successful `"ok"` results.
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub error: Option<String>,
45}
46
47impl SyncResourceResult {
48 /// Build a successful result for the given resource/kind/action.
49 #[must_use]
50 pub fn ok(resource: &str, kind: &str, action: &str) -> Self {
51 Self {
52 resource: resource.to_string(),
53 kind: kind.to_string(),
54 action: action.to_string(),
55 status: "ok".to_string(),
56 error: None,
57 }
58 }
59
60 /// Build an error result with a human-readable message.
61 #[must_use]
62 pub fn err(resource: &str, kind: &str, action: &str, message: String) -> Self {
63 Self {
64 resource: resource.to_string(),
65 kind: kind.to_string(),
66 action: action.to_string(),
67 status: "error".to_string(),
68 error: Some(message),
69 }
70 }
71
72 /// Build a skip result with a reason recorded in `error`.
73 #[must_use]
74 pub fn skip(resource: &str, kind: &str, message: String) -> Self {
75 Self {
76 resource: resource.to_string(),
77 kind: kind.to_string(),
78 action: "skip".to_string(),
79 status: "ok".to_string(),
80 error: Some(message),
81 }
82 }
83}
84
85/// Response for a real apply. Reports per-resource outcomes, the current
86/// commit SHA the sync was applied at (when known), and a short human-readable
87/// summary for CLI display.
88///
89/// NOTE: This is a breaking change from the previous dry-run-only
90/// `{ diff, message }` shape. Clients inspecting the apply response directly
91/// must be updated — callers that only consumed the HTTP status stay working.
92#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
93pub struct SyncApplyResponse {
94 /// Per-resource reconcile results.
95 pub results: Vec<SyncResourceResult>,
96 /// Commit SHA the sync was applied against (when resolvable).
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub applied_sha: Option<String>,
99 /// Aggregate summary suitable for CLI output, e.g.
100 /// `"3 created, 2 updated, 1 deleted, 0 skipped"`.
101 pub summary: String,
102}
103
104/// JSON-friendly wrapper around the sync diff output.
105#[derive(Debug, Serialize, Deserialize, ToSchema)]
106pub struct SyncDiffResponse {
107 /// Resources to create.
108 pub to_create: Vec<SyncResourceResponse>,
109 /// Resources to update.
110 pub to_update: Vec<SyncResourceResponse>,
111 /// Resource names to delete.
112 pub to_delete: Vec<String>,
113}
114
115/// A single resource in the diff output.
116#[derive(Debug, Serialize, Deserialize, ToSchema)]
117pub struct SyncResourceResponse {
118 /// Source file name.
119 pub file_path: String,
120 /// Resource kind.
121 pub kind: String,
122 /// Resource name.
123 pub name: String,
124}