Skip to main content

dockerfile_roast/
baseline.rs

1use crate::output::finding_fingerprint;
2use crate::rules::Finding;
3use anyhow::{Context, Result};
4use serde::{Deserialize, Serialize};
5use std::collections::BTreeSet;
6use std::path::Path;
7
8#[derive(Debug, Deserialize, Serialize)]
9struct BaselineDocument {
10    schema_version: u32,
11    fingerprints: BTreeSet<String>,
12}
13
14pub fn load(path: &Path) -> Result<BTreeSet<String>> {
15    let content = std::fs::read_to_string(path)
16        .with_context(|| format!("Failed to read baseline '{}'", path.display()))?;
17    let document: BaselineDocument = serde_json::from_str(&content)
18        .with_context(|| format!("Baseline '{}' is not valid JSON", path.display()))?;
19    if document.schema_version != 1 {
20        anyhow::bail!("Baseline '{}' uses unsupported schema version {}", path.display(), document.schema_version);
21    }
22    Ok(document.fingerprints)
23}
24
25pub fn write(path: &Path, results: &[(&str, &[Finding])]) -> Result<()> {
26    let fingerprints = results
27        .iter()
28        .flat_map(|(file, findings)| findings.iter().map(move |finding| finding_fingerprint(file, finding)))
29        .collect();
30    let document = BaselineDocument { schema_version: 1, fingerprints };
31    let content = format!("{}\n", serde_json::to_string_pretty(&document)?);
32    std::fs::write(path, content)
33        .with_context(|| format!("Failed to write baseline '{}'", path.display()))
34}
35
36pub fn contains(fingerprints: &BTreeSet<String>, file: &str, finding: &Finding) -> bool {
37    fingerprints.contains(&finding_fingerprint(file, finding))
38}