qtcloud_devops_cli/
contract.rs1pub use quanttide_devops::contract::{
5 detect_language_by_files, normalize_version, read_all_config_versions, validate_version,
6 BuildTool, Contract, Language, Pipeline, Platform, Registry, Scope, SourceControl, SourceType,
7 StageBuild, StageRelease, StageTest, VersionSource,
8};
9
10use std::path::Path;
11
12pub fn load(repo_path: &Path) -> Contract {
20 match quanttide_devops::contract::load(repo_path) {
21 Ok(c) => c,
22 Err(e) => {
23 eprintln!(" ℹ contract.yaml: {},使用默认契约", e);
24 Contract::default()
25 }
26 }
27}
28
29pub fn load_scopes(repo_path: &Path) -> Vec<Scope> {
31 load(repo_path).scopes
32}
33
34pub fn detect_by_files(dir: &Path) -> Language {
36 detect_language_by_files(dir)
37}
38
39#[derive(Debug)]
45pub struct VersionStatus {
46 pub tag_version: Option<String>,
47 pub config_version: Option<String>,
48 pub consistent: bool,
49 pub config_files: Vec<(String, Option<String>)>,
51}
52
53pub fn version_status(repo_path: &Path, scope: &Scope) -> VersionStatus {
55 let tag_version = latest_tag_for_scope(repo_path, &scope.name);
56 let scope_dir = repo_path.join(&scope.dir);
57 let config_files = quanttide_devops::contract::read_all_config_versions(&scope_dir);
58 let config_version = config_files
59 .iter()
60 .find(|(_, v)| v.is_some())
61 .and_then(|(_, v)| v.clone());
62 let consistent = match &tag_version {
63 Some(t) => config_files.iter().all(|(_, v)| match v {
64 Some(cv) => cv == t,
65 None => true,
66 }),
67 None => config_version.is_none(),
68 };
69 VersionStatus {
70 tag_version,
71 config_version,
72 consistent,
73 config_files,
74 }
75}
76
77fn latest_tag_for_scope(repo_path: &Path, scope_name: &str) -> Option<String> {
78 let output = std::process::Command::new("git")
79 .args(["tag", "--sort=-version:refname"])
80 .current_dir(repo_path)
81 .output()
82 .ok()?;
83 if !output.status.success() {
84 return None;
85 }
86 let prefix = format!("{}/", scope_name);
87 let tags: Vec<&str> = std::str::from_utf8(&output.stdout)
88 .ok()?
89 .lines()
90 .filter(|t| t.starts_with(&prefix) || !t.contains('/'))
91 .collect();
92 let scoped = tags.iter().find(|t| t.starts_with(&prefix));
93 match scoped {
94 Some(t) => Some(normalize_version(t)),
95 None => tags.first().map(|t| normalize_version(t)),
96 }
97}