1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use clap::{Parser, Subcommand, ValueEnum};
use clap_complete::Shell;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(
name = "svccat",
version,
about = "Service catalog drift detection for multi-service repositories",
long_about = "\
svccat reads your declared service manifest and compares it against what \
actually exists in the repo, flagging drift before it becomes toil.\n\n\
Typical workflow:\n \
svccat check # inspect drift in the current repo\n \
svccat check --fail-on-drift # gate CI on zero drift\n \
svccat graph # emit a Mermaid diagram for docs\n \
svccat export --format json # machine-readable catalog snapshot"
)]
pub struct Cli {
/// Repository root (defaults to current directory)
#[arg(short, long, global = true)]
pub root: Option<PathBuf>,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
/// Check declared services against the repo and report drift
Check {
/// Path to the manifest file (auto-detected if omitted)
#[arg(short, long)]
manifest: Option<PathBuf>,
/// Output format
#[arg(short, long, value_enum, default_value_t = OutputFormat::Terminal)]
format: OutputFormat,
/// Exit with code 1 when drift is detected (useful in CI)
#[arg(long)]
fail_on_drift: bool,
/// Ping each service URL and report reachability
#[arg(long)]
ping: bool,
/// Glob patterns to exclude from discovery (repeatable, e.g. --ignore "examples/*")
#[arg(long, value_name = "PATTERN")]
ignore: Vec<String>,
/// Only check services owned by this team (matches the `team:` field)
#[arg(long, value_name = "TEAM")]
team: Option<String>,
},
/// Generate a Mermaid or Markdown view of the service catalog
Graph {
/// Path to the manifest file (auto-detected if omitted)
#[arg(short, long)]
manifest: Option<PathBuf>,
/// Output format
#[arg(short, long, value_enum, default_value_t = GraphFormat::Mermaid)]
format: GraphFormat,
},
/// Export the full service catalog with drift summary
Export {
/// Path to the manifest file (auto-detected if omitted)
#[arg(short, long)]
manifest: Option<PathBuf>,
/// Export format
#[arg(short, long, value_enum, default_value_t = ExportFormat::Json)]
format: ExportFormat,
/// Glob patterns to exclude from discovery (repeatable)
#[arg(long, value_name = "PATTERN")]
ignore: Vec<String>,
},
/// Scaffold a services.yaml by auto-discovering services in the repo
Init {
/// Where to write the manifest (default: services.yaml in repo root)
#[arg(short, long)]
output: Option<PathBuf>,
/// Overwrite an existing manifest file
#[arg(long)]
force: bool,
},
/// Compare two svccat export JSON snapshots and show what changed
///
/// Generate snapshots with: svccat export --format json > snapshot.json
Diff {
/// Path to the older snapshot (JSON)
before: std::path::PathBuf,
/// Path to the newer snapshot (JSON)
after: std::path::PathBuf,
},
/// Watch the manifest and service directories for changes and re-run drift checks
///
/// Continuously monitors the manifest file and service directories.
/// Re-runs drift analysis whenever a file change is detected and prints
/// a timestamped report. Press Ctrl-C to stop.
Watch {
/// Path to the manifest file (auto-detected if omitted)
#[arg(short, long)]
manifest: Option<PathBuf>,
/// Exit with code 1 when drift is detected on the first check
#[arg(long)]
fail_on_drift: bool,
/// Only watch services owned by this team
#[arg(long, value_name = "TEAM")]
team: Option<String>,
/// Glob patterns to exclude from discovery (repeatable)
#[arg(long, value_name = "PATTERN")]
ignore: Vec<String>,
},
/// Print shell completion script to stdout
///
/// Source the output to enable tab completion, e.g.:
/// source <(svccat completions bash)
/// svccat completions zsh > ~/.zfunc/_svccat
Completions {
/// Shell to generate completions for
shell: Shell,
},
}
#[derive(Debug, Clone, ValueEnum, PartialEq)]
pub enum OutputFormat {
Terminal,
Json,
}
#[derive(Debug, Clone, ValueEnum, PartialEq)]
pub enum GraphFormat {
Mermaid,
Markdown,
}
#[derive(Debug, Clone, ValueEnum, PartialEq)]
pub enum ExportFormat {
Json,
Markdown,
}