qtcloud_devops_cli/
contract.rs1pub use quanttide_devops::contract::{
3 check_version_consistency, load_or_default, normalize_version, validate_version,
4 verify_version, BuildTool, Contract, ContractError, Language, Pipeline, Platform, Registry,
5 Scope, SourceControl, Stage, StageBuild, StageRelease, StageTest, VersionState,
6};
7pub use quanttide_devops::source::config_file::{detect_language, read_config_versions};
8
9use std::path::Path;
10
11pub fn load(repo_path: &Path) -> Contract {
13 load_or_default(repo_path)
14}
15
16pub fn load_scopes(repo_path: &Path) -> Vec<Scope> {
17 load(repo_path).scopes
18}
19
20pub fn detect_by_files(dir: &Path) -> Language {
21 detect_language(dir)
22}
23
24pub fn detect_all_languages(dir: &Path) -> Vec<String> {
26 let mut langs = Vec::new();
27 if dir.join("Cargo.toml").exists() {
28 langs.push("rust".into());
29 }
30 if dir.join("pyproject.toml").exists() || dir.join("requirements.txt").exists() {
31 langs.push("python".into());
32 }
33 if dir.join("go.mod").exists() {
34 langs.push("go".into());
35 }
36 if dir.join("pubspec.yaml").exists() {
37 langs.push("dart".into());
38 }
39 if dir.join("package.json").exists() {
40 langs.push("typescript".into());
41 }
42 langs
43}
44
45pub fn version_status(repo_path: &Path, scope: &Scope) -> VersionState {
47 verify_version(repo_path, scope).unwrap_or_else(|e| {
48 eprintln!(" ⚠ 版本状态检查失败: {}", e);
49 VersionState {
50 tag_version: None,
51 config_version: None,
52 consistent: false,
53 config_files: vec![],
54 }
55 })
56}
57
58pub fn status(repo_path: &Path) {
60 let mut stdout = std::io::stdout();
61 status_to(&mut stdout, repo_path).ok();
62}
63
64pub fn status_to(writer: &mut impl std::io::Write, repo_path: &Path) -> std::io::Result<()> {
66 let contract_path = repo_path.join(".quanttide/devops/contract.yaml");
67 let exists = contract_path.exists();
68 let c = load(repo_path);
69
70 writeln!(writer, "契约状态")?;
71 writeln!(writer, "{}", "-".repeat(40))?;
72 if exists {
73 writeln!(writer, " 配置文件: {}", contract_path.display())?;
74 writeln!(writer, " 状态: ✅ 已加载")?;
75 } else {
76 writeln!(writer, " 配置文件: 未找到,使用默认契约")?;
77 writeln!(writer, " 状态: ⚠ 默认配置")?;
78 }
79 writeln!(writer)?;
80
81 writeln!(writer, " Stages:")?;
82 writeln!(
83 writer,
84 " build: {}",
85 c.stages.build.command.as_deref().unwrap_or("—")
86 )?;
87 writeln!(
88 writer,
89 " test: {}(阈值 {}%)",
90 c.stages.test.command.as_deref().unwrap_or("—"),
91 c.stages.test.threshold
92 )?;
93 writeln!(
94 writer,
95 " release: {}(pre_publish: {:?})",
96 c.stages.release.changelog, c.stages.release.pre_publish
97 )?;
98 writeln!(writer)?;
99
100 writeln!(writer, " Platform:")?;
101 writeln!(
102 writer,
103 " source_control: {:?}",
104 c.platform.source_control
105 )?;
106 writeln!(writer, " pipeline: {:?}", c.platform.pipeline)?;
107 writeln!(
108 writer,
109 " artifact_registry: {}",
110 c.platform.artifact_registry
111 )?;
112 writeln!(writer)?;
113
114 writeln!(writer, " Sources:")?;
115 writeln!(
116 writer,
117 " version: {:?} {:?}",
118 c.sources.version.source_type, c.sources.version.path
119 )?;
120 writeln!(writer)?;
121
122 writeln!(writer, " Scopes: {} 个", c.scopes.len())?;
123 if c.scopes.is_empty() {
124 writeln!(writer, " 未定义 scope")?;
125 } else {
126 for s in &c.scopes {
127 writeln!(
128 writer,
129 " {:<12} dir: {:<24} {} / {}",
130 s.name,
131 s.dir,
132 s.language.as_str(),
133 s.build_tool.as_str()
134 )?;
135 }
136 }
137
138 let langs = detect_all_languages(repo_path);
139 if !langs.is_empty() {
140 writeln!(writer)?;
141 writeln!(writer, " 语言: {}", langs.join(", "))?;
142 }
143 Ok(())
144}