Skip to content

[build] Script to update Bazel multitool.lock.json (and update ruff) #16061

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jul 18, 2025

Conversation

cgoldberg
Copy link
Contributor

@cgoldberg cgoldberg commented Jul 16, 2025

User description

💥 What does this PR do?

This PR updates the version of Ruff (Python linter/formatter) used by Bazel and for local Python development.

It also includes a new script ./scripts/update_multitool_binaries.py for keeping the Bazel rules_multitool lockfile (multitool.lock.json) up to date. Previously, you had to edit this file and supply new URL's and hashes whenever updating a tool's binary versions.

See: https://github.com/theoremlp/rules_multitool

🔧 Implementation Notes

To update the lockfile, run $ ./scripts/update_multitool_binaries.py from the root of the repo.

💡 Additional Considerations

The update script requires that the tool binaries are hosted in a public GitHub repo's Release assets, otherwise the tool is just skipped. Currently, we only have 1 tool (ruff) defined in this file.

🔄 Types of changes

  • Build/Dev

PR Type

Enhancement


Description

  • Add Python script to automatically update Bazel multitool lockfile

  • Update Ruff version from 0.11.11/0.11.12 to 0.12.3

  • Automate URL and hash updates for GitHub-hosted tool binaries


Changes diagram

flowchart LR
  A["New Python Script"] --> B["Fetch Latest Releases"]
  B --> C["Update multitool.lock.json"]
  C --> D["Update Ruff URLs & Hashes"]
  D --> E["Update py/tox.ini"]
Loading

Changes walkthrough 📝

Relevant files
Enhancement
update_multitool_binaries.py
Add automated multitool binary updater script                       

scripts/update_multitool_binaries.py

  • New Python script to automatically update Bazel multitool lockfile
  • Fetches latest GitHub releases and updates URLs/hashes
  • Supports command-line arguments for custom lockfile paths
  • Requires PyGithub dependency for GitHub API access
  • +87/-0   
    Dependencies
    multitool.lock.json
    Update Ruff binaries to version 0.12.3                                     

    multitool.lock.json

  • Update Ruff binary URLs from version 0.11.11 to 0.12.3
  • Update SHA256 hashes for all platform binaries
  • Covers Linux (ARM64/x86_64), macOS (ARM64/x86_64), and Windows
    (x86_64)
  • +10/-10 
    tox.ini
    Update Ruff version in tox configuration                                 

    py/tox.ini

  • Update Ruff dependency version from 0.11.12 to 0.12.3
  • Maintain consistency with multitool.lock.json updates
  • +1/-1     

    Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • @selenium-ci selenium-ci added C-py Python Bindings B-build Includes scripting, bazel and CI integrations labels Jul 16, 2025
    Copy link
    Contributor

    qodo-merge-pro bot commented Jul 16, 2025

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    @cgoldberg cgoldberg changed the title Script to update Bazel multitool.lock.json Script to update Bazel multitool.lock.json (and update ruff) Jul 16, 2025
    Copy link
    Contributor

    qodo-merge-pro bot commented Jul 16, 2025

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Handle potential None from regex
    Suggestion Impact:The suggestion was implemented with a slightly different approach. Instead of using a separate variable and checking for None, the code was restructured to use the same match variable and check if it exists before accessing index [1], then continue if no match is found.

    code diff:

    +        match = re.search(f"download/(.*?)/{tool}", data[tool]["binaries"][0]["url"])
             if match:
    -            user_repo = match[1]
    +            version = match[1]
    +        else:
    +            continue

    The regex search could return None if the pattern doesn't match, causing an
    AttributeError when accessing index [1]. Add a check to handle cases where the
    URL format doesn't match the expected pattern.

    scripts/update_multitool_binaries.py [40-42]

    -version = re.search(f"download/(.*?)/{tool}", data[tool]["binaries"][0]["url"])[
    -    1
    -]
    +version_match = re.search(f"download/(.*?)/{tool}", data[tool]["binaries"][0]["url"])
    +if not version_match:
    +    continue
    +version = version_match[1]

    [Suggestion processed]

    Suggestion importance[1-10]: 8

    __

    Why: This suggestion correctly identifies that re.search can return None, which would cause a TypeError, and provides a robust fix to prevent the script from crashing on unexpected URL formats.

    Medium
    General
    Use tag_name for version
    Suggestion Impact:The commit implemented the suggestion by switching from using GitHub API's title field to tag_name field for version extraction, though it used a different approach (direct API call instead of PyGithub library)

    code diff:

    -            new_version = Github().get_repo(user_repo).get_releases()[0].title
    +            with urllib.request.urlopen(releases_url) as response:
    +                json_resp = json.loads(response.read())
    +                new_version = json_resp["tag_name"]

    Using .title assumes the release title contains the version, but GitHub releases
    often use .tag_name for version information. Consider using .tag_name instead
    for more reliable version extraction.

    scripts/update_multitool_binaries.py [50-53]

     try:
    -    new_version = Github().get_repo(user_repo).get_releases()[0].title
    +    new_version = Github().get_repo(user_repo).get_releases()[0].tag_name
     except Exception:
         continue

    [Suggestion processed]

    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly points out that a release tag_name is generally a more reliable source for a version string than its title, improving the script's robustness for different GitHub repositories.

    Medium
    Add file error handling

    The file is opened without error handling, which could cause the script to crash
    if the lockfile doesn't exist or is malformed. Add proper error handling to
    provide meaningful feedback to users.

    scripts/update_multitool_binaries.py [36-37]

    -with open(lockfile_path) as f:
    -    data = json.load(f)
    +try:
    +    with open(lockfile_path) as f:
    +        data = json.load(f)
    +except FileNotFoundError:
    +    exit(f"Error: lockfile '{lockfile_path}' not found")
    +except json.JSONDecodeError:
    +    exit(f"Error: invalid JSON in lockfile '{lockfile_path}'")
    • Apply / Chat
    Suggestion importance[1-10]: 7

    __

    Why: This is a good suggestion for improving the script's user experience and robustness by handling potential FileNotFoundError and json.JSONDecodeError with clear, user-friendly error messages.

    Medium
    • Update

    Copy link
    Member

    @p0deje p0deje left a comment

    Choose a reason for hiding this comment

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

    It would be even cooler if the script can be run with Bazel, so I don't have to think about installing Pygithub. Let me know if you want to work on that, I'll help.

    Copy link
    Member

    @p0deje p0deje left a comment

    Choose a reason for hiding this comment

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

    It would be even cooler if the script could be run from Bazel itself, so one doesn't need to remember to install dependencies. But either way, great work!

    @cgoldberg
    Copy link
    Contributor Author

    so I don't have to think about installing Pygithub

    I just improved it so it doesn't use PyGithub and it retrieves hashes from GitHub so it doesn't have to download assets and calculate them. Now there are no external dependencies.

    @cgoldberg cgoldberg changed the title Script to update Bazel multitool.lock.json (and update ruff) [build] Script to update Bazel multitool.lock.json (and update ruff) Jul 18, 2025
    @cgoldberg cgoldberg merged commit 91fc24d into SeleniumHQ:trunk Jul 18, 2025
    9 checks passed
    @cgoldberg cgoldberg deleted the update-mutitool-binaries branch July 18, 2025 19:14
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    B-build Includes scripting, bazel and CI integrations C-py Python Bindings Review effort 3/5
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    3 participants