Skip to content

Commit b3fd874

Browse files
committed
test(cli): cover --deny-config-warnings silent, precedence, and fmt; document the flag
Locks in that the flag still exits 2 under --silent (no stderr noise), that a config problem takes precedence over Markdown violations (exit 2, not 1) while a plain violation still exits 1, and that fmt honors the flag. Documents the flag and its exit-code semantics in the CLI reference. Refs #726
1 parent 0f93ca5 commit b3fd874

2 files changed

Lines changed: 98 additions & 13 deletions

File tree

docs/usage/cli.md

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,20 @@ rumdl check --fix . # Lint and auto-fix issues
2020

2121
**Options:**
2222

23-
| Option | Description |
24-
| ---------------------- | ---------------------------------------------------- |
25-
| `--fix` | Auto-fix issues (exits 1 if unfixable issues remain) |
26-
| `--config <PATH>` | Path to configuration file |
27-
| `--disable <RULES>` | Disable specific rules (e.g., `MD013,MD033`) |
28-
| `--enable <RULES>` | Enable only specific rules |
29-
| `--exclude <PATTERNS>` | Exclude files matching patterns |
30-
| `--include <PATTERNS>` | Include only files matching patterns |
31-
| `--watch` | Watch for changes and re-lint |
32-
| `--verbose` | Show detailed output |
33-
| `--quiet` | Print diagnostics, but suppress summaries |
34-
| `--silent` | Suppress diagnostics and summaries |
35-
| `--no-exclude` | Disable exclude patterns defined in config |
23+
| Option | Description |
24+
| ------------------------ | ---------------------------------------------------- |
25+
| `--fix` | Auto-fix issues (exits 1 if unfixable issues remain) |
26+
| `--config <PATH>` | Path to configuration file |
27+
| `--disable <RULES>` | Disable specific rules (e.g., `MD013,MD033`) |
28+
| `--enable <RULES>` | Enable only specific rules |
29+
| `--exclude <PATTERNS>` | Exclude files matching patterns |
30+
| `--include <PATTERNS>` | Include only files matching patterns |
31+
| `--watch` | Watch for changes and re-lint |
32+
| `--verbose` | Show detailed output |
33+
| `--quiet` | Print diagnostics, but suppress summaries |
34+
| `--silent` | Suppress diagnostics and summaries |
35+
| `--no-exclude` | Disable exclude patterns defined in config |
36+
| `--deny-config-warnings` | Treat configuration warnings as errors (exit code 2) |
3637

3738
### `fmt [PATHS...]`
3839

@@ -57,6 +58,7 @@ rumdl fmt --silent - # Format stdin to stdout without diagnostics
5758
| `--watch` | Re-run formatting when files change |
5859
| `--quiet` | Print diagnostics, but suppress summaries |
5960
| `--silent` | Suppress diagnostics and summaries |
61+
| `--deny-config-warnings` | Treat configuration warnings as errors (exit code 2) |
6062

6163
Use `--silent` whenever stdout should contain only formatted Markdown. Plain `rumdl fmt -` may also emit remaining diagnostics.
6264

@@ -187,6 +189,15 @@ These options are commonly used with `check` and `fmt`:
187189
- `rumdl fmt` always exits 0 (formatter mode)
188190
- `rumdl check --fix` exits 1 if unfixable issues remain
189191

192+
!!! note "Failing on configuration problems"
193+
Configuration problems (an unknown rule or option in a config file or a CLI
194+
flag, an unknown rule in an inline `rumdl-disable-line` comment, or a
195+
shadowed config file) are non-fatal warnings by default and do not affect the
196+
exit code. Pass `--deny-config-warnings` to make any of them exit with code
197+
`2`, so CI catches a typo'd rule name. This is distinct from `--fail-on`,
198+
which governs the severity of Markdown violations (exit `1`); a config
199+
problem exits `2` and takes precedence over Markdown violations.
200+
190201
## Usage Examples
191202

192203
### Basic Linting

tests/cli/cli_exit_codes_test.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,77 @@ fn stdin_inline_config_warning_non_fatal_by_default() {
273273
"stdin inline config warning must not affect exit code by default"
274274
);
275275
}
276+
277+
/// --silent suppresses the printed notice but the flag must still exit 2.
278+
#[test]
279+
fn deny_config_warnings_silent_still_exits_two() {
280+
let dir = tempdir().unwrap();
281+
std::fs::write(dir.path().join("clean.md"), "# Title\n\nText.\n").unwrap();
282+
std::fs::write(dir.path().join(".rumdl.toml"), "[global]\nenable = [\"MD999\"]\n").unwrap();
283+
284+
let output = rumdl()
285+
.args(["check", "--no-cache", "--deny-config-warnings", "--silent", "clean.md"])
286+
.current_dir(dir.path())
287+
.output()
288+
.expect("run rumdl check");
289+
assert_eq!(output.status.code(), Some(TOOL_ERROR));
290+
assert!(
291+
String::from_utf8_lossy(&output.stderr).is_empty(),
292+
"--silent must suppress the printed warning even while the flag makes it fatal. stderr: {}",
293+
String::from_utf8_lossy(&output.stderr)
294+
);
295+
}
296+
297+
/// A config warning outranks a real Markdown violation: exit 2, not 1.
298+
#[test]
299+
fn deny_config_warnings_take_precedence_over_violations() {
300+
let dir = tempdir().unwrap();
301+
// MD041: first line is not a top-level heading -> a real violation.
302+
std::fs::write(dir.path().join("dirty.md"), "no heading here\n").unwrap();
303+
std::fs::write(dir.path().join(".rumdl.toml"), "[global]\nenable = [\"MD999\"]\n").unwrap();
304+
305+
let status = rumdl()
306+
.args(["check", "--no-cache", "--deny-config-warnings", "dirty.md"])
307+
.current_dir(dir.path())
308+
.status()
309+
.expect("run rumdl check");
310+
assert_eq!(
311+
status.code(),
312+
Some(TOOL_ERROR),
313+
"a config problem must exit 2 even when Markdown violations (exit 1) are also present"
314+
);
315+
}
316+
317+
/// Sanity check the precedence test's premise: the same violation WITHOUT a
318+
/// config problem exits 1, not 2.
319+
#[test]
320+
fn violations_without_config_problem_exit_one() {
321+
let dir = tempdir().unwrap();
322+
std::fs::write(dir.path().join("dirty.md"), "no heading here\n").unwrap();
323+
324+
let status = rumdl()
325+
.args(["check", "--no-cache", "--deny-config-warnings", "dirty.md"])
326+
.current_dir(dir.path())
327+
.status()
328+
.expect("run rumdl check");
329+
assert_eq!(
330+
status.code(),
331+
Some(1),
332+
"a plain Markdown violation exits 1; the flag only changes config-problem exits"
333+
);
334+
}
335+
336+
/// `fmt` shares config loading and the flag; it also exits 2 on a config problem.
337+
#[test]
338+
fn deny_config_warnings_applies_to_fmt() {
339+
let dir = tempdir().unwrap();
340+
std::fs::write(dir.path().join("clean.md"), "# Title\n\nText.\n").unwrap();
341+
std::fs::write(dir.path().join(".rumdl.toml"), "[global]\nenable = [\"MD999\"]\n").unwrap();
342+
343+
let status = rumdl()
344+
.args(["fmt", "--no-cache", "--deny-config-warnings", "clean.md"])
345+
.current_dir(dir.path())
346+
.status()
347+
.expect("run rumdl fmt");
348+
assert_eq!(status.code(), Some(TOOL_ERROR));
349+
}

0 commit comments

Comments
 (0)