-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathsecrets_integration.rs
More file actions
148 lines (140 loc) · 5.28 KB
/
Copy pathsecrets_integration.rs
File metadata and controls
148 lines (140 loc) · 5.28 KB
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
//! Integration tests for `ado-aw secrets` (and the deprecation alias).
use std::path::PathBuf;
fn binary() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_ado-aw"))
}
#[test]
fn secrets_help_advertises_subcommands() {
let output = std::process::Command::new(binary())
.args(["secrets", "--help"])
.output()
.expect("Failed to run ado-aw secrets --help");
assert!(output.status.success(), "--help should exit 0");
let stdout = String::from_utf8_lossy(&output.stdout);
for sub in ["set", "list", "delete"] {
assert!(
stdout.contains(sub),
"secrets --help should advertise the {sub} subcommand, got:\n{stdout}"
);
}
}
#[test]
fn secrets_set_help_advertises_flags() {
let output = std::process::Command::new(binary())
.args(["secrets", "set", "--help"])
.output()
.expect("Failed to run ado-aw secrets set --help");
assert!(output.status.success(), "--help should exit 0");
let stdout = String::from_utf8_lossy(&output.stdout);
for flag in ["--allow-override", "--value-stdin", "--dry-run", "--pat"] {
assert!(
stdout.contains(flag),
"secrets set --help should advertise {flag}, got:\n{stdout}"
);
}
}
#[test]
fn secrets_set_rejects_value_with_value_stdin() {
// clap should reject the combination at parse time via
// `conflicts_with = "value"` on `--value-stdin`.
let output = std::process::Command::new(binary())
.args(["secrets", "set", "MY_VAR", "explicit", "--value-stdin"])
.output()
.expect("Failed to run ado-aw secrets set");
assert!(
!output.status.success(),
"Expected non-zero exit when both <value> and --value-stdin are supplied"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("value-stdin") || stderr.contains("value_stdin"),
"stderr should reference the conflict, got:\n{stderr}"
);
}
#[test]
fn secrets_list_help_warns_no_values() {
let output = std::process::Command::new(binary())
.args(["secrets", "list", "--help"])
.output()
.expect("Failed to run ado-aw secrets list --help");
assert!(output.status.success(), "--help should exit 0");
let stdout = String::from_utf8_lossy(&output.stdout);
// The no-values policy is a security property: the list command
// must never print secret variable values.
assert!(
stdout.contains("Never prints values"),
"secrets list --help should warn that values are never printed, got:\n{stdout}"
);
assert!(
stdout.contains("--json"),
"secrets list --help should advertise --json, got:\n{stdout}"
);
}
#[test]
fn configure_is_hidden_in_top_level_help() {
let output = std::process::Command::new(binary())
.arg("--help")
.output()
.expect("Failed to run ado-aw --help");
assert!(output.status.success(), "--help should exit 0");
let stdout = String::from_utf8_lossy(&output.stdout);
// `secrets` is the documented replacement.
assert!(
stdout.contains("secrets"),
"Top-level --help should advertise the secrets subcommand, got:\n{stdout}"
);
// The legacy `configure` line must not appear (it's hidden).
// We allow any line that mentions "configure" elsewhere but the
// top-level commands list must not include the literal subcommand.
// We check the "Commands:" section, which is everything between
// `Commands:` and `Options:`.
let lower = stdout.to_lowercase();
let commands_start = lower
.find("commands:")
.expect("top-level --help should contain a 'Commands:' section");
let options_start = lower
.find("options:")
.expect("top-level --help should contain an 'Options:' section");
let block = &lower[commands_start..options_start];
assert!(
!block.contains("configure"),
"configure should be hidden in top-level --help; commands block was:\n{block}"
);
}
#[test]
fn configure_invocation_still_works_and_warns() {
// We can't drive a real ADO call from a unit test, but the
// deprecation warning is emitted by the very first line of
// `run_set_github_token`, so we trigger it by passing arguments
// that will fail early after the warning prints.
//
// Use a path that doesn't exist; the warning is emitted before
// the path canonicalization step. The command will still
// ultimately fail, which is fine — we only assert on stderr.
let output = std::process::Command::new(binary())
.args([
"configure",
"--org",
"fake",
"--project",
"fake",
"--pat",
"dummy",
"--token",
"x",
"--path",
"/definitely-does-not-exist-9c4f0",
"--dry-run",
])
.output()
.expect("Failed to run ado-aw configure");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("deprecated"),
"configure should emit a deprecation warning, got stderr:\n{stderr}"
);
assert!(
stderr.contains("secrets set GITHUB_TOKEN") || stderr.contains("secrets set"),
"deprecation warning should mention the replacement, got stderr:\n{stderr}"
);
}