feat(rome_cli): allow to skip checks in `rome ci` command
MODIFY
crates/rome_cli/src/commands/ci.rs
crates/rome_cli/src/commands/ci.rs
@@ -2,6 +2,7 @@ use crate::{
configuration::load_configuration, execute_mode, CliSession, Execution, Termination,
TraversalMode,
};
+use rome_service::configuration::{FormatterConfiguration, LinterConfiguration};
use rome_service::workspace::UpdateSettingsParams;
use super::format::apply_format_settings_from_cli;
@@ -9,7 +10,43 @@ use super::format::apply_format_settings_from_cli;
/// Handler for the "ci" command of the Rome CLI
pub(crate) fn ci(mut session: CliSession) -> Result<(), Termination> {
let mut configuration = load_configuration(&mut session)?;
+
+ let formatter_enabled = session
+ .args
+ .opt_value_from_str("--formatter-enabled")
+ .map_err(|source| Termination::ParseError {
+ argument: "--formatter-enabled",
+ source,
+ })?;
+
+ let linter_enabled = session
+ .args
+ .opt_value_from_str("--linter-enabled")
+ .map_err(|source| Termination::ParseError {
+ argument: "--linter-enabled",
+ source,
+ })?;
+
+ let formatter = configuration
+ .formatter
+ .get_or_insert_with(FormatterConfiguration::default);
+
+ formatter.enabled = formatter_enabled.unwrap_or(true);
+
+ let linter = configuration
+ .linter
+ .get_or_insert_with(LinterConfiguration::default);
+
+ linter.enabled = linter_enabled.unwrap_or(true);
+
+ // no point in doing the traversal if all the checks have been disabled
+ if configuration.is_formatter_disabled() && configuration.is_linter_disabled() {
+ return Err(Termination::IncompatibleEndConfiguration("Formatter and Linter are both disabled, can't perform the command. This probably and error."));
+ }
+
+ if !configuration.is_formatter_disabled() {
apply_format_settings_from_cli(&mut session, &mut configuration)?;
+ }
session
.app

MODIFY
crates/rome_cli/src/commands/help.rs
crates/rome_cli/src/commands/help.rs
@@ -58,7 +58,9 @@ const CI: Markup = markup! {
INPUTS can be one or more filesystem path, each pointing to a single file or an entire directory to be searched recursively for supported files
-"<Emphasis>"OPTIONS:"</Emphasis>""
+"<Emphasis>"OPTIONS:"</Emphasis>"
+ "<Dim>"--formatter-enabled"</Dim>" Allow to enable or disable the formatter check. (default: true)
+ "<Dim>"--linter-enabled"</Dim>" Allow to enable or disable the linter check. (default: true)"
{FORMAT_OPTIONS}
};

MODIFY
crates/rome_cli/src/termination.rs
crates/rome_cli/src/termination.rs
@@ -73,6 +73,9 @@ pub enum Termination {
command_name()
)]
ServerNotRunning,
+
+ #[error("The combination of configuration and arguments is invalid: \n {0}")]
+ IncompatibleEndConfiguration(&'static str),
}
fn command_name() -> String {

MODIFY
crates/rome_cli/tests/commands/ci.rs
crates/rome_cli/tests/commands/ci.rs
@@ -14,6 +14,22 @@ use std::path::{Path, PathBuf};
const INCORRECT_CODE: &str = "let a = !b || !c";
+const UNFORMATTED_AND_INCORRECT: &str = "statement( ) ; let a = !b || !c;";
+
+const CI_CONFIGURATION: &str = r#"
+{
+ "formatter": {
+ "enabled": true
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true
+ }
+ }
+}
+"#;
+
#[test]
fn ok() {
let mut fs = MemoryFileSystem::default();
@@ -148,7 +164,7 @@ fn ci_does_not_run_formatter() {
fs.insert(file_path.into(), CONFIG_DISABLED_FORMATTER.as_bytes());
let file_path = Path::new("file.js");
- fs.insert(file_path.into(), UNFORMATTED.as_bytes());
+ fs.insert(file_path.into(), UNFORMATTED_AND_INCORRECT.as_bytes());
let result = run_cli(
DynRef::Borrowed(&mut fs),
@@ -156,7 +172,7 @@ fn ci_does_not_run_formatter() {
Arguments::from_vec(vec![OsString::from("ci"), file_path.as_os_str().into()]),
);
- assert!(result.is_ok(), "run_cli returned {result:?}");
+ assert!(result.is_err(), "run_cli returned {result:?}");
let mut file = fs
.open(file_path)
@@ -166,7 +182,7 @@ fn ci_does_not_run_formatter() {
file.read_to_string(&mut content)
.expect("failed to read file from memory FS");
- assert_eq!(content, UNFORMATTED);
+ assert_eq!(content, UNFORMATTED_AND_INCORRECT);
drop(file);
assert_cli_snapshot(SnapshotPayload::new(
@@ -178,6 +194,46 @@ fn ci_does_not_run_formatter() {
));
}
+#[test]
+fn ci_does_not_run_formatter_via_cli() {
+ let mut fs = MemoryFileSystem::default();
+ let mut console = BufferConsole::default();
+
+ let file_path = Path::new("file.js");
+ fs.insert(file_path.into(), UNFORMATTED_AND_INCORRECT.as_bytes());
+
+ let result = run_cli(
+ DynRef::Borrowed(&mut fs),
+ DynRef::Borrowed(&mut console),
+ Arguments::from_vec(vec![
+ OsString::from("ci"),
+ OsString::from("--formatter-enabled=false"),
+ file_path.as_os_str().into(),
+ ]),
+ );
+
+ assert!(result.is_err(), "run_cli returned {result:?}");
+
+ let mut file = fs
+ .open(file_path)
+ .expect("formatting target file was removed by the CLI");
+
+ let mut content = String::new();
+ file.read_to_string(&mut content)
+ .expect("failed to read file from memory FS");
+
+ assert_eq!(content, UNFORMATTED_AND_INCORRECT);
+
+ drop(file);
+ assert_cli_snapshot(SnapshotPayload::new(
+ module_path!(),
+ "ci_does_not_run_formatter_via_cli",
+ fs,
+ console,
+ result,
+ ));
+}
+
#[test]
fn ci_does_not_run_linter() {
let mut fs = MemoryFileSystem::default();
@@ -217,6 +273,90 @@ fn ci_does_not_run_linter() {
));
}
+#[test]
+fn ci_does_not_run_linter_via_cli() {
+ let mut fs = MemoryFileSystem::default();
+ let mut console = BufferConsole::default();
+
+ let file_path = Path::new("file.js");
+ fs.insert(file_path.into(), UNFORMATTED_AND_INCORRECT.as_bytes());
+
+ let result = run_cli(
+ DynRef::Borrowed(&mut fs),
+ DynRef::Borrowed(&mut console),
+ Arguments::from_vec(vec![
+ OsString::from("ci"),
+ OsString::from("--linter-enabled=false"),
+ file_path.as_os_str().into(),
+ ]),
+ );
+
+ assert!(result.is_err(), "run_cli returned {result:?}");
+
+ let mut file = fs
+ .open(file_path)
+ .expect("formatting target file was removed by the CLI");
+
+ let mut content = String::new();
+ file.read_to_string(&mut content)
+ .expect("failed to read file from memory FS");
+
+ assert_eq!(content, UNFORMATTED_AND_INCORRECT);
+
+ drop(file);
+ assert_cli_snapshot(SnapshotPayload::new(
+ module_path!(),
+ "ci_does_not_run_linter_via_cli",
+ fs,
+ console,
+ result,
+ ));
+}
+
+#[test]
+fn ci_errors_for_all_disabled_checks() {
+ let mut fs = MemoryFileSystem::default();
+ let mut console = BufferConsole::default();
+
+ let file_path = Path::new("rome.json");
+ fs.insert(file_path.into(), CI_CONFIGURATION.as_bytes());
+
+ let file_path = Path::new("file.js");
+ fs.insert(file_path.into(), UNFORMATTED_AND_INCORRECT.as_bytes());
+
+ let result = run_cli(
+ DynRef::Borrowed(&mut fs),
+ DynRef::Borrowed(&mut console),
+ Arguments::from_vec(vec![
+ OsString::from("ci"),
+ OsString::from("--linter-enabled=false"),
+ OsString::from("--formatter-enabled=false"),
+ file_path.as_os_str().into(),
+ ]),
+ );
+
+ assert!(result.is_err(), "run_cli returned {result:?}");
+
+ let mut file = fs
+ .open(file_path)
+ .expect("formatting target file was removed by the CLI");
+
+ let mut content = String::new();
+ file.read_to_string(&mut content)
+ .expect("failed to read file from memory FS");
+
+ assert_eq!(content, UNFORMATTED_AND_INCORRECT);
+
+ drop(file);
+ assert_cli_snapshot(SnapshotPayload::new(
+ module_path!(),
+ "ci_errors_for_all_disabled_checks",
+ fs,
+ console,
+ result,
+ ));
+}
+
#[test]
fn file_too_large() {
let mut fs = MemoryFileSystem::default();

ADD
crates/rome_cli/tests/snapshots/main_commands_ci/ci_errors_for_all_disabled_checks.snap
+---
+source: crates/rome_cli/tests/snap_test.rs
+expression: content
+---
+## `rome.json`
+
+```json
+
+{
+ "formatter": {
+ "enabled": true
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true
+ }
+ }
+}
+
+```
+
+## `file.js`
+
+```js
+statement( ) ; let a = !b || !c;
+```
+
+# Termination Message
+
+```block
+The combination of configuration and arguments is invalid:
+ Formatter and Linter are both disabled, can't perform the command. This probably and error.
+```
+
+

feat(rome_cli): allow to skip checks in `rome ci` command (#3545)