Skip to content

Error on odd .bazelrc lines #19

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

arvi18
Copy link

@arvi18 arvi18 commented Apr 28, 2025

I have tried to spare users a long debugging session searching for a .bazelrc
line that was not applied.

The main issue is in the client parser, which assumes that the first word on a line is always a command. If you are unlucky enough, you forgot the command an passed a single flag. The client assumes it is a command with no flags, and passes nothing to the server, hence silently ignoring the bogus line.

I have changed the client to refuse lines with a single word, which is both simpler to do, and prevents what seems like a code smell anyway.

It is thus a breaking change for users who used to comment only the flag and not the command, or those who have empty commands to keep blocks together.
Overall, the RC files lack a proper specification, which makes it impossible to know precisely what is valid.

# The two following lines will no more work.
common # --host_jvm_args=-Xmx1024m
common

The second commit is optional. It turns a warning about unrecognized command names into an error.
I think it makes sense to address these issues early. It may break users config if commands are removed in the future, but that set is pretty stable now.

Fixes bazelbuild#15245

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling for invalid or incomplete command lines in configuration files, ensuring that such cases now result in clear error messages and halted processing.
  • Tests
    • Added and refactored tests to verify that invalid or incomplete commands in configuration files are correctly identified and reported as errors.
    • Updated test cases to expect exceptions instead of warnings for invalid command names.

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

@iancha1992 can we get a review of this?

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

@iancha1992 can we get a review of this?

cc: @Wyverald @meteorcloudy

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

honestly not sure whether this is team-Core or team-Configurability. So I'll ping both of them! @haxorz @gregestren (who's OOO, so @katre in lieu)

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

RC parsing belongs to Scalability (team-core due to legacy naming).

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

Yes, and see my comments on the linked issue. Whoever handles this PR internally needs to do that work.

Thank you @layus for moving this forward!

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

Justin can you please take a look? Follow up with me internally about the internal work.

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

This change looks great! I did notice it still doesn't diagnose this invalid case:

build --copt=-v \
 # comment \
 --copt=-invalid

Copy link

coderabbitai bot commented Apr 28, 2025

Walkthrough

The changes introduce stricter validation and error handling for parsing and processing rc files and command options. In the C++ code, the parser now checks for incomplete command lines and returns an error if a command lacks arguments. In the Java code, encountering an invalid command name during rc options structuring now results in an exception rather than a warning, altering the control flow to halt processing on such errors. Corresponding tests in both C++ and Java have been updated or added to verify these new error conditions and ensure the correct exceptions and messages are produced.

Changes

File(s) Change Summary
src/main/cpp/rc_file.cc Added validation to detect and error on incomplete command lines (command without arguments) during rc file parsing.
src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java Changed handling of invalid command names: now throws OptionsParsingException instead of issuing a warning and continuing.
src/test/cpp/rc_options_test.cc Introduced helper for error assertion; refactored existing error tests to use it; added new tests for missing/empty commands.
src/test/java/com/google/devtools/build/lib/runtime/BlazeOptionHandlerTest.java Updated test to expect exception on invalid command name instead of verifying warning event; added assertions on exception details.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant RcFileParser (C++)
    User->>RcFileParser: Parse rc file
    RcFileParser->>RcFileParser: Check for command token
    alt Command token present
        RcFileParser->>RcFileParser: Check for arguments
        alt Arguments missing
            RcFileParser->>User: Return INVALID_FORMAT error with message
        else Arguments present
            RcFileParser->>User: Continue parsing
        end
    else Command token missing
        RcFileParser->>User: Return INVALID_FORMAT error
    end
Loading
sequenceDiagram
    participant User
    participant BlazeOptionHandler (Java)
    User->>BlazeOptionHandler: structureRcOptionsAndConfigs(...)
    BlazeOptionHandler->>BlazeOptionHandler: Validate command name
    alt Command name invalid
        BlazeOptionHandler->>User: Throw OptionsParsingException
    else Command name valid
        BlazeOptionHandler->>User: Continue processing options
    end
Loading

Poem

In files of rc, where commands reside,
Now errors are caught, no longer can hide.
Java throws exceptions, C++ checks the line,
Tests are refactored—robust by design!
With stricter control, the parsing is clear,
A rabbit hops forward—no warnings left here!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0c98a2 and ddd7d70.

📒 Files selected for processing (4)
  • src/main/cpp/rc_file.cc (1 hunks)
  • src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java (1 hunks)
  • src/test/cpp/rc_options_test.cc (7 hunks)
  • src/test/java/com/google/devtools/build/lib/runtime/BlazeOptionHandlerTest.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/test/java/com/google/devtools/build/lib/runtime/BlazeOptionHandlerTest.java (1)
src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java (1)
  • BlazeOptionHandler (68-700)
src/test/cpp/rc_options_test.cc (1)
src/main/cpp/rc_file.cc (2)
  • Parse (42-51)
  • Parse (42-44)
🔇 Additional comments (8)
src/main/cpp/rc_file.cc (1)

147-153: Improved validation prevents silent failure of incomplete command lines.

This change adds a critical validation step that checks if a command has any arguments after parsing the command token. If there are no arguments, it now correctly returns an INVALID_FORMAT error with a clear message indicating the incomplete line.

This fix aligns perfectly with the PR objective of preventing the silent ignoring of invalid lines where a command has no flags. The error message is descriptive and helps users identify and fix their configuration.

src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java (1)

632-638: Properly throws exception for invalid command names instead of warning.

The code now throws an OptionsParsingException when encountering an invalid command name instead of just emitting a warning and continuing. This ensures that invalid configuration is caught early.

This change aligns with the C++ validation improvements and fulfills the PR objective to reject invalid commands rather than silently ignoring them. The error message is clear and includes both the file and the problematic command name.

src/test/java/com/google/devtools/build/lib/runtime/BlazeOptionHandlerTest.java (1)

155-168: Updated test to verify exception behavior for invalid commands.

The test has been updated to expect an OptionsParsingException to be thrown when an invalid command name is encountered, instead of the previous behavior where a warning event was emitted.

This test correctly verifies the new behavior implemented in BlazeOptionHandler.java. The assertions check that the exception is thrown with the correct message and that no residual state is left in the parser or rcfile notes.

src/test/cpp/rc_options_test.cc (5)

101-111: Added a helper method to consolidate error case assertions.

This new helper method improves test code quality by reducing duplication across error test cases. It properly asserts both the error code and that the error message matches an expected regex pattern.

Good refactoring that will make the tests more maintainable. I like that it tests the error message text first since that's more helpful for debugging than just the error code.


374-380: Refactored import cycle tests to use the new helper method.

Updated the import cycle tests to use the new FailToParseRcWithErrorAndRegex helper method for more consistent error checking.

This refactoring maintains the same test functionality while improving code consistency and readability.

Also applies to: 397-408


410-419: Added test to verify error on missing command.

This new test verifies that lines with only flags (no command) are properly rejected with an INVALID_FORMAT error.

This test covers an important edge case directly related to the PR's objective of preventing silent ignoring of invalid lines. It ensures that the parser catches and reports when a line contains only a flag without a command.


421-430: Added test to verify error on empty options.

This test verifies that lines with a command but no options (due to comments) are properly rejected with an INVALID_FORMAT error.

This test case covers another important scenario that was previously silently ignored - a command with commented-out options. It verifies that the parser now correctly treats this as an error per the new validation in rc_file.cc.


433-440: Updated remaining error tests to use the helper method.

All error test cases have been updated to use the new FailToParseRcWithErrorAndRegex helper method.

This consistent application of the helper method across all error tests improves readability and maintainability of the test suite.

Also applies to: 446-452, 467-473, 478-484, 500-504, 520-524

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

This change looks great! I did notice it still doesn't diagnose this invalid case:

build --copt=-v \
 # comment \
 --copt=-invalid

@keith This is not invalid per se.

AFAIU it translates to build --copt=-v # comment --copt=-invalid which is valid, and should be expected by the users. At least if they are the kind of users that like shooting themselves in the foot by using backslashes.

Am I missing something ?

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

AFAIU it translates to build --copt=-v # comment --copt=-invalid which is valid, and should be expected by the users. At least if they are the kind of users that like shooting themselves in the foot by using backslashes.

Ah yea I guess it depends on how this should be interpreted, I expected the \ to work the same as bash, which means when used in a comment line it is not respected and is just interpreted as any other character in the comment

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

I've started to look into this and have some bad news. I ran the new parser over google-internal checked-in blazerc files, and on a sample of over 700 files, the breakage rate is nearly 2%. This doesn't even include non-checked-in blazerc files on user machines.

While it looks like most of these broken samples really should be errors, I think we need a better way to roll this out than just accepting this PR and expecting people to fix their blazercs when it's released.

To give an example of a breakage, there is a blazerc file that had the following line:

build --some_flag

then there was an effort to remove uses of --some_flag, which left the blazerc with the line:

build

which is now invalid with this PR.


We'll need to discuss how to proceed with this and whether it's worth the investment. Would you be open to an optional "strict mode" for rc file parsing? That might end up being the most feasible way to make progress, sadly.

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

Or another option is to display a warning for the single token case that's currently ignored. Would this solve your motivating scenario?

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

it'd probably be best if we have an incompatible flag for this anyhow, as it's a breaking change. We can only make this the default behavior in Bazel 8.0 at the earliest, so having a flag users could toggle on in 7.x would be the best way forward.

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

Actually, seems tricky to have a flag that controls the semantics of flag parsing. Might need to be a system property. Makes it seem more appealing to just add a warning.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Hello @arvi18, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

This pull request addresses an issue in the client parser for .bazelrc files, where lines with a single word (e.g., a command without flags or just a flag) were silently ignored. I've modified the client to reject such incomplete lines, preventing potential misconfigurations. Additionally, I've promoted a warning about unrecognized command names to an error. This change might break existing configurations that rely on commenting only the flag or using empty commands for block organization.

Highlights

  • Error Handling: The pull request introduces stricter error handling for .bazelrc files, specifically for incomplete lines (lines with only a command or a flag) and invalid command names.
  • Breaking Change: This change is potentially breaking for users who have .bazelrc files with single-word lines (e.g., common # --host_jvm_args=-Xmx1024m or just common).
  • Test Coverage: The pull request includes updates to the test suite to reflect the new error handling behavior, ensuring that incomplete lines and invalid command names now result in parsing errors.

Changelog

Click here to see the changelog
  • src/main/cpp/rc_file.cc
    • Added a check to ensure that .bazelrc lines contain both a command and at least one argument. If a line only contains a single word, a ParseError::INVALID_FORMAT error is returned.
    • The error message includes the filename and the offending line.
  • src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java
    • Changed the handling of unrecognized command names from a warning to an OptionsParsingException.
  • src/test/cpp/rc_options_test.cc
    • Added a helper function FailToParseRcWithErrorAndRegex to simplify testing for specific parse errors and error messages.
    • Updated existing tests and added new tests to verify that incomplete lines in .bazelrc files now result in ParseError::INVALID_FORMAT errors.
    • Tests were added to verify that invalid import declarations now result in ParseError::INVALID_FORMAT errors.
    • Tests were added to verify that import cycles are detected and reported as ParseError::IMPORT_LOOP errors.
    • Tests were added to verify that non-existent files are reported as ParseError::UNREADABLE_FILE errors.
  • src/test/java/com/google/devtools/build/lib/runtime/BlazeOptionHandlerTest.java
    • Updated the test testStructureRcOptionsAndConfigs_invalidCommand to assert that an OptionsParsingException is thrown when an invalid command is encountered, instead of just checking for a warning event.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


A config's cryptic call,
Ignored, it tripped up all.
Now errors bloom,
Dispelling gloom,
No silent failures enthrall.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

I think warnings are easy to lose in the sea of logs that come from bazel in a large project. It seems like a flag would be ideal so google could disable that until the violations are fixed

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

Actually, seems tricky to have a flag that controls the semantics of flag parsing. Might need to be a system property.

ah, that's true... is a startup flag an option, or is that also too late/tricky to implement?

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

In the single token case, we could use an empty string. Then the server would error if the single token is not a valid command name. That would push all verification to the server, making a startup option (or system property) possible.

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

In the single token case, we could use an empty string. Then the server would error if the single token is not a valid command name. That would push all verification to the server, making a startup option (or system property) possible.

I think this is the best way forward. Does the server already accept empty strings as options ?

@arvi18
Copy link
Author

arvi18 commented Apr 28, 2025

When passed an empty string with an invalid command name, it works (currently a warning today). When passed an empty string with a valid command name, it adds the empty string as an extra command line token. For example, a build command gives the error:

ERROR: Skipping '': invalid target name '': empty target name

(I didn't know this, but apparently an rc file line like build //target will build that target on every build command.)

If we do pass an empty string from the client for a single-token line, seems like a good idea to have the server reject it with a helpful error message when the command name is valid (if the strict mode is enabled) or ignore it (if the strict mode is disabled).

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a breaking change to the .bazelrc parsing logic, which now enforces that every line must start with a command. This change prevents silent failures due to incomplete lines and improves error reporting. The tests have been updated to reflect this change. Overall, the changes seem reasonable and improve the robustness of the .bazelrc parsing.

Summary of Findings

  • Breaking Change: The change to require a command on every line in .bazelrc is a breaking change that may affect existing users. Ensure that the impact is well-understood and communicated.
  • Error Message Clarity: The error message for incomplete lines could be improved to provide more context to the user, such as suggesting to add a command or comment out the line.
  • Test Coverage: The tests cover various scenarios, but it's important to ensure that all edge cases and potential user errors are covered, especially those related to the breaking change.

Merge Readiness

The pull request introduces a breaking change, so it's important to ensure that the impact is well-understood and communicated to users. The code changes improve the robustness of .bazelrc parsing and provide better error reporting. The tests have been updated to reflect the changes. I recommend addressing the review comments before merging. I am unable to approve this pull request, and other reviewers should review and approve this code before merging.

@visz11
Copy link
Collaborator

visz11 commented Apr 28, 2025

@coderabbitai full review

Copy link

coderabbitai bot commented Apr 28, 2025

✅ Actions performed

Full review triggered.

@katre
Copy link

katre commented Apr 28, 2025

You need to send this to the actual bazelbuild/bazel project: you are free to merge this to your own coderabbit-test/bazel project as you wish, we don't need to review it.

@layus
Copy link

layus commented Apr 28, 2025

@visz11, @arvi18 I am not too happy to suddenly get notified of all that happens on this repo. Do you need to use real data and ping real ppl for your tests ? @katre got confused and I was certainly too. Not to mention it is a bit shady to appropriate all the IP of other ppl.

The real PR is here: bazelbuild#20895

@visz11, @arvi18 Could you turn this repo private to do your testing ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bazelrc line with missing command should fail fast instead of silently ignoring
4 participants