pub type PipelineResult<T> = Result<T, PipelineError>;
#[derive(Debug, Clone, PartialEq)]
pub enum PipelineError {
GitError { reason: String },
BenchmarkFailed { reason: String },
BaselineNotFound { commit: String },
InvalidConfig { reason: String },
Timeout { timeout_sec: u64 },
StatusUpdateFailed { reason: String },
ArtifactError { reason: String },
}
impl std::fmt::Display for PipelineError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::GitError { reason } => write!(f, "Git error: {}", reason),
Self::BenchmarkFailed { reason } => write!(f, "Benchmark failed: {}", reason),
Self::BaselineNotFound { commit } => write!(f, "Baseline not found for {}", commit),
Self::InvalidConfig { reason } => write!(f, "Invalid config: {}", reason),
Self::Timeout { timeout_sec } => write!(f, "Timeout after {}s", timeout_sec),
Self::StatusUpdateFailed { reason } => write!(f, "Status update failed: {}", reason),
Self::ArtifactError { reason } => write!(f, "Artifact error: {}", reason),
}
}
}
impl std::error::Error for PipelineError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PipelineStatus {
Pending,
Running,
Passed,
Warning,
Failed,
Cancelled,
Error,
}
impl PipelineStatus {
pub fn is_terminal(&self) -> bool {
matches!(
self,
Self::Passed | Self::Warning | Self::Failed | Self::Cancelled | Self::Error
)
}
pub fn github_state(&self) -> &'static str {
match self {
Self::Pending => "pending",
Self::Running => "pending",
Self::Passed => "success",
Self::Warning => "success",
Self::Failed => "failure",
Self::Cancelled => "error",
Self::Error => "error",
}
}
}
#[derive(Debug, Clone)]
pub enum GitRef {
Branch(String),
Commit(String),
Tag(String),
PullRequest(u64),
}
impl GitRef {
pub fn as_ref_str(&self) -> String {
match self {
Self::Branch(name) => name.clone(),
Self::Commit(sha) => sha.clone(),
Self::Tag(name) => format!("refs/tags/{}", name),
Self::PullRequest(num) => format!("refs/pull/{}/head", num),
}
}
}
#[derive(Debug, Clone)]
pub struct PipelineConfig {
pub base_branch: String,
pub benchmark_command: String,
pub work_dir: String,
pub timeout_sec: u64,
pub regression_threshold_percent: f64,
pub warning_threshold_percent: f64,
pub github_token: Option<String>,
pub repository: Option<String>,
pub artifact_path: String,
pub iterations: u32,
pub warmup_iterations: u32,
}
impl Default for PipelineConfig {
fn default() -> Self {
Self {
base_branch: "main".to_string(),
benchmark_command: "cargo bench --no-fail-fast".to_string(),
work_dir: ".".to_string(),
timeout_sec: 600,
regression_threshold_percent: 5.0,
warning_threshold_percent: 2.0,
github_token: None,
repository: None,
artifact_path: "./benchmark-artifacts".to_string(),
iterations: 10,
warmup_iterations: 3,
}
}
}
#[derive(Debug, Clone)]
pub struct StatusCheck {
pub name: String,
pub state: PipelineStatus,
pub description: String,
pub target_url: Option<String>,
pub context: String,
}