use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
pub const REPLAY_MANIFEST_SCHEMA_VERSION: u32 = 1;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReplayManifest {
pub schema_version: u32,
pub assay_version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_run_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub selection_method: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub git_sha: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub git_dirty: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub workflow_run_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub config_digest: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub policy_digest: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub baseline_digest: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub trace_digest: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub trace_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub outputs: Option<ReplayOutputs>,
#[serde(skip_serializing_if = "Option::is_none")]
pub toolchain: Option<ToolchainMeta>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seeds: Option<ReplaySeeds>,
#[serde(skip_serializing_if = "Option::is_none")]
pub replay_coverage: Option<ReplayCoverage>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scrub_policy: Option<ScrubPolicy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub files: Option<BTreeMap<String, FileManifestEntry>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub env: Option<BTreeMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReplayOutputs {
#[serde(skip_serializing_if = "Option::is_none")]
pub run: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub junit: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sarif: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolchainMeta {
#[serde(skip_serializing_if = "Option::is_none")]
pub rustc: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cargo: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cargo_lock_hash: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub runner: Option<RunnerMeta>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RunnerMeta {
#[serde(skip_serializing_if = "Option::is_none")]
pub os: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub arch: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub container_image_digest: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ci: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReplaySeeds {
#[serde(skip_serializing_if = "Option::is_none")]
pub seed_version: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub order_seed: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub judge_seed: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReplayCoverage {
pub complete_tests: Vec<String>,
pub incomplete_tests: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<BTreeMap<String, String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScrubPolicy {
#[serde(skip_serializing_if = "Option::is_none")]
pub include_prompts: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scrub_cassettes: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
}
impl Default for ScrubPolicy {
fn default() -> Self {
Self {
include_prompts: Some(false),
scrub_cassettes: Some(true),
name: Some("default".into()),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileManifestEntry {
pub sha256: String,
pub size: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub content_type: Option<String>,
}
impl ReplayManifest {
pub fn minimal(assay_version: String) -> Self {
Self {
schema_version: REPLAY_MANIFEST_SCHEMA_VERSION,
assay_version,
created_at: None,
source_run_path: None,
selection_method: None,
git_sha: None,
git_dirty: None,
workflow_run_id: None,
config_digest: None,
policy_digest: None,
baseline_digest: None,
trace_digest: None,
trace_path: None,
outputs: None,
toolchain: None,
seeds: None,
replay_coverage: None,
scrub_policy: Some(ScrubPolicy::default()),
files: None,
env: None,
}
}
}