Skip to content

Conversation

arvi18
Copy link

@arvi18 arvi18 commented Apr 27, 2025

This PR implements part of the Execution Platform Scoped Spawn Strategies proposal.

It adds a new flag --allowed_strategies_by_exec_platform which permits filtering spawn strategies for spawns execution platform.

Example

# //.bazelrc
# Default strategies (order sensitive)
build --spawn_strategy=remote,worker,sandboxed,local

# Mnemonic targeted strategy override (order sensitive)
build --strategy=BAR=remote,sandboxed

# Host platform allowed strategies
build --allowed_strategies_by_exec_platform=@platforms//host:host=local,sandboxed,worker

# Remote platform allowed strategies
build --allowed_strategies_by_exec_platform=//:remote_platform=remote

For an action with mnemonic FOO configured for the host platform (@platforms//host:host), it will resolve worker,sandboxed,local as it's spawn strategy candidates.

  • remote was eliminated as a candidate (not in allow list for platform).
  • Order from --spawn_strategy was preserved.

For an action with mnemonic BAR configured for the host platform (@platforms//host:host), it will resolve sandboxed as it's spawn strategy candidate.

  • remote was eliminated as a candidate (not in allow list for platform).
  • Mnemonic override applied, leaving sandboxed as the final candidate.

For an action with mnemonic BAR configured for the remote platform (//:remote_platform), it will resolve remote as it's spawn strategy candidate.

  • sandboxed was eliminated as a candidate (not in allow list for platform).
  • Mnemonic override applied, leaving remote as the final candidate.

If no spawn strategy candidate remains after filtering, the standard error will be logged.

ERROR: /workspaces/___/BUILD.bazel:3:22: _description_ [for tool] failed: _mnemonic_ spawn cannot be executed with any of the available strategies: []. Your --spawn_strategy, --genrule_strategy and/or --strategy flags are probably too strict. Visit https://github.com/bazelbuild/bazel/issues/7480 for advice

TODO

  • Update "spawn cannot be executed" error to include new strategy flag.
  • CoverageReportActionBuilder.CoverageReportAction action uses spawn machinery but lacks an execution platform, leading to a precondition check failure. Being resolved in Give builtin actions a platform bazelbuild/bazel#23231
  • Fix //src/test/java/com/google/devtools/build/lib/remote:RemoteTests test failure

Summary by CodeRabbit

  • New Features
    • Added support for filtering and restricting spawn strategies based on execution platform via a new command-line option.
    • Enhanced error messaging to include the new platform-based strategy restriction flag.
  • Bug Fixes
    • Improved handling of empty execution platform properties to prevent unnecessary platform proto creation.
  • Tests
    • Introduced new tests to verify execution platform-based strategy filtering.
    • Updated existing tests to align with new method signatures and platform handling.
  • Chores
    • Updated build dependencies in both main and test modules for improved integration and coverage.

Copy link

coderabbitai bot commented Apr 27, 2025

Walkthrough

This update introduces execution platform-based filtering for spawn strategies within the build system. A new command-line option allows users to specify allowed strategies per execution platform. The SpawnStrategyRegistry and related classes are extended to support this filtering, ensuring that strategy selection now considers execution platform constraints in addition to existing mnemonic and regex filters. Several method signatures are updated to pass the Spawn object for more context-aware decisions, and corresponding tests are added or updated. Minor build file adjustments add necessary dependencies, and help messages are clarified to reflect the new option.

Changes

File(s) Change Summary
src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java Expanded the early null-return condition in getPlatformProto to treat execution platforms with empty properties as equivalent to null for skipping proto creation.
Strategy Registration and Filtering
src/main/java/com/google/devtools/build/lib/bazel/rules/BazelStrategyModule.java
src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java
Added support for registering spawn strategies filtered by execution platform labels. Introduced the allowed_strategies_by_exec_platform command-line option. Implemented StrategyPlatformFilter in the registry to filter strategies by execution platform after mnemonic and regex filters. Extended builder and strategy retrieval methods accordingly.
Remote Local Fallback Strategy Update
src/main/java/com/google/devtools/build/lib/exec/RemoteLocalFallbackRegistry.java
src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java
src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
Changed getRemoteLocalFallbackStrategy method to accept a Spawn parameter. Updated calls to this method to pass the current spawn instance. Adjusted lambda implementations in tests to match the new interface.
Build and Test Dependency Updates
src/main/java/com/google/devtools/build/lib/exec/BUILD
src/test/java/com/google/devtools/build/lib/exec/BUILD
Added dependencies for execution options, spawn strategy registry, command line, and platform analysis to relevant java_library and test targets.
Error Message and Test Enhancements
src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyResolver.java
src/test/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistryTest.java
src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java
Reformatted error message to include new flag and improve clarity. Added a test for platform-based strategy filtering. Updated tests to use the new fallback method signature. Modified FakeOwner constructor to use PlatformInfo.EMPTY_PLATFORM_INFO instead of null.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant BazelStrategyModule
    participant ExecutionOptions
    participant SpawnStrategyRegistry.Builder
    participant SpawnStrategyRegistry
    participant Spawn

    User->>ExecutionOptions: Set --allowed_strategies_by_exec_platform
    ExecutionOptions->>BazelStrategyModule: Provide platform-strategy map
    BazelStrategyModule->>SpawnStrategyRegistry.Builder: addExecPlatformFilter(Label, List<String>)
    SpawnStrategyRegistry.Builder->>SpawnStrategyRegistry: Build with platform filters

    User->>Spawn: Request execution
    Spawn->>SpawnStrategyRegistry: getStrategies(spawn, handler)
    SpawnStrategyRegistry->>SpawnStrategyRegistry: Apply mnemonic/regex filters
    SpawnStrategyRegistry->>SpawnStrategyRegistry: Apply platform filter (by execution platform label)
    SpawnStrategyRegistry-->>Spawn: Return filtered strategies
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Poem

In the meadow of builds, a new path is found,
Where platforms and strategies dance round and round.
With filters for labels, the choices are wise,
Each spawn gets its match—no more compromise!
A hop, a skip, and strategies align,
This rabbit approves—your code’s looking fine!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 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 01357a0 and c4eb49a.

📒 Files selected for processing (1)
  • src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch clone-filter-strategies-for-exec-platform

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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate unit tests to generate unit tests for 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.

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 introduces a new flag, --allowed_strategies_by_exec_platform, to filter spawn strategies based on the execution platform. This is part of the implementation for the Execution Platform Scoped Spawn Strategies proposal. The changes modify how spawn strategies are resolved, incorporating the new flag to allow or disallow certain strategies for specific execution platforms. The goal is to provide more fine-grained control over where actions are executed, for example, preventing remote execution for host platform actions.

Highlights

  • New Flag: Introduces the --allowed_strategies_by_exec_platform flag to filter spawn strategies based on the execution platform.
  • Strategy Filtering: Implements filtering logic within the SpawnStrategyRegistry to consider the allowed strategies for a given execution platform.
  • Error Reporting: Updates the error message when no valid spawn strategies are available after filtering, indicating the potential impact of the new flag.
  • Remote Fallback: Modifies the RemoteLocalFallbackRegistry to consider the execution platform when selecting a fallback strategy.

Changelog

Click here to see the changelog
  • src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java
    • Modifies the condition for checking empty execution platform properties to include checks for both execProperties and remoteExecutionProperties.
  • src/main/java/com/google/devtools/build/lib/bazel/rules/BazelStrategyModule.java
    • Adds a new dependency on com.google.devtools.build.lib.cmdline.Label.
    • Adds logic to register execution platform filters from the --allowed_strategies_by_exec_platform flag.
  • src/main/java/com/google/devtools/build/lib/exec/BUILD
    • Adds a dependency on //src/main/java/com/google/devtools/build/lib/analysis:config/fragment_options.
    • Adds a dependency on //src/main/java/com/google/devtools/build/lib/cmdline.
  • src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
    • Introduces the --allowed_strategies_by_exec_platform option, allowing users to specify allowed strategies for different execution platforms.
  • src/main/java/com/google/devtools/build/lib/exec/RemoteLocalFallbackRegistry.java
    • Modifies the getRemoteLocalFallbackStrategy method to accept a Spawn parameter.
    • Updates the RemoteLocalFallbackRegistry interface to pass the Spawn to getRemoteLocalFallbackStrategy.
  • src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java
    • Adds a StrategyPlatformFilter to filter strategies based on the execution platform.
    • Modifies the getStrategies methods to incorporate platform-based filtering.
    • Updates the getRemoteLocalFallbackStrategy method to use the platform filter.
    • Adds logging for platform-specific strategy filters.
    • Adds addExecPlatformFilter to the Builder class to allow adding platform filters.
    • Adds a new inner class StrategyPlatformFilter to handle filtering strategies based on execution platform.
  • src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyResolver.java
    • Updates the error message when no valid spawn strategies are available to include the --allowed_strategies_by_exec_platform flag.
  • src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java
    • Updates the call to getRemoteLocalFallbackStrategy to pass the Spawn object.
  • src/test/java/com/google/devtools/build/lib/exec/BUILD
    • Adds a dependency on //src/main/java/com/google/devtools/build/lib/analysis/platform.
  • src/test/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistryTest.java
    • Adds a test case for platform-based strategy filtering.
    • Updates tests to pass a Spawn object to getRemoteLocalFallbackStrategy.
  • src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java
    • Modifies the FakeOwner constructor to include PlatformInfo.EMPTY_PLATFORM_INFO by default.
  • src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
    • Updates the ImmutableClassToInstanceMap to accept a function that takes a Spawn object.
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 flag to filter,
Strategies align by platform,
Control takes its hold.

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.

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 new flag --allowed_strategies_by_exec_platform to filter spawn strategies based on the execution platform. The implementation involves adding a new filter StrategyPlatformFilter to the SpawnStrategyRegistry and updating the logic to retrieve spawn strategies. The changes seem well-structured and the provided examples are helpful. However, there are a few areas that could be improved, such as adding a null check for platformLabel and improving the error message in the Preconditions.checkNotNull call.

Summary of Findings

  • Missing null check: The code directly dereferences platformLabel without checking if it's null, which could lead to a NullPointerException. A null check should be added before accessing platformLabel.
  • Preconditions check message: The message in the Preconditions.checkNotNull call in StrategyPlatformFilter is not very informative. It should be updated to provide more context about why the execution platform is required.
  • Inconsistent use of var: The code uses var in some places and explicit types in others. It would be more consistent to use either var or explicit types throughout the code.
  • Logging level: The log messages in SpawnStrategyRegistry are at the INFO level, which might be too verbose. Consider using a more appropriate logging level, such as DEBUG.

Merge Readiness

The pull request is not ready for merging. There are a few issues that need to be addressed before merging, such as adding a null check for platformLabel and improving the error message in the Preconditions.checkNotNull call. I am unable to directly approve this pull request, and users should have others review and approve this code before merging.

Copy link

@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: 2

🧹 Nitpick comments (2)
src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java (1)

125-141: Help text and converter mismatch can confuse users

allowed_strategies_by_exec_platform is declared with StringToStringListConverter, which expects key=value1,value2 syntax, but the help text shows multi-line examples and back-ticks.
Two small issues:

  1. Consistency – every other flag uses a regular string, not a text-block. Sticking to one style avoids noise in --help.
  2. Ambiguity – mention explicitly that the option can be repeated and that the right-hand side is comma-separated.

No code breakage, just documentation polish.

src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java (1)

630-668: StrategyPlatformFilter – performance & correctness tweaks

  1. allowedStrategies.contains(strategy) is O(n) over an ImmutableList.
    Convert to an ImmutableSet once in the constructor for O(1) lookups.
  2. The overload that accepts an ImmutableCollection converts via newCopyOnWriteArrayList, incurring unnecessary concurrency overhead. A plain ArrayList suffices.

Not blocking, but an easy micro-optimisation.

📜 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 01357a0.

📒 Files selected for processing (12)
  • src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java (1 hunks)
  • src/main/java/com/google/devtools/build/lib/bazel/rules/BazelStrategyModule.java (2 hunks)
  • src/main/java/com/google/devtools/build/lib/exec/BUILD (2 hunks)
  • src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java (1 hunks)
  • src/main/java/com/google/devtools/build/lib/exec/RemoteLocalFallbackRegistry.java (2 hunks)
  • src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java (14 hunks)
  • src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyResolver.java (1 hunks)
  • src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java (1 hunks)
  • src/test/java/com/google/devtools/build/lib/exec/BUILD (1 hunks)
  • src/test/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistryTest.java (4 hunks)
  • src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java (1 hunks)
  • src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/test/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistryTest.java (1)
src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java (1)
  • SpawnStrategyRegistry (65-743)
🔇 Additional comments (12)
src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java (1)

82-88: Improved platform safety by replacing null with EMPTY_PLATFORM_INFO

This change ensures consistency with the broader execution platform-aware filtering being implemented. By explicitly providing PlatformInfo.EMPTY_PLATFORM_INFO instead of implicitly passing null, the code prevents potential NullPointerExceptions and aligns with the execution platform-based spawn strategy filtering introduced in this PR.

src/main/java/com/google/devtools/build/lib/exec/RemoteLocalFallbackRegistry.java (1)

17-18: Updated interface to support platform-specific strategy selection

The method signature change for getRemoteLocalFallbackStrategy now includes a Spawn parameter, allowing fallback strategies to be selected based on execution platform information associated with each spawn. This change properly aligns with the new execution platform-based strategy filtering functionality.

Also applies to: 32-33

src/main/java/com/google/devtools/build/lib/exec/BUILD (2)

107-110: Added dependency for new options functionality

Adding the config/fragment_options dependency to the execution_options target supports the new command-line option --allowed_strategies_by_exec_platform that filters spawn strategies by execution platform.


367-369: Added dependency for command-line handling

Adding the cmdline dependency to the spawn_strategy_registry target enables parsing and handling of new command-line options for execution platform-specific strategy filtering.

src/test/java/com/google/devtools/build/lib/exec/BUILD (1)

47-49: Added platform dependency for testing execution platform filtering

Adding the analysis/platform dependency enables tests to properly validate the new execution platform-based strategy filtering functionality.

src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyResolver.java (1)

89-94: Clean error message update with new flag information.

The error message was updated to include the new --allowed_strategies_by_exec_platform flag, which is consistent with the PR objective of implementing platform-scoped spawn strategies. Using a text block (triple quotes) also improves readability of the code.

src/main/java/com/google/devtools/build/lib/bazel/rules/BazelStrategyModule.java (1)

21-21: LGTM - Necessary import added.

Added import for Label class which is needed for the new platform filtering functionality.

src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java (1)

558-558: Updated method call to pass spawn parameter.

The method call is correctly updated to pass the spawn instance to the getRemoteLocalFallbackStrategy method, aligning with the new API that enables platform-aware fallback strategy selection.

src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java (1)

267-267: Test correctly updated to match the new API.

The lambda expression now accepts a Spawn parameter (_spawn), properly matching the updated method signature in RemoteLocalFallbackRegistry. The underscore prefix is a common convention indicating the parameter is not used in the lambda body.

src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java (1)

79-84: Early-return guard looks good, just double-check the cost of remoteExecutionProperties()

The additional check correctly treats execution platforms that have no execProperties and no remoteExecutionProperties the same as “no execution platform”.
Because remoteExecutionProperties() returns a (possibly large) string, consider calling it only once and caching the result in a local variable if this method ever appears on a hot path.
Otherwise the change is ✔️.

src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java (1)

174-178: ⚠️ Potential issue

getRemoteLocalFallbackStrategy can NPE / require JDK-21

List#getFirst() is only available since JDK 21.
On older LTS releases (JDK 11/17) this method does not exist, causing compilation failure.

It is also unsafe when remoteLocalFallbackStrategy == null and is filtered-out.

-    return strategyPlatformFilter.getStrategies(
-            spawn, Lists.newArrayList(remoteLocalFallbackStrategy))
-        .getFirst();
+    var filtered =
+        strategyPlatformFilter.getStrategies(
+            spawn, Lists.newArrayList(remoteLocalFallbackStrategy));
+    return filtered.isEmpty() ? null : filtered.get(0);

Likely an incorrect or invalid review comment.

src/test/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistryTest.java (1)

305-321: Test may hide real-world null-platform issues

createSpawnWithMnemonicAndDescription produces a SimpleSpawn without an execution platform, yet the test passes because PlatformInfo.EMPTY_PLATFORM_INFO happens to be returned.
Consider adding a second assertion with a truly null platform (or adapting the production code per earlier comment) to avoid a false sense of security.

@visz11
Copy link
Collaborator

visz11 commented Jul 28, 2025

/refacto-test

Copy link

refacto-test bot commented Jul 28, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

@visz11
Copy link
Collaborator

visz11 commented Jul 31, 2025

/refacto-test

Copy link

refacto-test bot commented Jul 31, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

Copy link

refacto-test bot commented Jul 31, 2025

Solid Implementation - Platform-Based Filtering Needs Reliability Improvements!

Review Summary

This PR introduces platform-specific spawn strategy filtering which enhances the build system's flexibility. The implementation follows good design patterns with proper separation of concerns and maintains backward compatibility. However, several reliability issues need to be addressed, particularly around null handling and edge cases. The most critical concerns are potential NullPointerExceptions when accessing execution platform properties and insufficient handling of empty execution platforms. Addressing these issues will ensure the feature is robust and production-ready.

Well Done!!!

  • The implementation properly extends the existing strategy filtering mechanism with a clean design pattern that maintains backward compatibility
  • The code includes comprehensive test coverage for the new platform filtering functionality
  • The error message enhancement provides more helpful guidance to users when strategies are unavailable

Files Processed

src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java 172-653
src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java 76-83

📌 Additional Comments (5)

Security Considerations

Potential Bypass of Execution Platform Restrictions

Explanation: The modified condition in PlatformUtils.java creates a potential security vulnerability by allowing execution to proceed even when an execution platform is present but has empty properties. This change could bypass intended execution restrictions if a platform is specified but its properties are empty. Consider strengthening the validation for platforms with empty properties.

if ((spawn.getExecutionPlatform() == null
        || (
          spawn.getExecutionPlatform().execProperties().isEmpty()
          && spawn.getExecutionPlatform().remoteExecutionProperties().isEmpty()
        ))
+ // Consider separating the null check from the empty properties check:
+ // var platform = spawn.getExecutionPlatform();
+ // if ((platform == null || validateEmptyPlatform(platform)) && otherChecks...)

Consider Adding Validation for Platform Labels

Explanation: Consider adding validation to ensure platform labels come from trusted sources before using them to filter strategies. This would prevent potential privilege escalation if an attacker could craft a malicious platform label.

var platformLabel = spawn.getExecutionPlatformLabel();
+ // Consider adding validation for platform labels:
+ // if (!isTrustedPlatformLabel(platformLabel)) {
+ //   logger.warning("Untrusted platform label: %s", platformLabel);
+ //   return candidateStrategies;
+ // }

Performance Optimizations

Inefficient Collection Conversion in getStrategies Method

Explanation: The method converts an ImmutableCollection to a CopyOnWriteArrayList and then back to an ImmutableList, which creates unnecessary temporary collections. Using ArrayList instead would be more efficient.

public <T extends SpawnStrategy> ImmutableCollection<T> getStrategies(
        Spawn spawn, ImmutableCollection<T> candidateStrategies) {
      return ImmutableList.copyOf(getStrategies(spawn, Lists.newCopyOnWriteArrayList(candidateStrategies)));
+ // Consider replacing with:
+ // return ImmutableList.copyOf(getStrategies(spawn, new ArrayList<>(candidateStrategies)));

Maintainability Improvements

Duplicated Strategy Filtering Logic

Explanation: The StrategyPlatformFilter class contains duplicated filtering logic in two methods: one for List and another for ImmutableCollection. This violates the DRY principle and creates unnecessary maintenance overhead.

public <T extends SpawnStrategy> List<T> getStrategies(
        Spawn spawn, List<T> candidateStrategies) {
+ // Consider simplifying the ImmutableCollection method implementation:
+ // public <T extends SpawnStrategy> ImmutableCollection<T> getStrategies(
+ //     Spawn spawn, ImmutableCollection<T> candidateStrategies) {
+ //   return ImmutableList.copyOf(getStrategies(spawn, new ArrayList<>(candidateStrategies)));
+ // }

Inconsistent Null Handling in RemoteLocalFallbackStrategy

Explanation: The implementation of getRemoteLocalFallbackStrategy(Spawn spawn) assumes that remoteLocalFallbackStrategy is never null. If it is null, Lists.newArrayList(null) will create a list with a null element, potentially causing issues.

public AbstractSpawnStrategy getRemoteLocalFallbackStrategy(Spawn spawn) {
    return strategyPlatformFilter.getStrategies(spawn, Lists.newArrayList(remoteLocalFallbackStrategy))
        .getFirst();
+ // Consider adding a null check:
+ // if (remoteLocalFallbackStrategy == null) {
+ //   return null;
+ // }

Comment on lines +638 to +646
this.platformToStrategies = platformToStrategies;
}

public <T extends SpawnStrategy> List<T> getStrategies(
Spawn spawn, List<T> candidateStrategies) {
var platformLabel = spawn.getExecutionPlatformLabel();
Preconditions.checkNotNull(platformLabel, "Attempting to spawn action without an execution platform.");

var allowedStrategies = platformToStrategies.get(platformLabel);
Copy link

Choose a reason for hiding this comment

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

Potential N+1 Performance Issue in Platform Filter Strategy Selection

The current implementation iterates through all candidate strategies for each spawn, checking if each strategy is in the allowed strategies list. This creates an O(n*m) operation where n is the number of candidate strategies and m is the number of allowed strategies. For platforms with many strategies and frequent spawns, this could create unnecessary CPU overhead. Additionally, the linear search pattern can be inefficient for large strategy collections.

      var allowedStrategies = platformToStrategies.get(platformLabel);
      if (allowedStrategies != null) {
        // Convert to HashSet for O(1) lookups instead of O(n) contains() operations
        Set<SpawnStrategy> allowedStrategiesSet = new HashSet<>(allowedStrategies);
        List<T> filteredStrategies = new ArrayList<>();
        for (var strategy : candidateStrategies) {
          if (allowedStrategiesSet.contains(strategy)) {
            filteredStrategies.add(strategy);
          }
        }
        // If filtering resulted in an empty list, return original candidates
        // to ensure at least one strategy is available
        return filteredStrategies.isEmpty() ? candidateStrategies : filteredStrategies;
      }
References

Standard: Google's Core Performance Principles - Hot Path Optimization

@arvi18
Copy link
Author

arvi18 commented Jul 31, 2025

/refacto-test

Copy link

refacto-test bot commented Jul 31, 2025

PR already reviewed at the latest commit: 01357a0.
Please try again with new changes.

@arvi18
Copy link
Author

arvi18 commented Jul 31, 2025

/refacto-test

Copy link

refacto-test bot commented Jul 31, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

@arvi18
Copy link
Author

arvi18 commented Jul 31, 2025

/refacto-test

Copy link

refacto-test bot commented Jul 31, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

@visz11
Copy link
Collaborator

visz11 commented Aug 22, 2025

/refacto-test

Copy link

refacto-test bot commented Aug 22, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

Copy link

refacto-test bot commented Aug 22, 2025

Code Review: Platform-specific Spawn Strategy Implementation

👍 Well Done
Platform-specific strategy filtering

Adds execution platform filtering for spawn strategies enhancing reliability and control

Comprehensive implementation

Thoroughly implements platform filtering across strategy resolver, registry and fallback mechanisms

📌 Files Processed
  • src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java
  • src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java
  • src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyResolver.java
  • src/test/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistryTest.java
  • src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java
  • src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
  • src/main/java/com/google/devtools/build/lib/bazel/rules/BazelStrategyModule.java
  • src/main/java/com/google/devtools/build/lib/exec/BUILD
  • src/main/java/com/google/devtools/build/lib/exec/RemoteLocalFallbackRegistry.java
  • src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java
  • src/test/java/com/google/devtools/build/lib/exec/BUILD
  • src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java

public <T extends SpawnStrategy> List<T> getStrategies(
Spawn spawn, List<T> candidateStrategies) {
var platformLabel = spawn.getExecutionPlatformLabel();
Preconditions.checkNotNull(platformLabel, "Attempting to spawn action without an execution platform.");
Copy link

Choose a reason for hiding this comment

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

Null pointer risk in platform label validation

The null check for platformLabel will throw NPE when a spawn has no execution platform. This contradicts the existing code in getPlatformProto that handles null execution platforms gracefully.

Suggested change
Preconditions.checkNotNull(platformLabel, "Attempting to spawn action without an execution platform.");
if (platformLabel == null) {
return candidateStrategies;
}
Standards
  • ISO-IEC-25010-Reliability-Fault-Tolerance
  • SRE-Graceful-Degradation

Comment on lines +175 to +177
public AbstractSpawnStrategy getRemoteLocalFallbackStrategy(Spawn spawn) {
return strategyPlatformFilter.getStrategies(spawn, Lists.newArrayList(remoteLocalFallbackStrategy))
.getFirst();
Copy link

Choose a reason for hiding this comment

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

NoSuchElementException risk in remote fallback strategy

If remoteLocalFallbackStrategy is null, Lists.newArrayList will create an empty list, and calling getFirst() on an empty list will throw NoSuchElementException, causing runtime failures.

Suggested change
public AbstractSpawnStrategy getRemoteLocalFallbackStrategy(Spawn spawn) {
return strategyPlatformFilter.getStrategies(spawn, Lists.newArrayList(remoteLocalFallbackStrategy))
.getFirst();
public AbstractSpawnStrategy getRemoteLocalFallbackStrategy(Spawn spawn) {
if (remoteLocalFallbackStrategy == null) {
return null;
}
return strategyPlatformFilter.getStrategies(spawn, Lists.newArrayList(remoteLocalFallbackStrategy))
.getFirst();
Standards
  • ISO-IEC-25010-Reliability-Fault-Tolerance
  • SRE-Defensive-Programming

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.

3 participants