Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e9dc45f
build(ci): align Rust with Blaze and allow fleet fallback
ScriptedAlchemy Oct 25, 2026
0d9769f
fix(ci): preserve prepared release fleet configuration
ScriptedAlchemy Oct 25, 2026
d8e95ad
fix(runtime): bound native Git startup future layout
ScriptedAlchemy Oct 25, 2026
4ec5cd6
fix(bazel): validate production features during generation
ScriptedAlchemy Oct 25, 2026
72bf941
fix(bazel): declare Cargo acquisition tools and policy
ScriptedAlchemy Oct 25, 2026
72b8cf5
Merge branch 'master' of https://github.com/ScriptedAlchemy/tracedeca…
ScriptedAlchemy Oct 25, 2026
b642d80
test(release): keep refresh fixture in provisioned CI
ScriptedAlchemy Oct 25, 2026
6351b51
fix(ci): let local-tagged tests spawn beside dynamic
ScriptedAlchemy Oct 25, 2026
1a01382
Merge branch 'master' into build/rust-1.99-blaze-compat
ScriptedAlchemy Oct 25, 2026
c3fde96
fix(ci): bound Windows compiler concurrency
ScriptedAlchemy Oct 25, 2026
8bb08a0
fix(ci): scope native concurrency to Windows
ScriptedAlchemy Oct 25, 2026
aad9d69
build(blaze): add pinned native launcher and workspace CI
ScriptedAlchemy Oct 25, 2026
ddc8b3c
fix(ci): resolve Blaze runtime paths on the runner
ScriptedAlchemy Oct 25, 2026
f112f4c
fix(blaze): enable the shared shallow acquisition policy
ScriptedAlchemy Oct 25, 2026
f0e8508
fix(blaze): propagate acquisition policy to metadata loaders
ScriptedAlchemy Oct 25, 2026
aecd7cc
docs(bazel): explain macOS worker hardlink permissions
ScriptedAlchemy Oct 26, 2026
be85029
docs(bazel): document shared APFS worker input trees
ScriptedAlchemy Oct 26, 2026
199785e
fix(blaze): use the selected Cargo for unit graph loading
ScriptedAlchemy Oct 26, 2026
e5cf9d9
build(ci): leave optimization to release jobs
ScriptedAlchemy Oct 26, 2026
dbb6b96
fix(blaze): avoid overlapping cold compiler warmups
ScriptedAlchemy Oct 26, 2026
33f1a52
fix(clippy): pin large pending-stop scout futures
ScriptedAlchemy Oct 26, 2026
939359b
ci: integrate master fleet-start-alongside-gates
ScriptedAlchemy Oct 26, 2026
36bb76d
fix(ci): avoid redundant Windows debug databases
ScriptedAlchemy Oct 26, 2026
219546f
fix(blaze): budget the cold native compiler bootstrap
ScriptedAlchemy Oct 26, 2026
d982d26
fix(ci): disable MSVC fastbuild before stripping PDBs
ScriptedAlchemy Oct 26, 2026
233a253
fix(ci): isolate Windows cache after PDB removal
ScriptedAlchemy Oct 26, 2026
efebdec
Merge remote-tracking branch 'origin/master' into HEAD
ScriptedAlchemy Oct 26, 2026
48c1e2c
Merge remote-tracking branch 'origin/master' into HEAD
ScriptedAlchemy Oct 26, 2026
2b25d1b
fix(runtime): complete expired timers before scheduling work
ScriptedAlchemy Oct 26, 2026
2ac59f4
Merge master into build/rust-1.99-blaze-compat
ScriptedAlchemy Oct 26, 2026
547bbce
fix(ci): restore assertion-enabled runtime optimization
ScriptedAlchemy Oct 26, 2026
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
21 changes: 9 additions & 12 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,12 @@ common --show_progress_rate_limit=15
# The shared fleet CAS uses size-based eviction, so it cannot guarantee
# Bazel's default three-hour retention. Revalidate remote outputs before reuse.
build --experimental_remote_cache_ttl=0s
# crate_universe re-fetches git dependencies into an empty CARGO_HOME on every
# splice. libgit2 indexes asupersync's ~1 GB history on one thread for over 25
# minutes; the git CLI indexes it in about 2.
common --repo_env=CARGO_NET_GIT_FETCH_WITH_CLI=true
# Fetch only the pinned commit of each git dependency: 76 MB instead of 1.3 GB,
# and a cold splice drops from about 6 minutes to 1. The splice runs rules_rust's
# stable host cargo, which reads -Z options only under RUSTC_BOOTSTRAP. A nightly
# host cargo would download another 418 MB toolchain on every CI job.
common --repo_env=CARGO_UNSTABLE_GIT=shallow-deps
# Cargo reads the unstable acquisition policy during repository evaluation.
common --repo_env=RUSTC_BOOTSTRAP=1
# MODULE.bazel registers only nightly/2026-10-25. Without this, rules_rust
# resolves the stable channel and the build fails closed.
# MODULE.bazel registers the pinned stable compiler.
# Hosts can extend this repository profile with their private fleet settings.
build --config=tracedecay
build:tracedecay --@rules_rust//rust/toolchain/channel=nightly
build:tracedecay --@rules_rust//rust/toolchain/channel=stable
build --incompatible_enable_cc_toolchain_resolution
build --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
build --workspace_status_command=scripts/bazel/workspace_status.sh
Expand Down Expand Up @@ -72,11 +63,17 @@ build:clippy --@rules_rust//rust/settings:pipelined_compilation=true
build:clippy --@rules_rust//rust/settings:clippy_flag=-Dwarnings
build:clippy --@rules_rust//rust/settings:clippy.toml=//:clippy.toml

# Default tests and their build-time tools use the assertion-enabled perf levels.
build --compilation_mode=fastbuild
build --host_compilation_mode=fastbuild

# Externals return to opt-level 3 over the perf overrides below.
build:release --compilation_mode=opt
build:release --host_compilation_mode=opt
build:release --@rules_rust//rust/settings:per_crate_rustc_flag=external/@-Copt-level=3

build:dist --compilation_mode=opt
build:dist --host_compilation_mode=opt
build:dist --@rules_rust//rust/settings:per_crate_rustc_flag=external/@-Copt-level=3
build:dist --@rules_rust//rust/settings:lto=thin
build:dist --@rules_rust//rust/settings:extra_rustc_flag=-Ccodegen-units=1
Expand Down
5 changes: 5 additions & 0 deletions .cargo/acquisition.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[net]
git-fetch-with-cli = true

[unstable]
git = "shallow-deps"
17 changes: 3 additions & 14 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,9 @@ linker = "scripts/macos-sign-linker.sh"
[alias]
# Full Rust test suite. Requires cargo-nextest:
# https://nexte.st/docs/installation/pre-built-binaries/
# Both aliases build with the perf cargo profile, which keeps the
# critical-path kernels (code index, graph, sha2, …) optimized for the
# generation-scale suites; see [profile.perf] in the root Cargo.toml.
#
# `test-ci` is the hosted acceptance selection: nextest's `ci` policy
# (.config/nextest.toml: fail-fast off, one retry that still fails flaky
# results, 8 threads, slow-timeout termination), the root fixture feature and
# `search-eval`, which is what compiles the evaluator acceptance suites (the
# root crate's dependency on the evaluator is optional so the Linux transport
# partition does not link it; a `--workspace` run resolves the evaluator
# anyway). `.github/workflows/ci.yml` runs this
# exact alias, and its support binaries/archives are built with `--profile
# perf` so they share artifacts with it. Extra flags append: `cargo test-ci
# --locked -E 'binary(=x)'`.
# Full-suite aliases share the assertion-enabled perf profile. Hosted CI
# runs Bazel targets generated from the same per-crate optimization levels.
# Extra filters append, for example: cargo test-ci --locked -E 'binary(=x)'.
test-ci = "nextest run --workspace --profile ci --features tracedecay/test-helpers,tracedecay/search-eval --cargo-profile perf"
# Deliberately broader than CI: every optional feature (test-transport
# acceptance suites, …) under the same cargo profile, with the
Expand Down
7 changes: 6 additions & 1 deletion .github/actions/build-cli/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ inputs:
Bazel config. `dist` is the shipping-tuned compile (thin LTO, strip,
codegen-units=1). `release` is opt-level 3 without LTO, the CI / cargo
`--release` equivalent; tracedecay-cli's default features are
`production`, the release source profile. `ci` is a dev-profile build.
`production`, the release source profile. `ci` uses the assertion-enabled
per-crate optimization levels from Cargo's `perf` profile.
required: true
dest:
description: Directory the binary is copied into, as tracedecay[.exe].
required: true
cache-key:
description: Disk-cache name (see the setup-bazel action).
required: true
prepared-build:
description: Whether the caller already configured Bazel for this build.
default: "false"
tailscale-client-id:
description: Restricted OIDC client for compatible trusted CI builds.
default: ""
Expand All @@ -31,6 +35,7 @@ runs:
steps:
- uses: ./.github/actions/setup-bazel
id: bazel
if: inputs.prepared-build != 'true'
with:
cache-key: ${{ inputs.cache-key }}
tailscale-client-id: ${{ inputs.tailscale-client-id }}
Expand Down
83 changes: 27 additions & 56 deletions .github/actions/setup-bazel/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ inputs:

outputs:
fleet-enabled:
description: Whether this job uses private workers and dynamic execution.
value: ${{ inputs.tailscale-client-id != '' }}
description: Whether Tailscale enrollment and executor connectivity enabled the fleet.
value: ${{ steps.fleet.outputs.enabled }}
disk-cache-path:
description: Action-cache directory to save after the caller's build.
value: ${{ steps.disk-cache-config.outputs.path }}
Expand Down Expand Up @@ -88,17 +88,6 @@ runs:
# D:/_bazel) keeps MSVC's header paths under MAX_PATH.
output-base: ${{ runner.os == 'Windows' && 'D:/b' || '' }}

# Bazel validates action contents itself. A fresh save key retains new
# source-build outputs even when MODULE.bazel and BUILD files are unchanged.
- name: Restore master action cache
id: disk-cache
if: inputs.tailscale-client-id == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.disk-cache-config.outputs.path }}
key: ${{ steps.disk-cache-config.outputs.prefix }}run-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}
restore-keys: ${{ steps.disk-cache-config.outputs.restore-keys }}

- name: Preserve the runner network environment for Tailscale
if: runner.os == 'Linux' && inputs.tailscale-client-id != ''
shell: bash
Expand All @@ -118,57 +107,39 @@ runs:
sudo visudo -cf /etc/sudoers.d/tailscale-ci-network

- name: Connect to the private Bazel fleet
id: tailscale
if: inputs.tailscale-client-id != ''
# Private infrastructure is optional; compilation and test failures are not.
continue-on-error: true
uses: tailscale/github-action@99a8333667fff04fdd6cffb46dfd409f8329a7bf # v4
with:
oauth-client-id: ${{ inputs.tailscale-client-id }}
audience: api.tailscale.com/${{ inputs.tailscale-client-id }}
tags: tag:bazel-ci
ping: ubuntu-main

- name: Share compilation and tests with private workers
if: inputs.tailscale-client-id != ''
- name: Select private executor or hosted execution
id: fleet
shell: bash
env:
TAILSCALE_OUTCOME: ${{ steps.tailscale.outcome }}
run: |
case "$RUNNER_OS/$RUNNER_ARCH" in
Linux/X64)
profile=rbe-linux
mkdir -p /tmp/zig-cache
;;
macOS/ARM64) profile=rbe-macos ;;
*)
echo "No compatible fleet worker for $RUNNER_OS/$RUNNER_ARCH" >&2
exit 1
;;
esac
# Use the checkout's existing local rc import for fleet settings.
# Tests carry their tools in runfiles, so both branches use identical inputs.
printf 'build --config=%s\n' "$profile" > .bazelrc.local
cat >> .bazelrc.local <<'RC'
build --remote_executor=grpc://ubuntu-main:50051
build --remote_cache=grpc://ubuntu-main:50051
build --remote_instance_name=main
build --remote_timeout=600
# Survive brief coordinator restarts; five retries expire in about 3s.
build --remote_retries=10
# Fleet compilation must not fall back onto the smaller hosted VM.
# Dynamic tests still have their explicitly scheduled local branch.
build --noremote_local_fallback
build --remote_download_outputs=toplevel
build --jobs=40
build --local_resources=cpu=HOST_CPUS
build --local_resources=memory=HOST_RAM*.5
build --internal_spawn_scheduler
build --dynamic_local_strategy=sandboxed
build --dynamic_remote_strategy=remote
# Large Rust links raced on the hosted VM while the same actions ran
# remotely. local_resources only schedules estimates; it does not cap
# rustc memory. Keep compilation on the fleet and tests hybrid.
build --strategy=Rustc=remote
build --strategy=TestRunner=dynamic
build --bes_backend=grpc://ubuntu-main:1985
build --bes_results_url=https://ubuntu-main.tail039078.ts.net/invocation/
build --bes_timeout=30s
build --bes_upload_mode=fully_async
RC
python3 "$GITHUB_ACTION_PATH/configure_fleet.py"

- name: Prepare the Linux fleet toolchain cache
if: steps.fleet.outputs.enabled == 'true' && runner.os == 'Linux'
shell: bash
run: mkdir -p /tmp/zig-cache

# Bazel validates action contents itself. A fresh save key retains new
# source-build outputs even when MODULE.bazel and BUILD files are unchanged.
# Restore after enrollment so an offline private executor gets the same
# hosted cache as a job without a fleet identity.
- name: Restore master action cache
id: disk-cache
if: steps.fleet.outputs.enabled != 'true'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.disk-cache-config.outputs.path }}
key: ${{ steps.disk-cache-config.outputs.prefix }}run-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}
restore-keys: ${{ steps.disk-cache-config.outputs.restore-keys }}
90 changes: 90 additions & 0 deletions .github/actions/setup-bazel/configure_fleet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""Select the private executor for the invoking CI checkout when reachable."""

from __future__ import annotations

import os
import socket
from pathlib import Path


def configure_fleet(
workspace: Path,
output: Path,
connection_outcome: str,
runner_os: str,
runner_arch: str,
host: str = "ubuntu-main",
port: int = 50051,
) -> bool:
profile = {("Linux", "X64"): "rbe-linux", ("macOS", "ARM64"): "rbe-macos"}.get(
(runner_os, runner_arch)
)
enabled = False
if connection_outcome == "success" and profile:
try:
# This checks the coordinator, not the number or capacity of workers.
with socket.create_connection((host, port), timeout=5):
pass
enabled = True
except OSError as error:
print(
f"::warning::Private Bazel executor is unreachable: {error}; "
"using hosted execution."
)
elif connection_outcome == "failure":
print("::warning::Private Bazel enrollment failed; using hosted execution.")
elif connection_outcome == "success":
print(
f"::warning::No fleet profile for {runner_os}/{runner_arch}; "
"using hosted execution."
)

if enabled:
rc = f"""# Generated by CI setup; workstation configuration is unchanged.
build --config={profile}
build --remote_executor=grpc://{host}:{port}
build --remote_cache=grpc://{host}:{port}
build --remote_instance_name=main
build --remote_timeout=600
# Survive brief coordinator restarts; five retries expire in about 3s.
build --remote_retries=10
# Fleet compilation must not fall back onto the smaller hosted VM.
# Dynamic tests still have their explicitly scheduled local branch.
build --noremote_local_fallback
build --remote_download_outputs=toplevel
build --jobs=40
build --local_resources=cpu=HOST_CPUS
build --local_resources=memory=HOST_RAM*.5
build --internal_spawn_scheduler
build --dynamic_local_strategy=sandboxed
build --dynamic_remote_strategy=remote
# asupersync and other Rust crates use the fleet first. Do not race large
# compilations on the hosted VM; local_resources does not cap rustc memory.
build --strategy=Rustc=remote
# Tag `local` requires the local strategy; dynamic-only cannot spawn those tests.
build --strategy=TestRunner=dynamic,local
build --bes_backend=grpc://ubuntu-main:1985
build --bes_results_url=https://ubuntu-main.tail039078.ts.net/invocation/
build --bes_timeout=30s
build --bes_upload_mode=fully_async
"""
else:
rc = "# Private executor unavailable or not configured; use hosted execution.\n"

# This action owns the CI checkout's local rc. Clear a previous fleet
# selection on retry, before advertising that hosted execution is selected.
(workspace / ".bazelrc.local").write_text(rc)
with output.open("a") as handle:
handle.write(f"enabled={str(enabled).lower()}\n")
return enabled


if __name__ == "__main__":
configure_fleet(
Path.cwd(),
Path(os.environ["GITHUB_OUTPUT"]),
os.environ.get("TAILSCALE_OUTCOME", ""),
os.environ["RUNNER_OS"],
os.environ["RUNNER_ARCH"],
)
Loading
Loading