Skip to content

Add --writeEmptyOutput flag on get-impacted-targets#358

Closed
tinder-maxwellelliott wants to merge 4 commits into
masterfrom
claude/silly-kowalevski-6cd077
Closed

Add --writeEmptyOutput flag on get-impacted-targets#358
tinder-maxwellelliott wants to merge 4 commits into
masterfrom
claude/silly-kowalevski-6cd077

Conversation

@tinder-maxwellelliott
Copy link
Copy Markdown
Collaborator

Summary

Inspired by ewhauser/bazel-differ's --output-on-empty, this adds an opt-in --no-writeEmptyOutput flag on get-impacted-targets. When set, the command skips creating the output file entirely if no targets are impacted, so CI can branch on file existence instead of file contents:

bazel-diff get-impacted-targets ... --no-writeEmptyOutput -o impacted.txt
if [ -f impacted.txt ]; then
  bazel test --target_pattern_file=impacted.txt
fi
  • Defaults to true (current behavior, always write).
  • Only applies when -o/--output is set; STDOUT is unaffected.
  • The interactor's execute / executeWithDistances are refactored into a pure compute* step + a write* step. The CLI now computes first and short-circuits before opening the output file when the set is empty and the user opted out. The original execute* entry points stay (now thin wrappers) so the existing tests and any external callers continue to work unchanged.

Background

This came out of a scheduled audit comparing our approach against three alternative differ projects. Findings:

  • ewhauser/bazel-differ — small UX wins: --output-on-empty (this PR) and an end-to-end get-targets wrapper with a disk-backed hash cache. The rest of the fork is years behind ours on correctness (no bzlmod, naive external-repo collapse, no cquery mode, no version gating, debug Println left in production).
  • bazel-contrib/target-determinator — one real correctness gap: configuration-aware hashing under cquery. That's a sizable refactor (key on (label, configuration) through TargetDigest/RuleHasher/BuildGraphHasher) and warrants a separate design discussion — filing a follow-up issue.
  • friel-openai/bazel-differous — explicit parity port aimed at matching us; nothing actionable. On bzlmod they're materially behind ours.

Test plan

  • bazel test //cli:CalculateImpactedTargetsInteractorTest — passes (new computeImpactedTargets_returnsEmpty_whenStartAndFinalMatch covers the compute step's empty case).
  • bazel test //cli:CalculateImpactedTargetsInteractorModuleQueryTest //cli:CalculateImpactedTargetsInteractorIssue335Test — both still pass; existing execute/executeWithDistances paths are intact.
  • bazel test //cli:E2ETest --test_filter=testGetImpactedTargets_writeEmptyOutput — new E2E test exercises all three cases (empty diff + --no-writeEmptyOutput → no file; empty diff with default → empty file; non-empty diff with --no-writeEmptyOutput → file IS written).
  • bazel test //cli:E2ETest --test_filter=testE2E$ — primary E2E still green.
  • bazel test //cli:E2ETest --test_filter=testTargetDistanceMetricsexecuteWithDistances path still green.
  • CI: full Ubuntu+macOS × Bazel 7/8/9 matrix.

🤖 Generated with Claude Code

tinder-maxwellelliott and others added 4 commits May 20, 2026 12:45
Wires up a shields.io endpoint badge sourced from coverage.json in the
repo so the README always shows the latest tested main-source coverage.

- tools/coverage_check.py gains a --badge-json PATH flag that writes the
  shields.io endpoint schema (color-banded against the 90% gate). Writing
  is decoupled from the threshold gate so a regression still surfaces in
  the badge instead of silently freezing on the last-good value.
- CI's existing coverage step is split into a Generate step (--threshold
  0, never gates) and the original strict Enforce step. A new Publish
  step commits coverage.json back to master on pushes and to the PR head
  branch on internal pull requests, so reviewers see the coverage delta
  directly in the PR diff. Skipped on fork PRs (GITHUB_TOKEN is
  read-only against forks) and on non-canonical matrix entries to avoid
  races on the same file.
- coverage.json is seeded with a "pending" placeholder so the badge
  renders correctly before the first master-merge CI run replaces it
  with the real value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reverts the PR auto-update path: PRs no longer get a github-actions[bot]
commit updating coverage.json on each push. The badge now reflects
master's tested state, full stop.

The two-step Generate/Enforce split is collapsed back into the single
Enforce step (which still writes the badge as a side effect via
--badge-json, since the script writes before gating).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Inspired by ewhauser/bazel-differ's --output-on-empty: let CI branch on
file existence instead of file contents (`[ -f impacted.txt ] && bazel
test --target_pattern_file=...`) without having to also probe whether
the file is empty. Defaults to true so existing pipelines are unaffected.

Split the interactor's execute/executeWithDistances into pure
compute + write halves so the CLI can short-circuit the file open when
the impacted set is empty and the user opted out of empty output.
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.

1 participant