Skip to main content

qtcloud_devops_cli/commands/
retire.rs

1use std::path::Path;
2
3use crate::model::release::{FileStorage, ReleaseStatus, Storage, TransitionError};
4
5pub fn run(version: &str, repo_path: &Path) -> Result<String, Box<dyn std::error::Error>> {
6    let mut storage = FileStorage::new(repo_path);
7    let mut record = storage
8        .load(version)
9        .ok_or_else(|| format!("版本 {} 不存在", version))?;
10
11    if record.status != ReleaseStatus::Published {
12        return Err(Box::new(TransitionError::NotPublished(version.to_string())));
13    }
14
15    record.status = ReleaseStatus::Retired;
16    record.updated_at = std::time::SystemTime::now()
17        .duration_since(std::time::UNIX_EPOCH)
18        .unwrap_or_default()
19        .as_secs()
20        .to_string();
21    storage.save(&record)?;
22
23    let id = record.id.clone();
24    println!("✓ 版本 {} 已退役 (发布尝试 ID: {})", version, id);
25    Ok(id)
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    use crate::model::release::{ReleaseRecord, ReleaseStatus, Storage};
32
33    fn make_record(version: &str, status: ReleaseStatus) -> ReleaseRecord {
34        let now = std::time::SystemTime::now()
35            .duration_since(std::time::UNIX_EPOCH)
36            .unwrap_or_default()
37            .as_secs()
38            .to_string();
39        ReleaseRecord {
40            id: uuid::Uuid::new_v4().to_string(),
41            version: version.to_string(),
42            status,
43            created_at: now.clone(),
44            updated_at: now,
45        }
46    }
47
48    #[test]
49    fn test_retire_not_published() {
50        let dir = tempfile::tempdir().unwrap();
51        let mut s = FileStorage::new(dir.path());
52        s.save(&make_record("v1.0.0", ReleaseStatus::Staged))
53            .unwrap();
54        assert!(run("v1.0.0", dir.path()).is_err());
55    }
56
57    #[test]
58    fn test_retire_nonexistent() {
59        let dir = tempfile::tempdir().unwrap();
60        assert!(run("v9.9.9", dir.path()).is_err());
61    }
62
63    #[test]
64    fn test_retire_from_published() {
65        let dir = tempfile::tempdir().unwrap();
66        {
67            let mut s = FileStorage::new(dir.path());
68            s.save(&make_record("v1.0.0", ReleaseStatus::Published))
69                .unwrap();
70        }
71        run("v1.0.0", dir.path()).unwrap();
72        let s = FileStorage::new(dir.path());
73        assert_eq!(
74            s.load("v1.0.0").unwrap().status,
75            ReleaseStatus::Retired
76        );
77    }
78}