mirror of
https://codeberg.org/Toasterson/solstice-ci.git
synced 2026-04-10 13:20:41 +00:00
160 lines
5.1 KiB
Rust
160 lines
5.1 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use time::OffsetDateTime;
|
|
use uuid::Uuid;
|
|
|
|
/// Versioned internal job request schema published to the message bus.
|
|
/// Keep additions backward compatible; never reuse or repurpose existing fields.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct JobRequest {
|
|
/// Schema identifier for routing and evolution.
|
|
#[serde(default = "default_jobrequest_schema")]
|
|
pub schema_version: String, // e.g., "jobrequest.v1"
|
|
/// Unique request identifier for idempotency and tracing correlation.
|
|
pub request_id: Uuid,
|
|
/// Source system of this request (forge or manual trigger).
|
|
pub source: SourceSystem,
|
|
/// Repository clone URL (SSH or HTTPS).
|
|
pub repo_url: String,
|
|
/// Repository owner (parsed from webhook or URL); optional for backward-compat.
|
|
#[serde(default)]
|
|
pub repo_owner: Option<String>,
|
|
/// Repository name (parsed from webhook or URL); optional for backward-compat.
|
|
#[serde(default)]
|
|
pub repo_name: Option<String>,
|
|
/// Commit SHA to check out.
|
|
pub commit_sha: String,
|
|
/// Optional path to the workflow file within the repo (KDL).
|
|
pub workflow_path: Option<String>,
|
|
/// Optional specific job id from the workflow to run.
|
|
pub workflow_job_id: Option<String>,
|
|
/// Optional scheduling hint selecting a base image or host group.
|
|
pub runs_on: Option<String>,
|
|
/// Submission timestamp (UTC).
|
|
pub submitted_at: OffsetDateTime,
|
|
}
|
|
|
|
fn default_jobrequest_schema() -> String {
|
|
"jobrequest.v1".to_string()
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum SourceSystem {
|
|
Github,
|
|
Forgejo,
|
|
Manual,
|
|
}
|
|
|
|
impl JobRequest {
|
|
pub fn new(
|
|
source: SourceSystem,
|
|
repo_url: impl Into<String>,
|
|
commit_sha: impl Into<String>,
|
|
) -> Self {
|
|
Self {
|
|
schema_version: default_jobrequest_schema(),
|
|
request_id: Uuid::new_v4(),
|
|
source,
|
|
repo_url: repo_url.into(),
|
|
repo_owner: None,
|
|
repo_name: None,
|
|
commit_sha: commit_sha.into(),
|
|
workflow_path: None,
|
|
workflow_job_id: None,
|
|
runs_on: None,
|
|
submitted_at: OffsetDateTime::now_utc(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Final job result reported by the orchestrator back to the Integration layer over MQ.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct JobResult {
|
|
/// Schema identifier used as routing key/type. e.g., "jobresult.v1"
|
|
#[serde(default = "default_jobresult_schema")]
|
|
pub schema_version: String,
|
|
/// Correlates to the original JobRequest.request_id
|
|
pub request_id: Uuid,
|
|
/// Repository and commit info (for convenience in consumers)
|
|
pub repo_url: String,
|
|
/// Repository owner (when known). Optional for backward-compat.
|
|
#[serde(default)]
|
|
pub repo_owner: Option<String>,
|
|
/// Repository name (when known). Optional for backward-compat.
|
|
#[serde(default)]
|
|
pub repo_name: Option<String>,
|
|
pub commit_sha: String,
|
|
/// Outcome info
|
|
pub success: bool,
|
|
pub exit_code: i32,
|
|
/// Optional human summary
|
|
pub summary: Option<String>,
|
|
/// Completion timestamp
|
|
pub completed_at: OffsetDateTime,
|
|
}
|
|
|
|
fn default_jobresult_schema() -> String {
|
|
"jobresult.v1".to_string()
|
|
}
|
|
|
|
impl JobResult {
|
|
pub fn new(
|
|
request_id: Uuid,
|
|
repo_url: String,
|
|
commit_sha: String,
|
|
success: bool,
|
|
exit_code: i32,
|
|
summary: Option<String>,
|
|
) -> Self {
|
|
Self {
|
|
schema_version: default_jobresult_schema(),
|
|
request_id,
|
|
repo_url,
|
|
repo_owner: None,
|
|
repo_name: None,
|
|
commit_sha,
|
|
success,
|
|
exit_code,
|
|
summary,
|
|
completed_at: OffsetDateTime::now_utc(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Combined dead-letter message that includes the original JobRequest and
|
|
/// an error summary so operators/tooling can inspect both together.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct DeadLetter {
|
|
#[serde(default = "default_deadletter_schema")]
|
|
pub schema_version: String, // e.g., "deadletter.v1"
|
|
pub request_id: Uuid,
|
|
pub occurred_at: OffsetDateTime,
|
|
/// Stage where the failure occurred (e.g., "prepare", "start", "other").
|
|
pub stage: String,
|
|
/// Human-readable error summary (single-line preferred).
|
|
pub error: String,
|
|
/// Original job request that triggered the failure.
|
|
pub original: JobRequest,
|
|
/// Optional bag of extra diagnostic info.
|
|
#[serde(default)]
|
|
pub extra: Option<std::collections::BTreeMap<String, String>>,
|
|
}
|
|
|
|
fn default_deadletter_schema() -> String {
|
|
"deadletter.v1".to_string()
|
|
}
|
|
|
|
impl DeadLetter {
|
|
pub fn new(stage: impl Into<String>, error: impl Into<String>, original: JobRequest) -> Self {
|
|
let request_id = original.request_id;
|
|
Self {
|
|
schema_version: default_deadletter_schema(),
|
|
request_id,
|
|
occurred_at: OffsetDateTime::now_utc(),
|
|
stage: stage.into(),
|
|
error: error.into(),
|
|
original,
|
|
extra: None,
|
|
}
|
|
}
|
|
}
|