-
-
Notifications
You must be signed in to change notification settings - Fork 955
feat(analyse/json): add useRequiredScripts rule
#8281
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
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
931ead3
feat(analyse/json): add `useRequiredScripts` rule
tylersayshi 8441a12
added changeset
tylersayshi 6fbb503
Update crates/biome_json_analyze/src/lint/nursery/use_required_script…
tylersayshi 260906a
fix coderabbit comment
tylersayshi 509f4cd
[autofix.ci] apply automated fixes
autofix-ci[bot] 66c591f
fixes from review from dyc3
tylersayshi f5a1438
reorder the docstring sections
tylersayshi fc96d5a
from review
tylersayshi ba52b07
fix utf8path type
tylersayshi 6a0e199
fix diagnostics and update snapshots
tylersayshi 4709fb4
add note to docstring and changeset
tylersayshi d589a60
Merge remote-tracking branch 'upstream/main' into use-required-scripts
tylersayshi a0936fc
rerun gen-analyzer after merge
tylersayshi a4f4dd1
grammar issue
tylersayshi 2416055
second changeset file
tylersayshi 29b0ac6
find_member, and update snaps with grammar fix
tylersayshi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@biomejs/biome": patch | ||
| --- | ||
|
|
||
| Added the rule [`useRequiredScripts`](https://biomejs.dev/linter/rules/use-required-scripts/), which enforces presence of configurable entries in the `scripts` section of `package.json` files. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@biomejs/biome": patch | ||
| --- | ||
|
|
||
| Fixed [`noDuplicateDependencies`](https://biomejs.dev/linter/rules/no-duplicate-dependencies/) incorrectly triggering on files like `_package.json`. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
crates/biome_json_analyze/src/lint/nursery/use_required_scripts.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| use biome_analyze::{Ast, Rule, RuleDiagnostic, context::RuleContext, declare_lint_rule}; | ||
| use biome_console::markup; | ||
| use biome_json_syntax::{JsonRoot, TextRange}; | ||
| use biome_rowan::{AstNode, AstSeparatedList}; | ||
| use biome_rule_options::use_required_scripts::UseRequiredScriptsOptions; | ||
|
|
||
| use crate::utils::is_package_json; | ||
|
|
||
| /// State containing the missing scripts and the range to highlight | ||
| pub struct UseRequiredScriptsState { | ||
| /// The list of missing script names | ||
| pub missing_scripts: Vec<String>, | ||
| /// The range to highlight in the diagnostic (scripts object or root object) | ||
| pub range: TextRange, | ||
| } | ||
|
|
||
| declare_lint_rule! { | ||
| /// Enforce the presence of required scripts in package.json. | ||
| /// | ||
| /// This rule ensures that specified scripts are defined in the `scripts` section of a `package.json` file. | ||
| /// It's particularly useful in monorepo environments where consistency across workspaces is important. | ||
| /// | ||
| /// Without required scripts configured, this rule doesn't do anything. | ||
| /// | ||
| /// ## Examples | ||
| /// | ||
| /// ### Invalid | ||
| /// | ||
| /// ```json,options | ||
| /// { | ||
| /// "options": { | ||
| /// "requiredScripts": ["test", "build"] | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// ```json,use_options | ||
| /// { | ||
| /// "scripts": { | ||
| /// "test": "vitest" | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// ### Valid | ||
| /// | ||
| /// ```json,use_options | ||
| /// { | ||
| /// "scripts": { | ||
| /// "test": "vitest", | ||
| /// "build": "tsc" | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// ## Options | ||
| /// | ||
| /// ### `requiredScripts` | ||
| /// | ||
| /// An array of script names that must be present in the `scripts` section of `package.json`. | ||
| /// Default: `[]` (no scripts required) | ||
| /// | ||
| pub UseRequiredScripts { | ||
| version: "next", | ||
| name: "useRequiredScripts", | ||
| language: "json", | ||
| recommended: false, | ||
| } | ||
| } | ||
|
|
||
| impl Rule for UseRequiredScripts { | ||
| type Query = Ast<JsonRoot>; | ||
| type State = UseRequiredScriptsState; | ||
| type Signals = Option<Self::State>; | ||
| type Options = UseRequiredScriptsOptions; | ||
|
|
||
| fn run(ctx: &RuleContext<Self>) -> Self::Signals { | ||
| let query = ctx.query(); | ||
| let path = ctx.file_path(); | ||
| let options = ctx.options(); | ||
|
|
||
| if !is_package_json(path) { | ||
| return None; | ||
| } | ||
| if options.required_scripts.is_empty() { | ||
| return None; | ||
| } | ||
|
|
||
| let value = query.value().ok()?; | ||
| let object_value = value.as_json_object_value()?; | ||
|
|
||
| let scripts_member = object_value.find_member("scripts"); | ||
|
|
||
| // If there's no scripts section, all required scripts are missing | ||
| // Point to the root object in this case | ||
| let Some(scripts_member) = scripts_member else { | ||
| return Some(UseRequiredScriptsState { | ||
| missing_scripts: options.required_scripts.clone(), | ||
| range: object_value.range(), | ||
| }); | ||
| }; | ||
|
|
||
| let scripts_value = scripts_member.value().ok()?; | ||
| let scripts_object = scripts_value.as_json_object_value()?; | ||
|
|
||
| let existing_scripts: Vec<String> = scripts_object | ||
| .json_member_list() | ||
| .iter() | ||
| .flatten() | ||
| .filter_map(|member| { | ||
| let name = member.name().ok()?; | ||
| let text = name.inner_string_text().ok()?; | ||
| Some(text.to_string()) | ||
| }) | ||
| .collect(); | ||
|
|
||
| let missing_scripts: Vec<String> = options | ||
| .required_scripts | ||
| .iter() | ||
| .filter(|script| !existing_scripts.iter().any(|s| s == *script)) | ||
| .cloned() | ||
| .collect(); | ||
|
|
||
| if missing_scripts.is_empty() { | ||
| None | ||
| } else { | ||
| // Point to the scripts member when scripts exist but some are missing | ||
| Some(UseRequiredScriptsState { | ||
| missing_scripts, | ||
| range: scripts_member.range(), | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| fn diagnostic(_ctx: &RuleContext<Self>, state: &Self::State) -> Option<RuleDiagnostic> { | ||
| let missing_count = state.missing_scripts.len(); | ||
| let missing_list = state.missing_scripts.join(", "); | ||
|
|
||
| let message = if missing_count == 1 { | ||
| markup! { | ||
| "The required script "<Emphasis>{missing_list}</Emphasis>" is missing from package.json." | ||
| } | ||
| } else { | ||
| markup! { | ||
| "The required scripts "<Emphasis>{missing_list}</Emphasis>" are missing from package.json." | ||
| } | ||
| }; | ||
|
|
||
| Some( | ||
| RuleDiagnostic::new(rule_category!(), state.range, message).note(markup! { | ||
| "Consistent scripts across packages ensure that each can be run reliably from the root of our project. Add the missing script"{{if missing_count > 1 { "s" } else { "" }}}" to your package.json." | ||
| }), | ||
tylersayshi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) | ||
| } | ||
tylersayshi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
...n_analyze/tests/specs/nursery/useRequiredScripts/invalid/missing-all-scripts/package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "name": "test-package", | ||
| "scripts": { | ||
| "start": "node index.js" | ||
| } | ||
| } |
35 changes: 35 additions & 0 deletions
35
...lyze/tests/specs/nursery/useRequiredScripts/invalid/missing-all-scripts/package.json.snap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| --- | ||
| source: crates/biome_json_analyze/tests/spec_tests.rs | ||
| expression: package.json | ||
| --- | ||
| # Input | ||
| ```json | ||
| { | ||
| "name": "test-package", | ||
| "scripts": { | ||
| "start": "node index.js" | ||
| } | ||
| } | ||
|
|
||
| ``` | ||
|
|
||
| # Diagnostics | ||
| ``` | ||
| package.json:3:3 lint/nursery/useRequiredScripts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
|
|
||
| i The required scripts test, build are missing from package.json. | ||
|
|
||
| 1 │ { | ||
| 2 │ "name": "test-package", | ||
| > 3 │ "scripts": { | ||
| │ ^^^^^^^^^^^^ | ||
| > 4 │ "start": "node index.js" | ||
| > 5 │ } | ||
| │ ^ | ||
| 6 │ } | ||
| 7 │ | ||
|
|
||
| i Consistent scripts across packages ensure that each can be run reliably from the root of our project. Add the missing scripts to your package.json. | ||
|
|
||
|
|
||
| ``` |
14 changes: 14 additions & 0 deletions
14
...e/tests/specs/nursery/useRequiredScripts/invalid/missing-all-scripts/package.options.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "linter": { | ||
| "rules": { | ||
| "nursery": { | ||
| "useRequiredScripts": { | ||
| "level": "error", | ||
| "options": { | ||
| "requiredScripts": ["test", "build"] | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
6 changes: 6 additions & 0 deletions
6
...lyze/tests/specs/nursery/useRequiredScripts/invalid/missing-multiple-scripts/package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "name": "test-package", | ||
| "scripts": { | ||
| "test": "vitest" | ||
| } | ||
| } |
35 changes: 35 additions & 0 deletions
35
...tests/specs/nursery/useRequiredScripts/invalid/missing-multiple-scripts/package.json.snap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| --- | ||
| source: crates/biome_json_analyze/tests/spec_tests.rs | ||
| expression: package.json | ||
| --- | ||
| # Input | ||
| ```json | ||
| { | ||
| "name": "test-package", | ||
| "scripts": { | ||
| "test": "vitest" | ||
| } | ||
| } | ||
|
|
||
| ``` | ||
|
|
||
| # Diagnostics | ||
| ``` | ||
| package.json:3:3 lint/nursery/useRequiredScripts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
|
|
||
| i The required scripts build, lint are missing from package.json. | ||
|
|
||
| 1 │ { | ||
| 2 │ "name": "test-package", | ||
| > 3 │ "scripts": { | ||
| │ ^^^^^^^^^^^^ | ||
| > 4 │ "test": "vitest" | ||
| > 5 │ } | ||
| │ ^ | ||
| 6 │ } | ||
| 7 │ | ||
|
|
||
| i Consistent scripts across packages ensure that each can be run reliably from the root of our project. Add the missing scripts to your package.json. | ||
|
|
||
|
|
||
| ``` |
14 changes: 14 additions & 0 deletions
14
...ts/specs/nursery/useRequiredScripts/invalid/missing-multiple-scripts/package.options.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "linter": { | ||
| "rules": { | ||
| "nursery": { | ||
| "useRequiredScripts": { | ||
| "level": "error", | ||
| "options": { | ||
| "requiredScripts": ["test", "build", "lint"] | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
6 changes: 6 additions & 0 deletions
6
...analyze/tests/specs/nursery/useRequiredScripts/invalid/missing-single-script/package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "name": "test-package", | ||
| "scripts": { | ||
| "test": "vitest" | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.