cuenv_ci/flake/
error.rs

1//! Error types for flake.lock parsing and purity analysis
2
3use miette::Diagnostic;
4use std::path::PathBuf;
5use thiserror::Error;
6
7/// Errors related to flake.lock parsing and purity analysis
8#[derive(Debug, Error, Diagnostic)]
9pub enum FlakeLockError {
10    /// Failed to parse flake.lock JSON
11    #[error("Failed to parse flake.lock: {0}")]
12    #[diagnostic(
13        code(cuenv::ci::flake::parse),
14        help("Ensure flake.lock is valid JSON and follows Nix flake.lock schema v7")
15    )]
16    ParseError(String),
17
18    /// Failed to read flake.lock file
19    #[error("Failed to read flake.lock at {path}: {message}")]
20    #[diagnostic(
21        code(cuenv::ci::flake::io),
22        help("Check that flake.lock exists and is readable")
23    )]
24    IoError {
25        /// Path to the flake.lock file
26        path: PathBuf,
27        /// Error message
28        message: String,
29    },
30
31    /// Flake purity check failed in strict mode
32    #[error("Flake purity check failed with {count} unlocked input(s): {}", inputs.join(", "))]
33    #[diagnostic(
34        code(cuenv::ci::flake::impure_strict),
35        help(
36            "In strict mode, all flake inputs must be locked. Run 'nix flake lock' to fix, or use purity_mode: warning/override"
37        )
38    )]
39    StrictModeViolation {
40        /// Number of unlocked inputs
41        count: usize,
42        /// Names of unlocked inputs
43        inputs: Vec<String>,
44    },
45
46    /// Missing flake.lock file
47    #[error("No flake.lock file found at {path}")]
48    #[diagnostic(
49        code(cuenv::ci::flake::missing),
50        help("Run 'nix flake lock' to generate a flake.lock file")
51    )]
52    MissingLockFile {
53        /// Expected path to the flake.lock file
54        path: PathBuf,
55    },
56}
57
58impl FlakeLockError {
59    /// Create a parse error
60    #[must_use]
61    pub fn parse(message: impl Into<String>) -> Self {
62        Self::ParseError(message.into())
63    }
64
65    /// Create an IO error
66    #[must_use]
67    pub fn io(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
68        Self::IoError {
69            path: path.into(),
70            message: message.into(),
71        }
72    }
73
74    /// Create a strict mode violation error
75    #[must_use]
76    pub fn strict_violation(inputs: Vec<String>) -> Self {
77        Self::StrictModeViolation {
78            count: inputs.len(),
79            inputs,
80        }
81    }
82
83    /// Create a missing lock file error
84    #[must_use]
85    pub fn missing(path: impl Into<PathBuf>) -> Self {
86        Self::MissingLockFile { path: path.into() }
87    }
88}