Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/rules/workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ basis:
* Run the workspace helper script to configure upstream tracking and safe
pushing:
```bash
.agents/scripts/setup_triangle_branch.sh <branch>
.agents/scripts/setup_client.py <branch>
```
* Never use `git push -u` or `--set-upstream` (it breaks upstream tracking).
* When pushing to a checked-out PR branch from an external fork, push
Expand Down
103 changes: 103 additions & 0 deletions .agents/scripts/setup_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""Configures git tracking and user environment for rules_python worktrees."""

from __future__ import annotations

import argparse
import subprocess
import sys
from pathlib import Path


def _get_current_branch() -> str:
result = subprocess.run(
["git", "symbolic-ref", "--short", "HEAD"],
capture_output=True,
text=True,
check=False,
)
if result.returncode != 0:
return ""
return result.stdout.strip()


def _get_workspace_root() -> Path:
result = subprocess.run(
["git", "rev-parse", "--show-toplevel"],
capture_output=True,
text=True,
check=True,
)
return Path(result.stdout.strip())


def setup_triangle_branch(branch: str) -> None:
"""Configures local git tracking to pull from upstream and push to origin."""
print(f"Setting up upstream tracking for branch: {branch}")
subprocess.check_call(
["git", "config", "--local", f"branch.{branch}.remote", "upstream"]
)
subprocess.check_call(
["git", "config", "--local", f"branch.{branch}.merge", "refs/heads/main"]
)
subprocess.check_call(
["git", "config", "--local", f"branch.{branch}.pushRemote", "origin"]
)
subprocess.check_call(["git", "config", "--local", "push.default", "current"])
print(
"Successfully configured upstream/main tracking and origin pushRemote "
f"for {branch}!"
)


def setup_buildbuddy_user_bazelrc(workspace_root: Path) -> None:
"""Links user BuildBuddy config to workspace user.bazelrc if not present."""
source_rc = (
Path.home() / ".config" / "rules_python" / "buildbuddy.bazelrc"
).resolve()
target_rc = workspace_root / "user.bazelrc"

if not source_rc.exists():
print(
f"Note: {source_rc} not found. Skipping user.bazelrc link "
"(BuildBuddy RBE may not work for local invocations)."
)
return

# Only create the symlink if user.bazelrc does not already exist
if target_rc.exists() or target_rc.is_symlink():
print(f"user.bazelrc already exists at {target_rc}. Skipping link.")
return

target_rc.symlink_to(source_rc)
print(f"Linked {source_rc} -> {target_rc}")


def main() -> int:
parser = argparse.ArgumentParser(
description="Setup git tracking and environment for rules_python workspace."
)
parser.add_argument(
"branch",
nargs="?",
default=None,
help="Branch name to configure (defaults to current branch)",
)
args = parser.parse_args()

branch = args.branch or _get_current_branch()
if not branch:
print(
"Error: Could not detect current branch name and none was provided.",
file=sys.stderr,
)
return 1

workspace_root = _get_workspace_root()
setup_triangle_branch(branch)
setup_buildbuddy_user_bazelrc(workspace_root)
return 0


if __name__ == "__main__":
sys.exit(main())
25 changes: 0 additions & 25 deletions .agents/scripts/setup_triangle_branch.sh

This file was deleted.

8 changes: 8 additions & 0 deletions .github/actions/setup-bazel/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ runs:
build --output_groups=-pyrefly
build --//python/config_settings:py_pbs_distribution=install_only_stripped
${{ inputs.buildbuddy_api_key && format('common --config={0}', inputs.buildbuddy_config) || '' }}
build --build_metadata=ROLE=CI
build --build_metadata=VISIBILITY=PUBLIC
build --build_metadata=RUN_ID=${{ github.run_id }}
build --build_metadata=ACTOR=${{ github.actor }}
build --build_metadata=COMMIT_SHA=${{ github.event.pull_request.head.sha || github.sha }}
${{ github.event.pull_request.number && format('build --build_metadata=PR_NUMBER={0}', github.event.pull_request.number) || '' }}
${{ (github.head_ref || github.ref_name) && format('build --build_metadata=BRANCH_NAME={0}', github.head_ref || github.ref_name) || '' }}
build --build_metadata="BUILDBUDDY_LINKS=[GHA Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"

# setup-bazel only configures Bazelisk and restores caches; the Bazel
# binary itself is downloaded by Bazelisk on first invocation. Because
Expand Down
17 changes: 17 additions & 0 deletions buildbuddy.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,26 @@
# `user.bazelrc` or passed by CI.
build:_buildbuddy_base --bes_results_url=https://rules-python.buildbuddy.io/invocation/
build:_buildbuddy_base --bes_backend=grpcs://rules-python.buildbuddy.io
build:_buildbuddy_base --build_metadata=REPO_URL=https://github.com/bazel-contrib/rules_python
common:_buildbuddy_base --remote_cache=grpcs://rules-python.buildbuddy.io
common:_buildbuddy_base --remote_timeout=10m
common:_buildbuddy_base --remote_executor=grpcs://rules-python.buildbuddy.io
# Compress remote cache transfers with zstd to improve network throughput.
common:_buildbuddy_base --remote_cache_compression
# Chunk large blobs using FastCDC (SplitBlob/SpliceBlob) for efficient
# deduplicated transfer.
common:_buildbuddy_base --experimental_remote_cache_chunking
# Automatically rewind and regenerate lost inputs when evicted from remote cache.
common:_buildbuddy_base --rewind_lost_inputs

# Diagnostic logs for troubleshooting cache misses and gRPC errors
common:_buildbuddy_base --remote_grpc_log=bazel-remote-grpc.log
common:_buildbuddy_base --execution_log_compact_file=bazel-execution-log.binpb.zst

# Detailed timing profiles for the BuildBuddy Timing tab
common:_buildbuddy_base --noslim_profile
common:_buildbuddy_base --experimental_profile_include_target_label
common:_buildbuddy_base --experimental_profile_include_primary_output
# Re-apply `--enable_platform_specific_config` after setting `--remote_executor`
# so `common:macos` and `common:windows` in `.bazelrc` inherit the priority of
# `--config=buildbuddy_*` (e.g. when set in `~/.bazelrc` by `setup-bazel`,
Expand Down
45 changes: 43 additions & 2 deletions tests/workflows/setup_bazel_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,55 @@ def test_action_yaml_enables_buildbuddy_on_all_os():
action = yaml.safe_load((_action_dir() / "action.yaml").read_text(encoding="utf-8"))
steps = action["runs"]["steps"]
setup_step = next(s for s in steps if s.get("name") == "Setup Bazel")
assert "inputs.buildbuddy_api_key" in setup_step["with"]["bazelrc"]
assert "runner.os" not in setup_step["with"]["bazelrc"]
bazelrc = setup_step["with"]["bazelrc"]
assert "inputs.buildbuddy_api_key" in bazelrc
assert "runner.os" not in bazelrc
assert "ROLE=CI" in bazelrc
assert "VISIBILITY=PUBLIC" in bazelrc
assert "RUN_ID=" in bazelrc
assert "ACTOR=" in bazelrc
assert "COMMIT_SHA=" in bazelrc
assert "PR_NUMBER=" in bazelrc
assert "BRANCH_NAME=" in bazelrc
assert '--build_metadata="BUILDBUDDY_LINKS=' in bazelrc
secret_step = next(
s for s in steps if s.get("name") == "Write secret to user.bazelrc"
)
assert secret_step["if"] == "${{ inputs.buildbuddy_api_key != '' }}"


def test_buildbuddy_bazelrc_cache_and_diagnostics():
"""Verifies buildbuddy.bazelrc includes recommended cache, diagnostic, and
profiling flags.
"""
rf = runfiles.CreateOrRaise()
buildbuddy_path = rf.root() / "rules_python/buildbuddy.bazelrc"
buildbuddy_lines = [
line.strip()
for line in buildbuddy_path.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.strip().startswith("#")
]
expected_flags = [
(
"build:_buildbuddy_base "
"--build_metadata=REPO_URL=https://github.com/bazel-contrib/rules_python"
),
"common:_buildbuddy_base --remote_cache_compression",
"common:_buildbuddy_base --experimental_remote_cache_chunking",
"common:_buildbuddy_base --rewind_lost_inputs",
"common:_buildbuddy_base --remote_grpc_log=bazel-remote-grpc.log",
(
"common:_buildbuddy_base "
"--execution_log_compact_file=bazel-execution-log.binpb.zst"
),
"common:_buildbuddy_base --noslim_profile",
"common:_buildbuddy_base --experimental_profile_include_target_label",
"common:_buildbuddy_base --experimental_profile_include_primary_output",
]
for flag in expected_flags:
assert flag in buildbuddy_lines, f"Expected '{flag}' in buildbuddy.bazelrc"


def test_buildbuddy_bazelrc_disables_remote_executor_on_macos_and_windows():
"""Verifies .bazelrc and buildbuddy.bazelrc disable remote_executor on macOS and Windows."""
rf = runfiles.CreateOrRaise()
Expand Down
Loading