qtcloud-devops-cli 0.3.0-rc.8

量潮DevOps云命令行工具
Documentation
use std::path::Path;

use crate::model::release::{FileStorage, ReleaseStatus, Storage, TransitionError};

pub fn run(version: &str, repo_path: &Path) -> Result<String, Box<dyn std::error::Error>> {
    let mut storage = FileStorage::new(repo_path);
    let mut record = storage
        .load(version)
        .ok_or_else(|| format!("版本 {} 不存在", version))?;

    if record.status != ReleaseStatus::Published {
        return Err(Box::new(TransitionError::NotPublished(version.to_string())));
    }

    record.status = ReleaseStatus::Retired;
    record.updated_at = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_secs()
        .to_string();
    storage.save(&record)?;

    let id = record.id.clone();
    println!("✓ 版本 {} 已退役 (发布尝试 ID: {})", version, id);
    Ok(id)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::model::release::{ReleaseRecord, ReleaseStatus, Storage};

    fn make_record(version: &str, status: ReleaseStatus) -> ReleaseRecord {
        let now = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs()
            .to_string();
        ReleaseRecord {
            id: uuid::Uuid::new_v4().to_string(),
            version: version.to_string(),
            status,
            created_at: now.clone(),
            updated_at: now,
        }
    }

    #[test]
    fn test_retire_not_published() {
        let dir = tempfile::tempdir().unwrap();
        let mut s = FileStorage::new(dir.path());
        s.save(&make_record("v1.0.0", ReleaseStatus::Staged))
            .unwrap();
        assert!(run("v1.0.0", dir.path()).is_err());
    }

    #[test]
    fn test_retire_nonexistent() {
        let dir = tempfile::tempdir().unwrap();
        assert!(run("v9.9.9", dir.path()).is_err());
    }

    #[test]
    fn test_retire_from_published() {
        let dir = tempfile::tempdir().unwrap();
        {
            let mut s = FileStorage::new(dir.path());
            s.save(&make_record("v1.0.0", ReleaseStatus::Published))
                .unwrap();
        }
        run("v1.0.0", dir.path()).unwrap();
        let s = FileStorage::new(dir.path());
        assert_eq!(
            s.load("v1.0.0").unwrap().status,
            ReleaseStatus::Retired
        );
    }
}