#![cfg_attr(coverage_nightly, coverage(off))]
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::Path;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TdgHooksConfig {
#[serde(default)]
pub quality_gates: QualityGatesConfig,
#[serde(default)]
pub baseline: BaselineConfig,
#[serde(default)]
pub ci_cd: CiCdConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QualityGatesConfig {
#[serde(default)]
pub min_grades: HashMap<String, String>,
#[serde(default)]
pub rust_min_grade: Option<String>,
#[serde(default)]
pub typescript_min_grade: Option<String>,
#[serde(default)]
pub python_min_grade: Option<String>,
#[serde(default = "default_max_score_drop")]
pub max_score_drop: f32,
#[serde(default)]
pub allow_grade_drop: bool,
#[serde(default = "default_mode")]
pub mode: EnforcementMode,
#[serde(default = "default_true")]
pub block_on_regression: bool,
#[serde(default = "default_true")]
pub block_on_new_files_below_threshold: bool,
}
impl Default for QualityGatesConfig {
fn default() -> Self {
let mut min_grades = HashMap::new();
min_grades.insert("rust".to_string(), "B+".to_string());
min_grades.insert("typescript".to_string(), "B+".to_string());
min_grades.insert("python".to_string(), "B".to_string());
Self {
min_grades,
rust_min_grade: Some("B+".to_string()),
typescript_min_grade: Some("B+".to_string()),
python_min_grade: Some("B".to_string()),
max_score_drop: 5.0,
allow_grade_drop: false,
mode: EnforcementMode::Strict,
block_on_regression: true,
block_on_new_files_below_threshold: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BaselineConfig {
#[serde(default = "default_true")]
pub auto_update_on_commit: bool,
#[serde(default = "default_true")]
pub auto_update_on_merge: bool,
#[serde(default = "default_baseline_path")]
pub baseline_path: String,
#[serde(default = "default_true")]
pub store_in_git: bool,
}
impl Default for BaselineConfig {
fn default() -> Self {
Self {
auto_update_on_commit: true,
auto_update_on_merge: true,
baseline_path: ".pmat/baseline.json".to_string(),
store_in_git: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CiCdConfig {
#[serde(default)]
pub fail_fast: bool,
#[serde(default = "default_true")]
pub generate_reports: bool,
#[serde(default = "default_true")]
pub comment_on_pr: bool,
}
impl Default for CiCdConfig {
fn default() -> Self {
Self {
fail_fast: false,
generate_reports: true,
comment_on_pr: true,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum EnforcementMode {
#[default]
Strict,
Warning,
Disabled,
}
fn default_max_score_drop() -> f32 {
5.0
}
fn default_mode() -> EnforcementMode {
EnforcementMode::Strict
}
fn default_true() -> bool {
true
}
fn default_baseline_path() -> String {
".pmat/baseline.json".to_string()
}
include!("hooks_config_operations.rs");
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
include!("hooks_config_tests.rs");
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
include!("hooks_config_tests_property.rs");
}