Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@anthonyshew
Copy link
Contributor

@anthonyshew anthonyshew commented Dec 11, 2025

Summary

Turborepo users love going fast - so they love Biome.

However, a key validation tool in Turborepos is in our ESLint plugin, which finds usage of environment variables that aren't declared in Turborepo's caching computations.

This PR introduces a port for this rule to Biome, letting users know when they are potentially using environment variables in an unsafe way.

Test Plan

I've written a number of tests that should represent this rule's usage.

Additionally, I did some hand-testing. Note that I didn't set up my editor with the dev binary, so diagnostics for these are not showing in my IDE.

Undeclared environment variable usage CleanShot 2025-12-11 at 10 10 09
Allowing an arbitrary variable with "allowedEnvVars" CleanShot 2025-12-11 at 10 10 52
Declaring environment variable in root turbo.json CleanShot 2025-12-11 at 10 15 47
Declaring environment variable in Package Configuration (non-root turbo.json) CleanShot 2025-12-11 at 10 17 03
Declaring environment variable as passthrough CleanShot 2025-12-11 at 10 34 04

AI Usage

Nearly all of the code for this PR was generated.

I used the repo's generation tooling described in CONTRIBUTING.md for its various responsibilities.

Additionally, I used AI for nearly all but a few words in the source/test code:

  • Model: Claude Opus 4.5 through Vercel AI Gateway
  • Agent: Opencode

Steering/context provided:

  • Ensured CONTRIBUTING was in context
  • Provided the original ESLint rule's source code
  • Provided high-level knowledge of how Biome works architecturally from previous experience working with the repo
  • Incrementally tested by hand on a demo Turborepo to find missing functionality/bugs/etc. to steer.
  • Provided performance tuning instructions after verifying correct behavior

I have read and reviewed every line of this PR. If it's no good, you can blame me, not the bot. 😄

Docs

Included in code.

Open questions

  • Regex that can be provided to allowedEnvVars is different from the ESLint version in minor ways. I opted to use the existing regex handling code in this repo for this rule, rather than whatever library ESLint uses. Maintainers, please let me know if I need to change to full ESLint parity.
  • The ESLint version of this rule does not handle object destructuring from process.env. I choose to preserve that limitation in this port. I can take a look at lifting this limitation if maintainers prefer.
    • I also added tests around this limitation so that its specifically documented in the code. Do we want these?
  • Is the name of the rule okay? noUndeclaredEnvVars feels like a fairly "wide" name, though it is underneath the Turborepo domain. Happy to change the name if maintainer's prefer something else.
  • I'll call out that I used the existing tooling config loading code for package.json, tsconfig.json, etc. for loading turbo.json. It felt like it fit the model of how Biome's internals work to me, but I can see how turbo.json isn't as fundamental to the JS ecosystem as package.json and tsconfig.json are. Let me know if there's a different way I should go about this.

@changeset-bot
Copy link

changeset-bot bot commented Dec 11, 2025

🦋 Changeset detected

Latest commit: 795863d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added A-CLI Area: CLI A-Core Area: core A-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages A-Diagnostic Area: diagnostocis labels Dec 11, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Dec 11, 2025

CodSpeed Performance Report

Merging #8426 will not alter performance

Comparing anthonyshew:shew/c00a2 (795863d) with main (ec43141)

Summary

✅ 58 untouched
⏩ 95 skipped1

Footnotes

  1. 95 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Walkthrough

Adds Turborepo support and a new nursery lint rule noUndeclaredEnvVars. Introduces a TurboJson manifest model (parsing, caching, declaration checks) and threads it through NodeJsPackage, project layout, workspace server, test utilities and the JS analyzer. Treats turbo.json/turbo.jsonc as indexed manifests. Adds Turborepo RuleDomain and EslintTurbo RuleSource variants, exposes Turborepo services/queries, and includes comprehensive tests/fixtures covering declared, pass‑through and negation env‑var scenarios.

Possibly related PRs

Suggested reviewers

  • ematipico
  • dyc3

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: introducing a new Turborepo domain and a noUndeclaredEnvVars lint rule.
Description check ✅ Passed The description is well-related to the changeset, explaining the motivation (Turborepo ESLint rule port), implementation approach, testing strategy, and acknowledging AI-assisted code generation with author review.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b75602 and 795863d.

⛔ Files ignored due to path filters (22)
  • crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs is excluded by !**/migrate/eslint_any_rule_to_biome.rs and included by **
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/domain_selector.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_configuration/tests/invalid/domains.json.snap is excluded by !**/*.snap and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_js_analyze/src/lint/nursery.rs is excluded by !**/nursery.rs and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithNegation.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithTurboJson.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validNoTurboJson.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithLegacyPipeline.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithOptions.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithPassThroughEnv.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJson.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/security/noSecrets/valid.js.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (43)
  • .changeset/rich-icons-talk.md (1 hunks)
  • crates/biome_analyze/src/rule.rs (11 hunks)
  • crates/biome_fs/src/path.rs (2 hunks)
  • crates/biome_js_analyze/src/lib.rs (3 hunks)
  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1 hunks)
  • crates/biome_js_analyze/src/services/mod.rs (1 hunks)
  • crates/biome_js_analyze/src/services/turborepo.rs (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalid.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalid.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithNegation.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithNegation.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithTurboJson.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithTurboJson.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validNoTurboJson.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithLegacyPipeline.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithLegacyPipeline.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithOptions.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithOptions.options.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithOptions.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithPassThroughEnv.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithPassThroughEnv.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJson.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJson.turbo.json (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.turbo.jsonc (1 hunks)
  • crates/biome_js_analyze/tests/specs/security/noSecrets/valid.js (1 hunks)
  • crates/biome_json_syntax/src/file_source.rs (1 hunks)
  • crates/biome_package/src/lib.rs (1 hunks)
  • crates/biome_package/src/node_js_package/mod.rs (3 hunks)
  • crates/biome_package/src/node_js_package/turbo_json.rs (1 hunks)
  • crates/biome_project_layout/src/project_layout.rs (10 hunks)
  • crates/biome_rule_options/src/lib.rs (1 hunks)
  • crates/biome_rule_options/src/no_undeclared_env_vars.rs (1 hunks)
  • crates/biome_service/src/workspace/server.rs (2 hunks)
  • crates/biome_test_utils/src/lib.rs (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalid.turbo.json
🚧 Files skipped from review as they are similar to previous changes (29)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithLegacyPipeline.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithNegation.turbo.json
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithLegacyPipeline.js
  • .changeset/rich-icons-talk.md
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.turbo.jsonc
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.js
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validNoTurboJson.js
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithOptions.js
  • crates/biome_service/src/workspace/server.rs
  • crates/biome_js_analyze/tests/specs/security/noSecrets/valid.js
  • crates/biome_js_analyze/src/services/mod.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJson.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithTurboJson.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJson.js
  • crates/biome_json_syntax/src/file_source.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithOptions.options.json
  • crates/biome_fs/src/path.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.js
  • crates/biome_js_analyze/src/lib.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js
  • crates/biome_rule_options/src/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithTurboJson.js
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithPassThroughEnv.js
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalid.js
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithNegation.js
  • crates/biome_package/src/lib.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.js
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithOptions.turbo.json
🧰 Additional context used
📓 Path-based instructions (1)
crates/**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update inline rustdoc documentation for rules, assists, and their options when adding new features or changing existing features in Rust crates

Files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_package/src/node_js_package/mod.rs
  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_package/src/node_js_package/turbo_json.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
  • crates/biome_analyze/src/rule.rs
  • crates/biome_test_utils/src/lib.rs
🧠 Learnings (45)
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Store type data in linear vectors instead of using recursive data structures with `Arc` for improved data locality and performance

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Avoid unnecessary string allocations by comparing against `&str` or `TokenText` instead of calling `to_string()` which allocates heap memory

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeReference` instead of `Arc` for types that reference other types to avoid stale cache issues when modules are replaced

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_package/src/node_js_package/mod.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use language tags in documentation code blocks (js, ts, tsx, json, css) and order properties consistently as: language, then `expect_diagnostic`, then options modifiers, then `ignore`, then `file=path`

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_package/src/node_js_package/mod.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For tokens that are not mandatory, use helper functions instead of hardcoding

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace*.rs : Implement the Workspace trait in the Biome Service to manage internal state of projects, including open documents, project layout instances, and module graph instances

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import the `FormatNode` trait and implement it for your Node when creating formatters in biome_js_formatter

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_package/src/node_js_package/mod.rs
  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.jsonc : Use `.jsonc` files in test specs with code snippets as array of strings to test rules in script environment (no import/export syntax)

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithPassThroughEnv.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.js
  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-12-04T13:29:49.287Z
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithPassThroughEnv.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.js
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.{js,ts,tsx,jsx,json,css} : Test rules using snapshot tests via the `insta` library with test cases in `tests/specs/<group>/<rule_name>/` directories prefixed by `invalid` or `valid`

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.js
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUndeclared` prefix for rules that report undefined entities (e.g., `noUndeclaredVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Deprecate rules by adding a `deprecated` field to the `declare_lint_rule!` macro with a message explaining the reason for deprecation (e.g., 'Use the rule noAnotherVar')

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnused` prefix for rules that report unused entities (e.g., `noUnusedVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Check if a variable is global before banning it to avoid false positives when the variable is redeclared in local scope; use the semantic model to verify global scope

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.turbo.json
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.turbo.json
  • crates/biome_js_analyze/src/services/turborepo.rs
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.js
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRestricted` prefix for rules that report user-banned entities (e.g., `noRestrictedGlobals`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : The `declare_lint_rule!` macro must include metadata fields: `version` (set to 'next'), `name` (rule identifier), `language` (applicable language), `recommended` (boolean), and optional fields like `severity`, `fix_kind`, `sources`, `domains`, and `deprecated`

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnknown` prefix for rules that report mistyped entities in CSS (e.g., `noUnknownUnit`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnsafe` prefix for rules that report code leading to runtime failures (e.g., `noUnsafeOptionalChaining`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Framework-specific rules should be named using the `use` or `no` prefix followed by the framework name (e.g., `noVueReservedProps`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noDuplicate` prefix for rules that report duplication overriding previous occurrences (e.g., `noDuplicateObjectKeys`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Rules should use the `no` prefix naming convention when the sole intention is to forbid a single concept (e.g., `noDebugger` to disallow debugger statements)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Wrap optional rule option fields in `Option<_>` to properly track set vs unset options during configuration merging

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noInvalid` prefix for rules that report runtime errors from mistyping (e.g., `noInvalidConstructorSuper`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use `Semantic<T>` query type instead of `Ast<T>` when a rule needs to access the semantic model for binding references and scope information

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Implement custom `Queryable` types and `Visitor` traits for rules requiring deep AST inspection to avoid redundant traversal passes

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Implement watcher tests for workspace methods in watcher.tests.rs and end-to-end tests in LSP tests

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : When using multiple services in a rule, use `ctx.get_service::<ServiceType>()` to retrieve services running in the second phase when query runs during that phase

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : For rules ported from other ecosystems like ESLint or Clippy, add a `sources` field with `RuleSource` metadata using `.same()` for identical behavior or `.inspired()` for different behavior

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Document rules with a one-line brief description in the first paragraph of the doc comment, followed by detailed paragraphs, `## Examples` section with `### Invalid` and `### Valid` subsections, and optional `## Options` section

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-12-12T10:11:05.549Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-12T10:11:05.549Z
Learning: Applies to crates/**/*.rs : Update inline rustdoc documentation for rules, assists, and their options when adding new features or changing existing features in Rust crates

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/specs/**/options.json : Create an `options.json` file (formatted as `biome.json`) in test specification folders to apply non-default formatting options to all test files in that folder

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.turbo.json
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use `rule_category!()` macro instead of dynamic string parsing to refer to rule diagnostic categories for compile-time validation

Applied to files:

  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Set rule severity to `error` for correctness/security/a11y rules, `warn` for suspicious/performance rules, `info` for style/complexity rules, and `info` for actions

Applied to files:

  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Rules should use the `use` prefix naming convention when the sole intention is to mandate a single concept (e.g., `useValidLang` to enforce valid HTML lang attribute values)

Applied to files:

  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUseless` prefix for rules that report unnecessary code that could be removed or simplified (e.g., `noUselessConstructor`)

Applied to files:

  • crates/biome_analyze/src/rule.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/Cargo.toml : Include development dependencies in `Cargo.toml` for formatter tests: `biome_formatter_test`, `biome_<language>_factory`, `biome_<language>_parser`, `biome_parser`, `biome_service`, `countme`, `iai`, `quickcheck`, `quickcheck_macros`, and `tests_macros`

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Distinguish between `TypeData::Unknown` and `TypeData::UnknownKeyword` to measure inference effectiveness versus explicit user-provided unknown types

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:04:57.309Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:04:57.309Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Use helper types from the biome_diagnostics::v2 module (CodeFrameAdvice, CommandAdvice, DiffAdvice, LogAdvice) or implement the Advices trait yourself for custom advice handling

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/spec_tests.rs : Use the `tests_macros::gen_tests!` macro in `spec_tests.rs` to generate test functions for each specification file matching the pattern `tests/specs/<language>/**/*.<ext>`

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to 'fix' the code; if a token/node is known to be mandatory but is missing, return `None` instead

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeReference` variants (`Qualifier`, `Resolved`, `Import`, `Unknown`) to represent different phases of type resolution

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeData::Unknown` to indicate when type inference falls short or is not implemented

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-08-20T16:24:59.781Z
Learnt from: arendjr
Repo: biomejs/biome PR: 7266
File: crates/biome_js_type_info/src/type.rs:94-102
Timestamp: 2025-08-20T16:24:59.781Z
Learning: In crates/biome_js_type_info/src/type.rs, the flattened_union_variants() method returns TypeReference instances that already have the correct module IDs applied to them. These references should be used directly with resolver.resolve_reference() without applying additional module ID transformations, as variant references may originate from nested unions in different modules.

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Always apply the correct `ResolverId` when retrieving raw type data from `ResolvedTypeData.as_raw_data()` to prevent panics during subsequent resolution calls

Applied to files:

  • crates/biome_test_utils/src/lib.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : When using `ResolvedTypeData`, track the `ResolverId` to ensure subsequent resolver calls use the correct context

Applied to files:

  • crates/biome_test_utils/src/lib.rs
🧬 Code graph analysis (5)
crates/biome_project_layout/src/project_layout.rs (2)
crates/biome_package/src/node_js_package/turbo_json.rs (1)
  • clone (61-77)
crates/biome_package/src/node_js_package/mod.rs (3)
  • insert_serialized_turbo_json (46-58)
  • manifest (98-100)
  • without_turbo_json (69-76)
crates/biome_package/src/node_js_package/mod.rs (2)
crates/biome_project_layout/src/project_layout.rs (1)
  • insert_serialized_turbo_json (345-387)
crates/biome_package/src/node_js_package/turbo_json.rs (1)
  • deserialize_manifest (116-127)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (2)
crates/biome_js_syntax/src/expr_ext.rs (1)
  • global_identifier (1896-1916)
crates/biome_js_analyze/src/services/turborepo.rs (1)
  • model (59-61)
crates/biome_package/src/node_js_package/turbo_json.rs (1)
crates/biome_js_analyze/src/services/turborepo.rs (2)
  • deserialize_from_json_str (129-129)
  • is_env_var_declared (47-51)
crates/biome_js_analyze/src/services/turborepo.rs (1)
crates/biome_package/src/node_js_package/turbo_json.rs (2)
  • is_env_var_declared (254-285)
  • parse (141-155)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Test Node.js API
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: End-to-end tests
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Documentation
  • GitHub Check: Check Dependencies
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Check JS Files
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_package)
🔇 Additional comments (32)
crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/valid.turbo.json (1)

1-2: LGTM.

This serves as a proper baseline fixture—a valid turbo.json with no additional environment variable declarations, which is exactly what you need to test the rule's behaviour on the simplest valid case.

crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDestructuring.turbo.json (1)

1-3: LGTM!

Simple and appropriate fixture for testing the rule's documented limitation with destructuring patterns. The empty globalEnv array correctly sets up the test scenario.

crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validDynamicAccess.turbo.json (1)

1-3: Test fixture looks good.

Valid JSON configuration testing the edge case where dynamic access occurs with an empty globalEnv declaration. Filename and structure align with the test suite pattern.

crates/biome_analyze/src/rule.rs (2)

168-220: LGTM – EslintTurbo source addition follows existing patterns.

The new EslintTurbo variant and its implementations (Display, as_rule_name, to_namespaced_rule_name, to_rule_url) are consistent with other ESLint plugin sources in the codebase.


473-587: LGTM – Turborepo domain implementation is consistent.

The new Turborepo domain follows the established pattern for other domains. The manifest dependency ("turbo", ">=1.0.0") is appropriate for auto-enabling Turborepo rules when the dependency is detected.

crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithPassThroughEnv.turbo.json (1)

1-8: LGTM – Valid test fixture.

This turbo.json fixture appropriately exercises the rule's handling of task-level env and passThroughEnv declarations, including wildcard patterns.

crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.turbo.json (1)

1-3: LGTM – Valid test fixture.

This fixture correctly tests global-level globalPassThroughEnv declarations with wildcard patterns.

crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithGlobalPassThroughEnv.js (1)

1-14: LGTM – Comprehensive test coverage.

This fixture appropriately exercises both process.env and import.meta.env access patterns, including wildcard pattern matching for variables declared in globalPassThroughEnv.

crates/biome_test_utils/src/lib.rs (1)

309-342: LGTM – Turbo.json discovery logic is sound.

The implementation correctly:

  • Checks for turbo.json first, then falls back to turbo.jsonc
  • Handles parsing errors by collecting diagnostics
  • Inserts the parsed configuration into the project layout

The approach of deserialising before insertion (using insert_turbo_json) is appropriate for test utilities.

crates/biome_project_layout/src/project_layout.rs (2)

344-387: LGTM – Past issue resolved; implementation is solid.

The insert_serialized_turbo_json method now correctly accepts filename as a parameter (line 349) and uses it when joining paths (lines 368, 379). This addresses the previous concern about hardcoding "turbo.json" for turbo.jsonc files.

The use of Arc<TurboJson> for shared ownership is appropriate, and the implementation follows the established patterns for manifest and tsconfig handling.


88-140: LGTM – Comprehensive accessor methods.

The new turbo.json accessor methods are well-designed:

  • find_turbo_json_for_path returns the nearest turbo.json
  • find_all_turbo_json_for_path returns all turbo.json files in the ancestor chain (useful for Turborepo's hierarchical configuration)
  • get_turbo_json_for_package retrieves the turbo.json for a specific package path

All methods correctly handle Arc<TurboJson> cloning for shared ownership.

crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (3)

12-86: LGTM – Rule metadata and documentation are excellent.

The rule declaration follows all guidelines:

  • Correct use of noUndeclared prefix for undefined entities
  • Metadata includes all required fields (version, name, language, sources, domains, severity)
  • Uses RuleSource::EslintTurbo("no-undeclared-env-vars").same() indicating identical logic to the ESLint version
  • Comprehensive documentation with clear examples and options

Based on learnings.


186-225: LGTM – Efficient default checking implementation.

The implementation correctly:

  • Uses binary_search on the sorted DEFAULT_ALLOWED_ENV_VARS array (lines 186-188, 208)
  • Uses starts_with for prefix matching instead of regex for better performance (lines 192-203, 218-221)
  • Handles the special case for "VERCEL" (lines 213-215)

This addresses the performance concerns from past reviews.


100-150: LGTM – Rule logic is sound.

The implementation correctly:

  • Skips when no turbo.json is present (lines 102-104), ensuring the rule only applies to Turborepo projects
  • Validates both process.env and import.meta.env access patterns
  • Checks defaults, options, and turbo.json declarations in the right order
  • Uses the global identifier check to avoid false positives when process is shadowed
crates/biome_package/src/node_js_package/mod.rs (2)

3-11: LGTM – Module declaration follows existing patterns.

The addition of the turbo_json module and its public re-export follows the same pattern as package_json and tsconfig_json. The use of Arc for shared ownership is appropriate.


46-76: LGTM – Implementation is consistent with existing manifest handling.

The new methods follow established patterns:

  • insert_serialized_turbo_json (lines 46-58) mirrors the implementation of insert_serialized_tsconfig
  • without_turbo_json (lines 69-76) follows the pattern of without_tsconfig
  • The without_tsconfig method correctly preserves turbo_json (line 65)

All diagnostic handling and Arc wrapping is consistent with the codebase.

crates/biome_js_analyze/src/services/turborepo.rs (6)

1-5: Module documentation looks good.

The rustdoc explaining the module's purpose and how TurborepoServices integrates with lint rules is clear and helpful.


36-51: Well-documented aggregation logic.

The doc comment at lines 42-44 clearly explains why all configs are checked (task-level env and passThroughEnv can be in package-level configs). The any() semantics are sensible for this use case.


64-83: Standard service retrieval pattern.

Correctly retrieves both TurboJson configs and SemanticModel from the service bag with appropriate error handling.


91-118: Queryable implementation follows established patterns.

The visitor wiring and query key setup mirror the existing Semantic<N> pattern, which is the right approach for a service that needs semantic model access.


197-211: Cross-config negation semantics clearly documented.

The test explicitly documents that when root negates a variable but package declares it, the declaration wins. This is a deliberate design choice worth keeping visible.


254-308: Excellent regression test.

The detailed comments explaining the monorepo scenario and the bug being prevented make this a valuable regression test for future maintainers.

crates/biome_package/src/node_js_package/turbo_json.rs (10)

14-21: Clean separation of positive and negation patterns.

Using FxHashSet for O(1) exact match lookups is a good choice. The wildcard matching still requires iteration, but that's unavoidable.


23-58: Forward-compatible struct definition.

The unknown_fields = "allow" attribute ensures Biome won't break when Turborepo adds new fields. Good documentation on each field's purpose.


60-78: Correct handling of OnceLock in Clone.

Since OnceLock doesn't implement Clone, this manual implementation correctly preserves the cached value when present. Nicely done.


113-138: Standard Manifest implementation.

Follows the established pattern used by other configuration files in the codebase.


140-155: Parser options support JSONC.

Allowing comments and trailing commas correctly handles turbo.jsonc files.


169-230: Thorough env var collection.

All sources are covered: globalEnv, globalPassThroughEnv, task-level env and passThroughEnv, plus legacy pipeline support. The OnceLock ensures this work is only done once.


254-285: Correct negation precedence and wildcard matching.

The implementation correctly handles:

  1. Exact negation matches
  2. Wildcard negation matches (e.g., !SECRET_*)
  3. Exact positive matches
  4. Wildcard positive matches (e.g., FOO_*)

The trailing-wildcard-only pattern (* suffix) matches Turborepo's documented behaviour.


232-245: Clear public API.

The doc comment explicitly states that only positive patterns are returned, not negations. This prevents confusion for callers.


328-369: Thorough negation testing.

The tests for negation behaviour (exact match, wildcard, order independence) provide good coverage and document the expected semantics clearly.


371-503: Comprehensive pass-through env testing.

Good coverage of globalPassThroughEnv and task-level passThroughEnv, including combinations with regular env declarations.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1)

191-217: Consider simplifying the pattern definitions.

The individual LazyLock<Regex> statics work correctly, but there's some repetition. You could consider using starts_with checks for simple prefix patterns instead of full regex, which would be faster. However, this is minor since LazyLock ensures one-time compilation.

For simple prefix patterns, a string check could be more efficient:

 fn is_env_var_allowed_by_defaults(env_var: &str) -> bool {
     if DEFAULT_ALLOWED_ENV_VARS.contains(&env_var) {
         return true;
     }

+    // Simple prefix checks (faster than regex)
+    const PREFIX_PATTERNS: &[&str] = &[
+        "NEXT_PUBLIC_", "VITE_", "REACT_APP_", "VUE_APP_",
+        "NUXT_", "GATSBY_", "EXPO_PUBLIC_",
+    ];
+    if PREFIX_PATTERNS.iter().any(|p| env_var.starts_with(p)) {
+        return true;
+    }
+
+    // VERCEL special case: exact match or prefix
+    if env_var == "VERCEL" || env_var.starts_with("VERCEL_") {
+        return true;
+    }
+
-    for pattern in DEFAULT_ALLOWED_PATTERNS {
-        if pattern.is_match(env_var) {
-            return true;
-        }
-    }
-
     false
 }
crates/biome_project_layout/src/project_layout.rs (1)

385-396: Good addition of turbo.jsonc support.

The pattern match correctly handles both turbo.json and turbo.jsonc. Minor nit: the doc comment on line 385 only mentions turbo.json, but the code also handles turbo.jsonc.

-    /// Only returns `true` for `package.json`, `tsconfig.json`, and `turbo.json` manifests.
+    /// Only returns `true` for `package.json`, `tsconfig.json`, `turbo.json`, and `turbo.jsonc` manifests.

Copy link
Contributor

@dyc3 dyc3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Nice first draft.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
crates/biome_service/src/workspace/server.rs (1)

860-880: Turbo manifest wiring looks sound; please double‑check turbo.jsonc end‑to‑end.

The new turbo.json / turbo.jsonc branch in update_project_layout mirrors the existing package.json / tsconfig.json handling and correctly threads the actual filename into insert_serialized_turbo_json, which fixes the earlier hard‑coded "turbo.json" issue.

One thing worth a quick sanity‑check: this path relies on the surrounding plumbing treating turbo.jsonc as a manifest (e.g. BiomePath::is_manifest and any JSON file‑source detection). If those weren’t updated alongside this change, .jsonc files might never hit this arm even though is_indexed now recognises them.

If you want, I can sketch a small rg/ast-grep script to verify turbo.jsonc is covered in the relevant helpers.

crates/biome_project_layout/src/project_layout.rs (1)

392-408: Doc comment slightly lags behaviour w.r.t. turbo.jsonc.

The implementation of is_indexed correctly treats both turbo.json and turbo.jsonc as indexed manifests, but the comment only mentions turbo.json. Might be worth explicitly calling out turbo.jsonc to avoid confusion for future readers.

-    /// Only returns `true` for `package.json`, `tsconfig.json`, and `turbo.json` manifests.
+    /// Only returns `true` for `package.json`, `tsconfig.json`, and `turbo.json`/`turbo.jsonc` manifests.
crates/biome_js_analyze/src/services/turborepo.rs (1)

20-52: Root‑only env‑var resolution for Turborepo is a good correction.

Constraining is_env_var_declared to the last (root) TurboJson config, while still using TurboJson::is_env_var_declared so task‑level env and wildcards/negations are honoured, lines up with Turborepo’s semantics and fixes the earlier “package can override root” issue. Relying on the configs being ordered closest→root is reasonable, and you’ve documented that expectation clearly.

If you ever want extra belt‑and‑braces, a debug assert about the ordering at construction time could catch mis‑wired services early, but it’s not strictly necessary.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c66e8f5 and 7c812bb.

📒 Files selected for processing (4)
  • .changeset/rich-icons-talk.md (1 hunks)
  • crates/biome_js_analyze/src/services/turborepo.rs (1 hunks)
  • crates/biome_project_layout/src/project_layout.rs (10 hunks)
  • crates/biome_service/src/workspace/server.rs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
.changeset/**/*.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

.changeset/**/*.md: Create changesets for user-facing changes using just new-changeset; use headers with #### or ##### only; keep descriptions concise (1-3 sentences) and focus on user-facing changes
Use past tense when describing what was done ('Added new feature'), present tense when describing Biome behavior ('Biome now supports'); end sentences with a full stop
For new lint rules, show an example of an invalid case in an inline code snippet or code block; for rule changes, demonstrate what is now invalid or valid; for formatter changes, use a diff code block

Files:

  • .changeset/rich-icons-talk.md
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use the dbg!() macro for debugging output during testing, and pass the --show-output flag to cargo to view debug output
Use cargo t or cargo test to run tests; for a single test, pass the test name after the test command
Use snapshot testing with the insta crate; run cargo insta accept, cargo insta reject, or cargo insta review to manage snapshot changes
Write doctests as doc comments with code blocks; the code inside code blocks will be run during the testing phase
Use just f (alias for just format) to format Rust and TOML files before committing

Files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_service/src/workspace/server.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
crates/biome_service/src/workspace/server.rs

📄 CodeRabbit inference engine (crates/biome_service/CONTRIBUTING.md)

Use WorkspaceServer implementation for maintaining workspace state in daemon mode and CLI daemonless mode

Files:

  • crates/biome_service/src/workspace/server.rs
🧠 Learnings (27)
📓 Common learnings
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to **/*.tsx : For Node.js package development, build WebAssembly bindings and JSON-RPC bindings; run tests against compiled files after implementing features or bug fixes
📚 Learning: 2025-11-28T09:08:10.091Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to .changeset/**/*.md : Create changesets for user-facing changes using `just new-changeset`; use headers with `####` or `#####` only; keep descriptions concise (1-3 sentences) and focus on user-facing changes

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Commit rule changes with message format: `feat(biome_<crate>): <ruleName>` to follow Biome's conventional commit style

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-28T09:08:10.091Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to .changeset/**/*.md : For new lint rules, show an example of an invalid case in an inline code snippet or code block; for rule changes, demonstrate what is now invalid or valid; for formatter changes, use a `diff` code block

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-28T09:08:10.091Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to .changeset/**/*.md : Use past tense when describing what was done ('Added new feature'), present tense when describing Biome behavior ('Biome now supports'); end sentences with a full stop

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Deprecate rules by adding a `deprecated` field to the `declare_lint_rule!` macro with a message explaining the reason for deprecation (e.g., 'Use the rule noAnotherVar')

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUndeclared` prefix for rules that report undefined entities (e.g., `noUndeclaredVariables`)

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noInvalid` prefix for rules that report runtime errors from mistyping (e.g., `noInvalidConstructorSuper`)

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-08-05T14:43:29.581Z
Learnt from: dyc3
Repo: biomejs/biome PR: 7081
File: packages/@biomejs/biome/configuration_schema.json:7765-7781
Timestamp: 2025-08-05T14:43:29.581Z
Learning: The file `packages/biomejs/biome/configuration_schema.json` is auto-generated and should not be manually edited or reviewed for schema issues; any changes should be made at the code generation source.

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-09-25T12:32:59.003Z
Learnt from: arendjr
Repo: biomejs/biome PR: 7593
File: crates/biome_service/src/workspace/server.rs:1306-1306
Timestamp: 2025-09-25T12:32:59.003Z
Learning: In the biomejs/biome project, do not flag compilation errors during code review as they are handled by the existing test infrastructure and CI. Focus on other code quality aspects instead.

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Store type data in linear vectors instead of using recursive data structures with `Arc` for improved data locality and performance

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Avoid unnecessary string allocations by comparing against `&str` or `TokenText` instead of calling `to_string()` which allocates heap memory

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeReference` instead of `Arc` for types that reference other types to avoid stale cache issues when modules are replaced

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_service/src/workspace/server.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For tokens that are not mandatory, use helper functions instead of hardcoding

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use language tags in documentation code blocks (js, ts, tsx, json, css) and order properties consistently as: language, then `expect_diagnostic`, then options modifiers, then `ignore`, then `file=path`

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace*.rs : Implement the Workspace trait in the Biome Service to manage internal state of projects, including open documents, project layout instances, and module graph instances

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
  • crates/biome_service/src/workspace/server.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import the `FormatNode` trait and implement it for your Node when creating formatters in biome_js_formatter

Applied to files:

  • crates/biome_project_layout/src/project_layout.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Implement watcher tests for workspace methods in watcher.tests.rs and end-to-end tests in LSP tests

Applied to files:

  • crates/biome_service/src/workspace/server.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.jsonc : Use `.jsonc` files in test specs with code snippets as array of strings to test rules in script environment (no import/export syntax)

Applied to files:

  • crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to 'fix' the code; if a token/node is known to be mandatory but is missing, return `None` instead

Applied to files:

  • crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeData::Unknown` to indicate when type inference falls short or is not implemented

Applied to files:

  • crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Distinguish between `TypeData::Unknown` and `TypeData::UnknownKeyword` to measure inference effectiveness versus explicit user-provided unknown types

Applied to files:

  • crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Check if a variable is global before banning it to avoid false positives when the variable is redeclared in local scope; use the semantic model to verify global scope

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Implement custom `Queryable` types and `Visitor` traits for rules requiring deep AST inspection to avoid redundant traversal passes

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use `Semantic<T>` query type instead of `Ast<T>` when a rule needs to access the semantic model for binding references and scope information

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Implement the `Merge` trait for rule options to define how options from extended configuration merge with user configuration (usually reset instead of extend)

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRestricted` prefix for rules that report user-banned entities (e.g., `noRestrictedGlobals`)

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
🧬 Code graph analysis (3)
crates/biome_project_layout/src/project_layout.rs (2)
crates/biome_package/src/node_js_package/turbo_json.rs (1)
  • clone (61-77)
crates/biome_package/src/node_js_package/mod.rs (3)
  • insert_serialized_turbo_json (46-58)
  • manifest (98-100)
  • without_turbo_json (69-76)
crates/biome_service/src/workspace/server.rs (1)
crates/biome_service/src/diagnostics.rs (2)
  • not_found (117-119)
  • not_found (743-748)
crates/biome_js_analyze/src/services/turborepo.rs (2)
crates/biome_package/src/node_js_package/turbo_json.rs (2)
  • is_env_var_declared (254-285)
  • parse (141-155)
crates/biome_rowan/src/ast/mod.rs (1)
  • unwrap_cast (200-212)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: End-to-end tests
  • GitHub Check: Documentation
  • GitHub Check: Check Dependencies
  • GitHub Check: Check JS Files
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_package)
🔇 Additional comments (8)
crates/biome_service/src/workspace/server.rs (1)

2247-2250: Indexing hook for turbo.json / turbo.jsonc is consistent with layout semantics.

Routing package.json, tsconfig.json, turbo.json, and turbo.jsonc through project_layout.is_indexed while leaving everything else to module_graph.contains matches how you treat other manifest files and ensures turbo manifests participate properly in layout‑based indexing.

crates/biome_project_layout/src/project_layout.rs (5)

88-140: Turbo manifest lookup API is clear and matches Turborepo’s model.

find_turbo_json_for_path, find_all_turbo_json_for_path, and get_turbo_json_for_package mirror the existing package.json/tsconfig helpers and correctly rely on path.ancestors() to give closest‑first behaviour. Using Arc<TurboJson> here is a good fit for sharing parsed config across services without extra cloning.


146-216: Preserving turbo_json when updating manifests/tsconfig keeps package state coherent.

The changes to insert_node_manifest, insert_tsconfig, insert_serialized_node_manifest, and insert_serialized_tsconfig correctly carry over any existing turbo_json field when rebuilding NodeJsPackage. This matches how you already preserve the complementary manifest/tsconfig field and avoids silently dropping Turbo config on unrelated updates.


218-255: insert_turbo_json follows existing layout patterns and uses Arc appropriately.

The new insert_turbo_json helper mirrors the other insertors: it preserves existing manifest/tsconfig, resets diagnostics, and stores turbo_json as an Arc, reusing the same instance across callers. That keeps the layout API consistent and avoids unnecessary parsing when a consumer already has a TurboJson value.


341-387: insert_serialized_turbo_json correctly tracks the actual filename (including .jsonc).

Accepting filename and using path.join(filename) fixes the previous hard‑coded "turbo.json" path and ensures the stored path matches either turbo.json or turbo.jsonc. Reusing existing manifest/tsconfig from data.node_package keeps all three pieces of package metadata in sync.


440-468: Turbo query/removal helpers round out the layout API nicely.

query_turbo_json_for_path and remove_turbo_json_from_package mirror the existing tsconfig counterparts and correctly leverage NodeJsPackage::without_turbo_json. This gives analysers a clean way to consult and invalidate turbo state without duplicating traversal logic.

crates/biome_js_analyze/src/services/turborepo.rs (2)

55-109: Service wiring and query integration follow the existing analyser patterns.

FromServices correctly requires both the TurboJson config vec and the SemanticModel, and Phase::Semantic matches the need for semantic data. The Queryable impl for Turborepo<N> reuses the standard SemanticModelBuilderVisitor + SyntaxVisitor combo and delegates unwrap_match to N::unwrap_cast, so rules can opt into turbo‑aware queries without custom plumbing.


111-243: Tests give good coverage of the env‑var semantics and ordering contract.

The unit tests cover root‑vs‑package precedence, task‑specific env, wildcards, negation, empty/no‑config cases, and multi‑level layouts. Using create_services with ordered Arc<TurboJson> values makes the “root is last” contract explicit, which should help prevent regressions if the layout side ever changes how it builds that vector.

@github-actions github-actions bot added A-Parser Area: parser L-JSON Language: JSON and super languages labels Dec 11, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
.changeset/rich-icons-talk.md (1)

5-5: Address the feedback: add a full stop, include an invalid example, and link to the rule.

The changeset still needs the improvements flagged in the previous reviews—specifically, a full stop at the end, a concrete example of unsafe environment variable usage, and a link to the rule documentation.

Apply this diff to align with changeset guidelines:

-Added a Turborepo domain and a new "noUndeclaredEnvVars" rule in it for warning users of unsafe environment variable usage in Turborepos.
+Added a Turborepo domain and a new [`noUndeclaredEnvVars`](https://biomejs.dev/linter/rules/no-undeclared-env-vars/) rule for warning users of unsafe environment variable usage in Turborepos. For example, `process.env.UNDECLARED_VAR` now triggers a diagnostic when the variable is not declared in turbo.json.

Based on learnings and coding guidelines.

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1)

205-224: Consider consolidating the VERCEL check.

The special case for VERCEL on lines 212–214 could be simplified by adding it to DEFAULT_ALLOWED_ENV_VARS instead. This would be more consistent and slightly more efficient, as it would be checked via binary search along with the other allowed variables.

Apply this diff:

 const DEFAULT_ALLOWED_ENV_VARS: &[&str] = &[
-    "CI", "HOME", "NODE_ENV", "PATH", "PWD", "SHELL", "TZ", "USER",
+    "CI", "HOME", "NODE_ENV", "PATH", "PWD", "SHELL", "TZ", "USER", "VERCEL",
 ];

 /// Checks if an environment variable is allowed based on default values and patterns
 fn is_env_var_allowed_by_defaults(env_var: &str) -> bool {
     // Check against default allowed env vars (sorted, so binary search is used)
     if DEFAULT_ALLOWED_ENV_VARS.binary_search(&env_var).is_ok() {
         return true;
     }

-    // Check for exact match "VERCEL" (CI provider)
-    if env_var == "VERCEL" {
-        return true;
-    }
-
     // Check against default allowed prefixes
     for prefix in DEFAULT_ALLOWED_PREFIXES {
         if env_var.starts_with(prefix) {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c812bb and 0ffa26d.

📒 Files selected for processing (3)
  • .changeset/rich-icons-talk.md (1 hunks)
  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1 hunks)
  • crates/biome_json_syntax/src/file_source.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use the dbg!() macro for debugging output during testing, and pass the --show-output flag to cargo to view debug output
Use cargo t or cargo test to run tests; for a single test, pass the test name after the test command
Use snapshot testing with the insta crate; run cargo insta accept, cargo insta reject, or cargo insta review to manage snapshot changes
Write doctests as doc comments with code blocks; the code inside code blocks will be run during the testing phase
Use just f (alias for just format) to format Rust and TOML files before committing

Files:

  • crates/biome_json_syntax/src/file_source.rs
  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
.changeset/**/*.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

.changeset/**/*.md: Create changesets for user-facing changes using just new-changeset; use headers with #### or ##### only; keep descriptions concise (1-3 sentences) and focus on user-facing changes
Use past tense when describing what was done ('Added new feature'), present tense when describing Biome behavior ('Biome now supports'); end sentences with a full stop
For new lint rules, show an example of an invalid case in an inline code snippet or code block; for rule changes, demonstrate what is now invalid or valid; for formatter changes, use a diff code block

Files:

  • .changeset/rich-icons-talk.md
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Commit rule changes with message format: `feat(biome_<crate>): <ruleName>` to follow Biome's conventional commit style
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/language_kind.rs : Add a new language prefix to the `LANGUAGE_PREFIXES` constant in `language_kind.rs` file

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Distinguish between `TypeData::Unknown` and `TypeData::UnknownKeyword` to measure inference effectiveness versus explicit user-provided unknown types

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/language_kind.rs : Add a new variant to `LanguageKind` enum in `language_kind.rs` file and implement all methods for the new language variant

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to 'fix' the code; if a token/node is known to be mandatory but is missing, return `None` instead

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.jsonc : Use `.jsonc` files in test specs with code snippets as array of strings to test rules in script environment (no import/export syntax)

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Implement a token source struct that wraps the lexer and implements `TokenSourceWithBufferedLexer` and `LexerWithCheckpoint` for lookahead and re-lexing capabilities

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeReference` instead of `Arc` for types that reference other types to avoid stale cache issues when modules are replaced

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When formatting AST nodes, use mandatory tokens from the AST instead of hardcoding token strings (e.g., use `node.l_paren_token().format()` instead of `token("(")`)

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use language tags in documentation code blocks (js, ts, tsx, json, css) and order properties consistently as: language, then `expect_diagnostic`, then options modifiers, then `ignore`, then `file=path`

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For tokens that are not mandatory, use helper functions instead of hardcoding

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/comments.rs : Define `<Language>CommentStyle` as a public type alias for `Comments<<Language>Language>` in a `comments.rs` file

Applied to files:

  • crates/biome_json_syntax/src/file_source.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUndeclared` prefix for rules that report undefined entities (e.g., `noUndeclaredVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Check if a variable is global before banning it to avoid false positives when the variable is redeclared in local scope; use the semantic model to verify global scope

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Deprecate rules by adding a `deprecated` field to the `declare_lint_rule!` macro with a message explaining the reason for deprecation (e.g., 'Use the rule noAnotherVar')

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnused` prefix for rules that report unused entities (e.g., `noUnusedVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRestricted` prefix for rules that report user-banned entities (e.g., `noRestrictedGlobals`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : The `declare_lint_rule!` macro must include metadata fields: `version` (set to 'next'), `name` (rule identifier), `language` (applicable language), `recommended` (boolean), and optional fields like `severity`, `fix_kind`, `sources`, `domains`, and `deprecated`

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Framework-specific rules should be named using the `use` or `no` prefix followed by the framework name (e.g., `noVueReservedProps`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnsafe` prefix for rules that report code leading to runtime failures (e.g., `noUnsafeOptionalChaining`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnknown` prefix for rules that report mistyped entities in CSS (e.g., `noUnknownUnit`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Set the `language` field in `declare_lint_rule!` to the primary language (js for JavaScript, jsx for JSX, ts for TypeScript, tsx for TSX) that the rule applies to

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Rules should use the `no` prefix naming convention when the sole intention is to forbid a single concept (e.g., `noDebugger` to disallow debugger statements)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noInvalid` prefix for rules that report runtime errors from mistyping (e.g., `noInvalidConstructorSuper`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Wrap optional rule option fields in `Option<_>` to properly track set vs unset options during configuration merging

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-28T09:08:10.091Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to .changeset/**/*.md : Create changesets for user-facing changes using `just new-changeset`; use headers with `####` or `#####` only; keep descriptions concise (1-3 sentences) and focus on user-facing changes

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Commit rule changes with message format: `feat(biome_<crate>): <ruleName>` to follow Biome's conventional commit style

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-28T09:08:10.091Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to .changeset/**/*.md : Use past tense when describing what was done ('Added new feature'), present tense when describing Biome behavior ('Biome now supports'); end sentences with a full stop

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-11-28T09:08:10.091Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to .changeset/**/*.md : For new lint rules, show an example of an invalid case in an inline code snippet or code block; for rule changes, demonstrate what is now invalid or valid; for formatter changes, use a `diff` code block

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-08-05T14:43:29.581Z
Learnt from: dyc3
Repo: biomejs/biome PR: 7081
File: packages/@biomejs/biome/configuration_schema.json:7765-7781
Timestamp: 2025-08-05T14:43:29.581Z
Learning: The file `packages/biomejs/biome/configuration_schema.json` is auto-generated and should not be manually edited or reviewed for schema issues; any changes should be made at the code generation source.

Applied to files:

  • .changeset/rich-icons-talk.md
📚 Learning: 2025-09-25T12:32:59.003Z
Learnt from: arendjr
Repo: biomejs/biome PR: 7593
File: crates/biome_service/src/workspace/server.rs:1306-1306
Timestamp: 2025-09-25T12:32:59.003Z
Learning: In the biomejs/biome project, do not flag compilation errors during code review as they are handled by the existing test infrastructure and CI. Focus on other code quality aspects instead.

Applied to files:

  • .changeset/rich-icons-talk.md
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (2)
crates/biome_js_syntax/src/expr_ext.rs (1)
  • global_identifier (1896-1916)
crates/biome_js_analyze/src/services/turborepo.rs (1)
  • model (50-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: Test Node.js API
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Check Dependencies
  • GitHub Check: Documentation
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: End-to-end tests
  • GitHub Check: Check JS Files
  • GitHub Check: Bench (biome_package)
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_json_formatter)
🔇 Additional comments (8)
crates/biome_json_syntax/src/file_source.rs (1)

110-113: turbo.jsonc placement and semantics look good

Adding "turbo.jsonc" here matches the “comments allowed, no trailing commas” semantics and mirrors the existing "turbo.json" handling. The list remains correctly sorted ("turbo.json" < "turbo.jsonc"), so the binary search and test_order invariants are preserved.

crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (7)

1-11: LGTM! Clean imports.

The imports are well-organized and appropriate for the rule's functionality.


12-85: LGTM! Comprehensive rule documentation.

The rule declaration follows Biome conventions, and the documentation clearly explains the rule's purpose, default allowed variables, and configuration options.


87-91: LGTM!

The state struct appropriately uses TokenText to preserve the environment variable name from the source.


151-163: LGTM! Clear and actionable diagnostic.

The diagnostic message clearly explains the issue and provides specific guidance on where to declare the environment variable in turbo.json.


165-181: LGTM! Proper scope checking.

Both helper functions are correct. Notably, is_global_process_object properly verifies that process is not shadowed by a local binding, avoiding false positives.


226-237: LGTM! Proper options handling.

The function correctly checks user-provided regex patterns against the environment variable name.


99-149: The has_turborepo_config() check is necessary, not redundant.

The Turborepo<N> query type doesn't filter matches based on config presence—it will invoke run() for every matching JsStaticMemberExpression regardless of whether turbo.json exists. The guard on line 101 prevents unnecessary processing in non-Turborepo projects.

@anthonyshew anthonyshew changed the title feat: Turborepo domain and noUndeclaredEnvVars rule feat: new Turborepo domain and noUndeclaredEnvVars rule Dec 11, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1)

186-215: Consider adding "VERCEL" to the sorted array.

The special case for "VERCEL" on lines 212-215 could be consolidated into DEFAULT_ALLOWED_ENV_VARS. Alphabetically, it slots in after "USER", maintaining sort order and allowing binary search to handle it.

 const DEFAULT_ALLOWED_ENV_VARS: &[&str] = &[
-    "CI", "HOME", "NODE_ENV", "PATH", "PWD", "SHELL", "TZ", "USER",
+    "CI", "HOME", "NODE_ENV", "PATH", "PWD", "SHELL", "TZ", "USER", "VERCEL",
 ];

Then remove the special case:

 fn is_env_var_allowed_by_defaults(env_var: &str) -> bool {
     // Check against default allowed env vars (sorted, so binary search is used)
     if DEFAULT_ALLOWED_ENV_VARS.binary_search(&env_var).is_ok() {
         return true;
     }

-    // Check for exact match "VERCEL" (CI provider)
-    if env_var == "VERCEL" {
-        return true;
-    }
-
     // Check against default allowed prefixes
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ffa26d and ba39d09.

⛔ Files ignored due to path filters (1)
  • crates/biome_configuration/tests/invalid/domains.json.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (2)
  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1 hunks)
  • crates/biome_package/src/node_js_package/turbo_json.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use the dbg!() macro for debugging output during testing, and pass the --show-output flag to cargo to view debug output
Use cargo t or cargo test to run tests; for a single test, pass the test name after the test command
Use snapshot testing with the insta crate; run cargo insta accept, cargo insta reject, or cargo insta review to manage snapshot changes
Write doctests as doc comments with code blocks; the code inside code blocks will be run during the testing phase
Use just f (alias for just format) to format Rust and TOML files before committing

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_package/src/node_js_package/turbo_json.rs
🧠 Learnings (13)
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUndeclared` prefix for rules that report undefined entities (e.g., `noUndeclaredVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Deprecate rules by adding a `deprecated` field to the `declare_lint_rule!` macro with a message explaining the reason for deprecation (e.g., 'Use the rule noAnotherVar')

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnused` prefix for rules that report unused entities (e.g., `noUnusedVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRestricted` prefix for rules that report user-banned entities (e.g., `noRestrictedGlobals`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Check if a variable is global before banning it to avoid false positives when the variable is redeclared in local scope; use the semantic model to verify global scope

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : The `declare_lint_rule!` macro must include metadata fields: `version` (set to 'next'), `name` (rule identifier), `language` (applicable language), `recommended` (boolean), and optional fields like `severity`, `fix_kind`, `sources`, `domains`, and `deprecated`

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnknown` prefix for rules that report mistyped entities in CSS (e.g., `noUnknownUnit`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnsafe` prefix for rules that report code leading to runtime failures (e.g., `noUnsafeOptionalChaining`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Framework-specific rules should be named using the `use` or `no` prefix followed by the framework name (e.g., `noVueReservedProps`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/nursery/**/*.rs : New rules must be placed inside the `nursery` group as an incubation space exempt from semantic versioning, with promotion to appropriate groups done during minor/major releases

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Rules should use the `no` prefix naming convention when the sole intention is to forbid a single concept (e.g., `noDebugger` to disallow debugger statements)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Wrap optional rule option fields in `Option<_>` to properly track set vs unset options during configuration merging

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noInvalid` prefix for rules that report runtime errors from mistyping (e.g., `noInvalidConstructorSuper`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
🧬 Code graph analysis (1)
crates/biome_package/src/node_js_package/turbo_json.rs (3)
crates/biome_js_analyze/src/services/turborepo.rs (2)
  • deserialize_from_json_str (120-120)
  • is_env_var_declared (38-42)
crates/biome_package/src/lib.rs (3)
  • deserialize_manifest (34-37)
  • read_manifest (40-40)
  • manifest (50-52)
crates/biome_package/src/node_js_package/mod.rs (1)
  • manifest (98-100)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Check JS Files
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: End-to-end tests
  • GitHub Check: Documentation
  • GitHub Check: Check Dependencies
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_package)
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_configuration)
🔇 Additional comments (9)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (3)

12-86: LGTM!

Rule declaration follows Biome conventions nicely. The noUndeclared prefix is appropriate per project guidelines, documentation is thorough, and metadata is correctly structured for a nursery rule.


100-150: LGTM!

The run function logic is clear and well-structured. Good use of early returns and proper semantic model verification to avoid false positives on shadowed process variables.


166-182: LGTM!

Proper use of the semantic model to distinguish global process from locally-bound variables. This avoids false positives when users shadow the global.

crates/biome_package/src/node_js_package/turbo_json.rs (6)

1-12: LGTM!

Imports are clean and appropriate for the turbo.json manifest handling.


14-58: Well-structured data model.

The separation of positive and negation patterns in EnvVarsCache is clever, enabling efficient single-pass matching. Good use of OnceLock for lazy initialization and unknown_fields = "allow" for forward compatibility with future turbo.json schema changes.

Also applies to: 83-111


60-78: Efficient cache preservation on clone.

The manual Clone implementation thoughtfully preserves the cached environment variables rather than forcing recomputation. This optimisation is worthwhile given that env_vars_cache aggregates data from multiple sources.


169-230: LGTM!

The lazy cache initialization correctly aggregates patterns from all sources (global, task-level, and legacy pipeline), properly separating positive and negation patterns. Thread-safety via OnceLock is appropriate.


254-285: Correct matching logic with proper precedence.

The implementation correctly checks negations before positive patterns, and handles both exact matches and wildcard patterns. The special case of "*" as a wildcard (where strip_suffix yields "") works correctly since starts_with("") is always true.

For typical turbo.json files, the O(n) pattern iteration is perfectly adequate.


288-504: Excellent test coverage.

The test suite thoroughly validates exact matches, wildcards, negations, pass-through variables, and their combinations. The test_negation_order_independent test is particularly good at documenting that negations take precedence regardless of their position in the declaration list.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1)

152-163: Consider a more concise diagnostic message.

The current message is quite detailed. Whilst thorough, you might condense it slightly for readability:

         Some(RuleDiagnostic::new(
             rule_category!(),
             node.range(),
             markup! {
-                "The environment variable "<Emphasis>{env_var}</Emphasis>" is not listed as a dependency in turbo.json. Add this environment variable a task's 'env'/'passThroughEnv', or to 'globalEnv', 'globalPassThroughEnv', in your turbo.json(c) configuration to ensure correct caching behavior in Turborepo."
+                "Environment variable "<Emphasis>{env_var}</Emphasis>" is not declared in turbo.json. Add it to a task's 'env'/'passThroughEnv' or to 'globalEnv'/'globalPassThroughEnv' to ensure correct Turborepo caching."
             },
         ))
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba39d09 and a9e6a4e.

⛔ Files ignored due to path filters (5)
  • crates/biome_configuration/tests/invalid/domains.json.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithNegation.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/invalidWithTurboJson.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (5)
  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (1 hunks)
  • crates/biome_js_analyze/src/services/turborepo.rs (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.turbo.jsonc (1 hunks)
  • crates/biome_test_utils/src/lib.rs (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.turbo.jsonc
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_test_utils/src/lib.rs
🧰 Additional context used
📓 Path-based instructions (1)
crates/**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update inline rustdoc documentation for rules, assists, and their options when adding new features or changing existing features in Rust crates

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
🧠 Learnings (22)
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.jsonc : Use `.jsonc` files in test specs with code snippets as array of strings to test rules in script environment (no import/export syntax)

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.{js,ts,tsx,jsx,json,css} : Test rules using snapshot tests via the `insta` library with test cases in `tests/specs/<group>/<rule_name>/` directories prefixed by `invalid` or `valid`

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUndeclared` prefix for rules that report undefined entities (e.g., `noUndeclaredVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Deprecate rules by adding a `deprecated` field to the `declare_lint_rule!` macro with a message explaining the reason for deprecation (e.g., 'Use the rule noAnotherVar')

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnused` prefix for rules that report unused entities (e.g., `noUnusedVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Check if a variable is global before banning it to avoid false positives when the variable is redeclared in local scope; use the semantic model to verify global scope

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRestricted` prefix for rules that report user-banned entities (e.g., `noRestrictedGlobals`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : The `declare_lint_rule!` macro must include metadata fields: `version` (set to 'next'), `name` (rule identifier), `language` (applicable language), `recommended` (boolean), and optional fields like `severity`, `fix_kind`, `sources`, `domains`, and `deprecated`

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnknown` prefix for rules that report mistyped entities in CSS (e.g., `noUnknownUnit`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnsafe` prefix for rules that report code leading to runtime failures (e.g., `noUnsafeOptionalChaining`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Framework-specific rules should be named using the `use` or `no` prefix followed by the framework name (e.g., `noVueReservedProps`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/nursery/**/*.rs : New rules must be placed inside the `nursery` group as an incubation space exempt from semantic versioning, with promotion to appropriate groups done during minor/major releases

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Rules should use the `no` prefix naming convention when the sole intention is to forbid a single concept (e.g., `noDebugger` to disallow debugger statements)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noInvalid` prefix for rules that report runtime errors from mistyping (e.g., `noInvalidConstructorSuper`)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Wrap optional rule option fields in `Option<_>` to properly track set vs unset options during configuration merging

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace*.rs : Implement the Workspace trait in the Biome Service to manage internal state of projects, including open documents, project layout instances, and module graph instances

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Implement watcher tests for workspace methods in watcher.tests.rs and end-to-end tests in LSP tests

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeReference` instead of `Arc` for types that reference other types to avoid stale cache issues when modules are replaced

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-12-12T10:11:05.549Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-12T10:11:05.549Z
Learning: Applies to crates/**/*.rs : Update inline rustdoc documentation for rules, assists, and their options when adding new features or changing existing features in Rust crates

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Implement the `Merge` trait for rule options to define how options from extended configuration merge with user configuration (usually reset instead of extend)

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use `Semantic<T>` query type instead of `Ast<T>` when a rule needs to access the semantic model for binding references and scope information

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Implement custom `Queryable` types and `Visitor` traits for rules requiring deep AST inspection to avoid redundant traversal passes

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
🧬 Code graph analysis (2)
crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (2)
crates/biome_js_syntax/src/expr_ext.rs (1)
  • global_identifier (1896-1916)
crates/biome_js_analyze/src/services/turborepo.rs (1)
  • model (53-55)
crates/biome_js_analyze/src/services/turborepo.rs (1)
crates/biome_package/src/node_js_package/turbo_json.rs (2)
  • is_env_var_declared (254-285)
  • parse (141-155)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: Test Node.js API
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_package)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Documentation
  • GitHub Check: End-to-end tests
  • GitHub Check: Check Dependencies
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Check JS Files
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_json_formatter)
🔇 Additional comments (6)
crates/biome_js_analyze/tests/specs/nursery/noUndeclaredEnvVars/validWithTurboJsonc.js (1)

1-22: LGTM!

Test fixture is well-organised with clear comments documenting each scenario being validated. The JSONC_ prefix convention consistently distinguishes these from the standard turbo.json test cases.

crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs (2)

12-86: Excellent documentation.

The rustdoc clearly explains the rule's purpose, default allowed variables, and configuration options. Well done following the inline documentation guidelines.


166-238: LGTM!

Helper functions are well-implemented with appropriate optimisations (binary search for exact matches, starts_with for prefixes). The special case for VERCEL at line 213 correctly handles the single-word variable distinct from the VERCEL_* prefix pattern.

crates/biome_js_analyze/src/services/turborepo.rs (3)

30-56: LGTM!

The implementation correctly checks all configs to support task-level env/passThroughEnv declarations in package-level turbo.json files. The explanatory comment at lines 36-38 clearly documents why checking all configs is necessary, addressing the earlier review concern.


58-112: LGTM!

Standard trait implementations following Biome patterns. The Queryable correctly wires up semantic model building and syntax visiting in the appropriate phases.


114-247: LGTM!

Comprehensive test suite covering multi-level configs, task-level declarations, wildcards, negations, and edge cases. The test at line 191 nicely documents the "any positive match wins" behaviour across multiple configs.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/services/turborepo.rs (1)

31-45: Clarify the "any" matching semantics in the documentation.

The method documentation explains why all configs are checked but doesn't explicitly state that a positive match in ANY config will return true, regardless of negations in other configs. This is important for understanding test cases like test_negation_and_positive_in_different_configs.

Consider enhancing the documentation:

     /// Checks if the given environment variable is declared in any turbo.json.
     ///
     /// This method checks all turbo.json configurations that apply to the current file,
     /// including both the root turbo.json and any package-level turbo.json files.
     ///
     /// While Turborepo treats `globalEnv` and `globalPassThroughEnv` as root-only,
     /// task-level `env` and `passThroughEnv` can be declared in package-level turbo.json files.
     /// Therefore, we need to check all applicable configs.
     ///
+    /// Returns `true` if the env var is declared in ANY of the configs (OR semantics).
+    /// Note that a positive match in one config overrides negations in other configs.
+    ///
     /// Returns `false` if no turbo.json configs exist or the env var is not declared in any of them.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9e6a4e and ff7d34d.

📒 Files selected for processing (1)
  • crates/biome_js_analyze/src/services/turborepo.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
crates/**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update inline rustdoc documentation for rules, assists, and their options when adding new features or changing existing features in Rust crates

Files:

  • crates/biome_js_analyze/src/services/turborepo.rs
🧠 Learnings (11)
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace*.rs : Implement the Workspace trait in the Biome Service to manage internal state of projects, including open documents, project layout instances, and module graph instances

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use `Semantic<T>` query type instead of `Ast<T>` when a rule needs to access the semantic model for binding references and scope information

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Implement custom `Queryable` types and `Visitor` traits for rules requiring deep AST inspection to avoid redundant traversal passes

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Check if a variable is global before banning it to avoid false positives when the variable is redeclared in local scope; use the semantic model to verify global scope

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Implement watcher tests for workspace methods in watcher.tests.rs and end-to-end tests in LSP tests

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeReference` instead of `Arc` for types that reference other types to avoid stale cache issues when modules are replaced

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-12-12T10:11:05.549Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-12T10:11:05.549Z
Learning: Applies to crates/**/*.rs : Update inline rustdoc documentation for rules, assists, and their options when adding new features or changing existing features in Rust crates

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Implement the `Merge` trait for rule options to define how options from extended configuration merge with user configuration (usually reset instead of extend)

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUndeclared` prefix for rules that report undefined entities (e.g., `noUndeclaredVariables`)

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/src/**/*.rs : Wrap optional rule option fields in `Option<_>` to properly track set vs unset options during configuration merging

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRestricted` prefix for rules that report user-banned entities (e.g., `noRestrictedGlobals`)

Applied to files:

  • crates/biome_js_analyze/src/services/turborepo.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/services/turborepo.rs (1)
crates/biome_package/src/node_js_package/turbo_json.rs (2)
  • is_env_var_declared (254-285)
  • parse (141-155)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Check Dependencies
  • GitHub Check: End-to-end tests
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Documentation
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Check JS Files
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_package)
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_configuration)
🔇 Additional comments (5)
crates/biome_js_analyze/src/services/turborepo.rs (5)

14-28: LGTM!

The struct documentation clearly explains the purpose and field organization. The use of Arc<TurboJson> is appropriate for sharing configuration data across the analysis pipeline.


47-56: LGTM!

Simple accessor methods with clear, self-documenting implementations.


79-112: LGTM!

The Phase and Queryable implementations follow standard Biome patterns. The visitor setup correctly builds the semantic model in the Syntax phase and makes it available for the Semantic phase.


114-303: LGTM!

Comprehensive test coverage with well-documented test cases. The regression test at lines 255-302 is particularly thorough, with clear explanations of the monorepo scenario being validated. The test helpers are cleanly implemented.


58-77: No changes needed. The SemanticModel::clone() on line 74 is efficient—SemanticModel derives Clone and its fields use reference-counted types (DashMap and Vec<Arc<Scope>>), making the clone a cheap O(1) operation.

Copy link
Contributor

@dyc3 dyc3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Rerun the codegen to fix the merge conflict

@anthonyshew
Copy link
Contributor Author

@dyc3 My force push is resolving that codegen conflict. Was doing my morning GitHub round and figured I'd fix it real quick.

@dyc3 dyc3 merged commit 285d932 into biomejs:main Dec 15, 2025
24 checks passed
@github-actions github-actions bot mentioned this pull request Dec 15, 2025
l0ngvh pushed a commit to l0ngvh/biome that referenced this pull request Dec 21, 2025
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Carson McManus <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI A-Core Area: core A-Diagnostic Area: diagnostocis A-Linter Area: linter A-Parser Area: parser A-Project Area: project L-JavaScript Language: JavaScript and super languages L-JSON Language: JSON and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants