Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(biome_cli): add schema version check to check,lint,format commands #4796

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
- `biome migrate eslint` now correctly handles ESLint configuration with `null` values in file lists ([#4740](https://github.com/biomejs/biome/issues/4740)).
Contributed by @Conaclos

#### New features

- Command `check`, `format` and `lint` now check the schema and CLI versions, and report a warning in case of a schema version mismatch. ([#4147](https://github.com/biomejs/biome/issues/4147)).
Contributed by @MaxtuneLee

### Configuration

### Editors
Expand Down
4 changes: 3 additions & 1 deletion crates/biome_cli/src/commands/check.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{determine_fix_file_mode, FixFileModeOptions, LoadEditorConfig};
use crate::cli_options::CliOptions;
use crate::commands::{get_files_to_process_with_cli_options, CommandRunner};
use crate::{CliDiagnostic, Execution, TraversalMode};
use crate::{check_schema_version, CliDiagnostic, Execution, TraversalMode};
use biome_configuration::analyzer::assists::PartialAssistsConfiguration;
use biome_configuration::{
organize_imports::PartialOrganizeImports, PartialConfiguration, PartialFormatterConfiguration,
Expand Down Expand Up @@ -59,6 +59,8 @@ impl CommandRunner for CheckCommandPayload {
// this makes biome configuration take precedence over editorconfig configuration
fs_configuration.merge_with(biome_configuration);

check_schema_version(&fs_configuration, console);

let formatter = fs_configuration
.formatter
.get_or_insert_with(PartialFormatterConfiguration::default);
Expand Down
4 changes: 3 additions & 1 deletion crates/biome_cli/src/commands/format.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::cli_options::CliOptions;
use crate::commands::{get_files_to_process_with_cli_options, CommandRunner, LoadEditorConfig};
use crate::diagnostics::DeprecatedArgument;
use crate::{CliDiagnostic, Execution, TraversalMode};
use crate::{check_schema_version, CliDiagnostic, Execution, TraversalMode};
use biome_configuration::vcs::PartialVcsConfiguration;
use biome_configuration::{
PartialConfiguration, PartialCssFormatter, PartialFilesConfiguration,
Expand Down Expand Up @@ -162,6 +162,8 @@ impl CommandRunner for FormatCommandPayload {
.merge_with(self.files_configuration.clone());
configuration.vcs.merge_with(self.vcs_configuration.clone());

check_schema_version(&configuration, console);

Ok(configuration)
}

Expand Down
6 changes: 4 additions & 2 deletions crates/biome_cli/src/commands/lint.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{determine_fix_file_mode, FixFileModeOptions};
use crate::cli_options::CliOptions;
use crate::commands::{get_files_to_process_with_cli_options, CommandRunner};
use crate::{CliDiagnostic, Execution, TraversalMode};
use crate::{check_schema_version, CliDiagnostic, Execution, TraversalMode};
use biome_configuration::analyzer::RuleSelector;
use biome_configuration::css::PartialCssLinter;
use biome_configuration::javascript::PartialJavascriptLinter;
Expand Down Expand Up @@ -49,7 +49,7 @@ impl CommandRunner for LintCommandPayload {
&mut self,
loaded_configuration: LoadedConfiguration,
_fs: &DynRef<'_, dyn FileSystem>,
_console: &mut dyn Console,
console: &mut dyn Console,
) -> Result<PartialConfiguration, WorkspaceError> {
let LoadedConfiguration {
configuration: mut fs_configuration,
Expand All @@ -75,6 +75,8 @@ impl CommandRunner for LintCommandPayload {
..Default::default()
});

check_schema_version(&fs_configuration, console);

if self.css_linter.is_some() {
let css = fs_configuration.css.get_or_insert_with(Default::default);
css.linter.merge_with(self.css_linter.clone());
Expand Down
78 changes: 77 additions & 1 deletion crates/biome_cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
//! to parse commands and arguments, redirect the execution of the commands and
//! execute the traversal of directory and files, based on the command that were passed.

use biome_console::{markup, ColorMode, Console, ConsoleExt};
use biome_configuration::PartialConfiguration;
use biome_console::fmt::{Display, Formatter};
use biome_console::{markup, ColorMode, Console, ConsoleExt, KeyValuePair};
use biome_fs::OsFileSystem;
use biome_service::{App, DynRef, Workspace, WorkspaceRef};
use commands::search::SearchCommandPayload;
use std::cmp::Ordering;
use std::env;

mod changed;
Expand Down Expand Up @@ -38,6 +41,50 @@ pub use panic::setup_panic_handler;
pub use reporter::{DiagnosticsPayload, Reporter, ReporterVisitor, TraversalSummary};
pub use service::{open_transport, SocketTransport};

#[derive(PartialEq, Eq)]
pub struct Version(String);

impl Version {
pub fn new(version: &str) -> Self {
Version(version.to_string())
}

fn parse_version(&self) -> Vec<u32> {
self.0
.split('.')
.filter_map(|part| part.parse::<u32>().ok())
.collect()
}
}

impl PartialOrd for Version {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Version {
fn cmp(&self, other: &Self) -> Ordering {
let self_parts = self.parse_version();
let other_parts = other.parse_version();

for (a, b) in self_parts.iter().zip(other_parts.iter()) {
match a.cmp(b) {
Ordering::Equal => continue,
non_eq => return non_eq,
}
}

self_parts.len().cmp(&other_parts.len())
}
}

impl Display for Version {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::io::Error> {
write!(f, "{}", self.0)
}
}

pub(crate) const VERSION: &str = match option_env!("BIOME_VERSION") {
Some(version) => version,
None => env!("CARGO_PKG_VERSION"),
Expand Down Expand Up @@ -316,3 +363,32 @@ pub(crate) fn run_command(
let command = &mut command;
command.run(session, cli_options)
}

pub fn check_schema_version(
loaded_configuration: &PartialConfiguration,
console: &mut dyn Console,
) {
let schema = &loaded_configuration.schema;
let version_regex =
regex::Regex::new(r"https://biomejs.dev/schemas/([\d.]+)/schema.json").unwrap();
if let Some(schema_string) = schema {
if let Some(captures) = version_regex.captures(schema_string) {
if let Some(config_version_match) = captures.get(1) {
let cli_version = Version::new(VERSION);
let config_version_str = Version::new(config_version_match.as_str());
match config_version_str.cmp(&cli_version) {
Ordering::Less =>
console.log(markup!(<Warn>"The configuration schema version does not match the CLI version.\n"
{KeyValuePair("Expect", markup!({VERSION}))}
{KeyValuePair("Found", markup!({config_version_str}))}</Warn>"\n"
<Info>"If you wish to update the configuration schema, run `biome migrate --write`."</Info>)),
Ordering::Greater => console.log(markup!(<Warn>"The configuration schema version does not match the CLI version.\n"
{KeyValuePair("Expect", markup!({VERSION}))}
{KeyValuePair("Found", markup!({config_version_str}))}</Warn>"\n"
<Info>"If you wish to update the configuration schema, setting the `$schema` option to the expected version."</Info>)),
_ => {}
}
}
}
}
}
31 changes: 30 additions & 1 deletion crates/biome_cli/tests/commands/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2880,7 +2880,7 @@ fn should_show_formatter_diagnostics_for_files_ignored_by_linter() {
fs.insert(
biome_json.into(),
r#"{
"$schema": "https://biomejs.dev/schemas/1.6.1/schema.json",
"$schema": "https://biomejs.dev/schemas/0.0.0/schema.json",
"organizeImports": {
"enabled": true
},
Expand Down Expand Up @@ -3419,3 +3419,32 @@ fn should_error_if_unchanged_files_only_with_changed_flag() {
result,
));
}

#[test]
fn should_report_when_schema_version_mismatch() {
let mut console = BufferConsole::default();
let mut fs = MemoryFileSystem::default();

let biome_json = Path::new("biome.json");
fs.insert(
biome_json.into(),
r#"{
"$schema": "https://biomejs.dev/schemas/0.0.1/schema.json"
}
"#,
);
let result = run_cli(
DynRef::Borrowed(&mut fs),
&mut console,
Args::from([("check")].as_slice()),
);

assert!(result.is_err(), "run_cli returned {result:?}");
assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"should_report_when_schema_version_mismatch",
fs,
console,
result,
));
}
31 changes: 30 additions & 1 deletion crates/biome_cli/tests/commands/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3565,7 +3565,7 @@ fn should_format_files_in_folders_ignored_by_linter() {
fs.insert(
biome_json.into(),
r#"{
"$schema": "https://biomejs.dev/schemas/1.6.1/schema.json",
"$schema": "https://biomejs.dev/schemas/0.0.0/schema.json",
"organizeImports": {
"enabled": true
},
Expand Down Expand Up @@ -3817,3 +3817,32 @@ fn applies_custom_bracket_spacing_for_graphql() {
result,
));
}

#[test]
fn should_report_when_schema_version_mismatch() {
let mut console = BufferConsole::default();
let mut fs = MemoryFileSystem::default();

let biome_json = Path::new("biome.json");
fs.insert(
biome_json.into(),
r#"{
"$schema": "https://biomejs.dev/schemas/0.0.1/schema.json"
}
"#,
);
let result = run_cli(
DynRef::Borrowed(&mut fs),
&mut console,
Args::from([("check")].as_slice()),
);

assert!(result.is_err(), "run_cli returned {result:?}");
assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"should_report_when_schema_version_mismatch",
fs,
console,
result,
));
}
29 changes: 29 additions & 0 deletions crates/biome_cli/tests/commands/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4327,3 +4327,32 @@ fn should_error_if_unchanged_files_only_with_changed_flag() {
result,
));
}

#[test]
fn should_report_when_schema_version_mismatch() {
let mut console = BufferConsole::default();
let mut fs = MemoryFileSystem::default();

let biome_json = Path::new("biome.json");
fs.insert(
biome_json.into(),
r#"{
"$schema": "https://biomejs.dev/schemas/0.0.1/schema.json"
}
"#,
);
let result = run_cli(
DynRef::Borrowed(&mut fs),
&mut console,
Args::from([("check")].as_slice()),
);

assert!(result.is_err(), "run_cli returned {result:?}");
assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"should_report_when_schema_version_mismatch",
fs,
console,
result,
));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: content
snapshot_kind: text
---
## `biome.json`

```json
{
"$schema": "https://biomejs.dev/schemas/0.0.1/schema.json"
}
```

# Termination Message

```block
internalError/io ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× No files were processed in the specified paths.



```

# Emitted Messages

```block
The configuration schema version does not match the CLI version.
Expect: 0.0.0
Found: 0.0.1

If you wish to update the configuration schema, setting the `$schema` option to the expected version.
```

```block
Checked 0 files in <TIME>. No fixes applied.
```
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: content
snapshot_kind: text
---
## `biome.json`

```json
{
"$schema": "https://biomejs.dev/schemas/1.6.1/schema.json",
"$schema": "https://biomejs.dev/schemas/0.0.0/schema.json",
"organizeImports": {
"enabled": true
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: content
snapshot_kind: text
---
## `biome.json`

```json
{
"$schema": "https://biomejs.dev/schemas/1.6.1/schema.json",
"$schema": "https://biomejs.dev/schemas/0.0.0/schema.json",
"organizeImports": {
"enabled": true
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: content
snapshot_kind: text
---
## `biome.json`

```json
{
"$schema": "https://biomejs.dev/schemas/0.0.1/schema.json"
}
```

# Termination Message

```block
internalError/io ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× No files were processed in the specified paths.



```

# Emitted Messages

```block
The configuration schema version does not match the CLI version.
Expect: 0.0.0
Found: 0.0.1

If you wish to update the configuration schema, setting the `$schema` option to the expected version.
```

```block
Checked 0 files in <TIME>. No fixes applied.
```
Loading
Loading