Skip to main content

opal/
history.rs

1use anyhow::{Context, Result};
2use serde::{Deserialize, Serialize};
3use std::fs;
4use std::path::Path;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct HistoryEntry {
8    pub run_id: String,
9    pub finished_at: String,
10    pub status: HistoryStatus,
11    pub jobs: Vec<HistoryJob>,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct HistoryJob {
16    pub name: String,
17    pub stage: String,
18    pub status: HistoryStatus,
19    pub log_hash: String,
20    #[serde(default)]
21    pub log_path: Option<String>,
22    #[serde(default)]
23    pub artifact_dir: Option<String>,
24    #[serde(default)]
25    pub artifacts: Vec<String>,
26    #[serde(default)]
27    pub caches: Vec<HistoryCache>,
28    #[serde(default)]
29    pub container_name: Option<String>,
30    #[serde(default)]
31    pub service_network: Option<String>,
32    #[serde(default)]
33    pub service_containers: Vec<String>,
34    #[serde(default)]
35    pub runtime_summary_path: Option<String>,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, Default)]
39pub struct HistoryCache {
40    pub key: String,
41    pub policy: String,
42    pub host: String,
43    #[serde(default)]
44    pub paths: Vec<String>,
45}
46
47#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
48pub enum HistoryStatus {
49    Success,
50    Failed,
51    Skipped,
52    Running,
53}
54
55pub fn load(path: &Path) -> Result<Vec<HistoryEntry>> {
56    if !path.exists() {
57        return Ok(Vec::new());
58    }
59    let contents =
60        fs::read_to_string(path).with_context(|| format!("failed to read {:?}", path))?;
61    let entries: Vec<HistoryEntry> = serde_json::from_str(&contents)
62        .with_context(|| format!("failed to parse history {:?}", path))?;
63    Ok(entries)
64}
65
66pub fn save(path: &Path, entries: &[HistoryEntry]) -> Result<()> {
67    let serialized =
68        serde_json::to_string_pretty(entries).context("failed to serialize history")?;
69    fs::write(path, serialized).with_context(|| format!("failed to write {:?}", path))
70}