fix(lint): handle BES/remote-download race for lint output files (#1148)
With remote execution, Bazel streams `named_set_of_files` BES events as soon as an action completes on the remote executor — before `--remote_download_regex` transfers have completed locally. The lint BES loop was calling `read_to_string` immediately on receipt of the event, causing a fatal `No such file or directory` crash. Root cause confirmed via Bazel source: `RemoteExecutionService.java` downloads blobs to a unique temp path, then atomically renames to the final location via `FileSystemUtils.moveFile` (`moveOutputsToFinalLocation` L930). `fs.exists()` returning `True` therefore means the file is fully written with no partial-read risk. See: https://github.com/bazelbuild/bazel/blob/d3c9a2080e30cecd661c02a8f0cce84caa696aed/src/main/java/com/google/devtools/build/lib/remote/RemoteExecutionService.java#L930 **Changes in this PR:** - All lint file reads (`.out`, `.report`, `.patch`, `.exit_code`) are routed through `_try_process_lint_file`, which guards with `fs.exists()` and returns `None` when the file isn't on disk yet. Not-yet-available files are queued in `pending_files` and retried each 250 ms tick via a shared `_drain_pending_files` helper used by both the tick loop and the post-build drain. - After `build.wait()`, a bounded post-build drain polls for up to 30 seconds before warning and skipping any files that still haven't landed. - `rules_lint_human` and `rules_lint_machine` are separate action sets in rules_lint — requesting both runs each linter twice. We now pick exactly one: interactive (local TTY, not CI) → `rules_lint_human`; everything else → `rules_lint_machine`. Non-interactive / CI runs always get `rules_lint_machine`, preventing a silent "no lint results" failure when no hooks requested machine output. - `detect_ci()` is checked alongside `is_tty`: some CI hosts (e.g. GitHub Actions) allocate a pseudo-TTY, making `is_tty` True while the correct output is still machine. --- ### Changes are visible to end-users: yes - Searched for relevant documentation and updated as needed: no - Breaking change (forces users to change their own code or config): no - Suggested release notes appear below: yes Previously, `aspect lint` could crash with a fatal `No such file or directory` error when using remote execution, because BES events for lint output files can arrive before Bazel finishes downloading them. The lint task now queues those files and retries each tick, with a 30-second timeout after the build completes. Also fixes: `.patch` files were subject to the same race; non-TTY/CI runs now always select `rules_lint_machine` output (previously could silently produce no output groups and exit with a misleading "no lint results" error); `detect_ci()` prevents CI hosts with pseudo-TTYs from incorrectly selecting human output. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
G
Greg Magolan committed
5b667cb249819360d964fdcf0e572687cc233902
Parent: 1f62b9a
Committed by GitHub <noreply@github.com>
on 5/27/2026, 6:48:10 PM