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, /// Commit SHA to check out. pub commit_sha: String, /// Optional path to the workflow file within the repo (KDL). pub workflow_path: Option, /// Optional specific job id from the workflow to run. pub workflow_job_id: Option, /// Optional scheduling hint selecting a base image or host group. pub runs_on: Option, /// 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, commit_sha: impl Into) -> Self { Self { schema_version: default_jobrequest_schema(), request_id: Uuid::new_v4(), source, repo_url: repo_url.into(), 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, pub commit_sha: String, /// Outcome info pub success: bool, pub exit_code: i32, /// Optional human summary pub summary: Option, /// 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) -> Self { Self { schema_version: default_jobresult_schema(), request_id, repo_url, commit_sha, success, exit_code, summary, completed_at: OffsetDateTime::now_utc(), } } }