Balance Windows Bazel test shards using duration estimates (#49103)

## Why

Hash-based sharding does not account for differences in test duration. Use estimated test time to balance the Windows Bazel workload across shards.

## What changed

- Add checked-in duration weights and a deterministic selector that assigns the longest targets first to the least-loaded shard.
- Assign every queried target exactly once, default missing weights to one second, and ignore stale weights.
- Run queries and selection in the foreground so failures stop the job before tests run with a partial target list.
- Emit LF-delimited target labels for Git Bash and report estimated shard loads on stderr.

## Testing

Add seven passing selector tests covering deterministic coverage and balancing, missing and stale weights, invalid inputs, duration-file overrides, and CLI output. Run them on the first Windows CI shard.

GitOrigin-RevId: d415ae093bfe57794ee53a2eb9d712022202dad8
This commit is contained in:
jgershen-oai
2026-09-28 23:52:19 +00:00
committed by copyberry
parent c2d2f422e6
commit 7e049b3eaa
4 changed files with 520 additions and 22 deletions
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""Assign Windows Bazel test targets using checked-in duration estimates."""
import argparse
import sys
from pathlib import Path
DEFAULT_DURATION_SECONDS = 1
DURATIONS_PATH = Path(__file__).with_name("windows_bazel_test_durations.tsv")
def read_durations(path: Path) -> dict[str, int]:
durations = {}
for line_number, line in enumerate(
path.read_text(encoding="utf-8").splitlines(), 1
):
if not line.strip() or line.lstrip().startswith("#"):
continue
fields = line.split("\t")
if len(fields) != 2 or not fields[0] or not fields[1].isdecimal():
raise ValueError(
f"{path}:{line_number}: expected target<TAB>positive integer"
)
target, duration_text = fields
duration = int(duration_text)
if duration < 1:
raise ValueError(f"{path}:{line_number}: duration must be positive")
if target in durations:
raise ValueError(f"{path}:{line_number}: duplicate target {target}")
durations[target] = duration
return durations
def assign_targets(
targets: list[str], durations: dict[str, int], shard_count: int
) -> tuple[list[list[str]], list[int]]:
if shard_count < 1:
raise ValueError("shard count must be positive")
if not targets:
raise ValueError("no Bazel test targets were provided")
if any(not target.strip() for target in targets):
raise ValueError("Bazel test target labels must not be empty")
if len(targets) != len(set(targets)):
raise ValueError("duplicate Bazel test target labels were provided")
assignments: list[list[str]] = [[] for _ in range(shard_count)]
loads = [0] * shard_count
# Place the longest targets first, breaking ties by label and shard number.
for target in sorted(
targets,
key=lambda target: (-durations.get(target, DEFAULT_DURATION_SECONDS), target),
):
shard = min(range(shard_count), key=lambda shard: (loads[shard], shard))
assignments[shard].append(target)
loads[shard] += durations.get(target, DEFAULT_DURATION_SECONDS)
for assignment in assignments:
assignment.sort()
return assignments, loads
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--shard", required=True, type=int)
parser.add_argument("--shard-count", required=True, type=int)
parser.add_argument(
"--durations",
type=Path,
default=DURATIONS_PATH,
help="use this timing file instead of the checked-in default",
)
args = parser.parse_args()
if not 1 <= args.shard <= args.shard_count:
parser.error("shard must be between 1 and shard count")
try:
durations = read_durations(args.durations)
targets = sys.stdin.read().splitlines()
assignments, loads = assign_targets(targets, durations, args.shard_count)
except (OSError, ValueError) as error:
parser.error(str(error))
selected_targets = assignments[args.shard - 1]
if not selected_targets:
parser.error(
f"no Bazel test targets selected for shard {args.shard}/{args.shard_count}"
)
target_set = set(targets)
print(
f"Windows Bazel shards: targets={[len(assignment) for assignment in assignments]}, "
f"estimated test-seconds={loads}, default weights={len(target_set - durations.keys())}, "
f"unused weights={len(durations.keys() - target_set)}. "
f"Selected shard {args.shard}/{args.shard_count}.",
file=sys.stderr,
)
# Keep LF delimiters when native Windows Python feeds Git Bash mapfile.
sys.stdout.buffer.write(("\n".join(selected_targets) + "\n").encode("utf-8"))
if __name__ == "__main__":
main()
@@ -0,0 +1,147 @@
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
from select_windows_bazel_targets import DURATIONS_PATH
from select_windows_bazel_targets import assign_targets
from select_windows_bazel_targets import read_durations
class SelectWindowsBazelTargetsTest(unittest.TestCase):
def test_balances_targets_with_complete_deterministic_coverage(self) -> None:
durations = {
f"//test:{name}": duration
for name, duration in zip("abcdefgh", range(8, 0, -1))
}
targets = list(durations)
assignments, loads = assign_targets(targets, durations, 4)
self.assertEqual(loads, [9, 9, 9, 9])
self.assertEqual(
sorted(target for shard in assignments for target in shard), sorted(targets)
)
self.assertEqual(
assign_targets(list(reversed(targets)), durations, 4), (assignments, loads)
)
self.assertTrue(all(shard == sorted(shard) for shard in assignments))
def test_missing_weights_use_one_and_unused_weights_do_not_create_targets(
self,
) -> None:
targets = ["//test:c", "//test:a", "//test:b"]
assignments, loads = assign_targets(targets, {"//test:stale": 100}, 2)
self.assertEqual(assignments, [["//test:a", "//test:c"], ["//test:b"]])
self.assertEqual(loads, [2, 1])
def test_rejects_empty_or_duplicate_target_input(self) -> None:
for targets in ([], [""], ["//test:a", "//test:a"]):
with self.subTest(targets=targets), self.assertRaises(ValueError):
assign_targets(targets, {}, 4)
def test_reads_duration_file_and_rejects_invalid_weights(self) -> None:
with tempfile.TemporaryDirectory() as temp_dir:
path = Path(temp_dir) / "durations.tsv"
path.write_text(
"# comment\n\n//test:a\t12\n//test:b\t1\n", encoding="utf-8"
)
self.assertEqual(read_durations(path), {"//test:a": 12, "//test:b": 1})
for contents in (
"//test:a 12\n",
"//test:a\t0\n",
"//test:a\t-1\n",
"//test:a\t1.5\n",
"//test:a\t1\n//test:a\t2\n",
):
with self.subTest(contents=contents), self.assertRaises(ValueError):
path.write_text(contents, encoding="utf-8")
read_durations(path)
def test_cli_uses_checked_in_weights_and_writes_only_lf_delimited_targets(
self,
) -> None:
durations = read_durations(DURATIONS_PATH)
known = sorted(durations, key=lambda target: (-durations[target], target))[:4]
self.assertEqual(len(known), 4)
targets = [*known, "//test:new-target"]
expected, _ = assign_targets(targets, durations, 4)
script = DURATIONS_PATH.with_name("select_windows_bazel_targets.py")
for shard, assignment in enumerate(expected, 1):
command = [
sys.executable,
str(script),
"--shard",
str(shard),
"--shard-count",
"4",
]
for ordered_targets in (targets, list(reversed(targets))):
with self.subTest(shard=shard, ordered_targets=ordered_targets):
result = subprocess.run(
command,
input=("\r\n".join(ordered_targets) + "\r\n").encode(),
capture_output=True,
check=True,
)
self.assertEqual(
result.stdout, ("\n".join(assignment) + "\n").encode()
)
self.assertIn(b"default weights=1", result.stderr)
def test_cli_uses_only_the_requested_duration_file(self) -> None:
script = DURATIONS_PATH.with_name("select_windows_bazel_targets.py").resolve()
with tempfile.TemporaryDirectory() as temp_dir:
path = Path(temp_dir) / "durations.tsv"
path.write_text("//test:a\t1\n//test:b\t9\n", encoding="utf-8")
command = [sys.executable, str(script), "--shard-count", "2"]
for shard, expected in ((1, b"//test:b\n"), (2, b"//test:a\n//test:c\n")):
with self.subTest(shard=shard):
result = subprocess.run(
[*command, "--shard", str(shard), "--durations", path.name],
input=b"//test:a\n//test:b\n//test:c\n",
cwd=temp_dir,
capture_output=True,
check=True,
)
self.assertEqual(result.stdout, expected)
self.assertIn(b"estimated test-seconds=[9, 2]", result.stderr)
self.assertIn(b"unused weights=0", result.stderr)
result = subprocess.run(
[*command, "--shard", "1", "--durations", "missing.tsv"],
input=b"//test:a\n",
cwd=temp_dir,
capture_output=True,
check=False,
)
self.assertNotEqual(result.returncode, 0)
self.assertEqual(result.stdout, b"")
self.assertIn(b"missing.tsv", result.stderr)
def test_cli_rejects_bad_or_empty_selection_without_partial_output(self) -> None:
script = DURATIONS_PATH.with_name("select_windows_bazel_targets.py")
for targets, error in (
(b"", b"no Bazel test targets were provided"),
(b"//test:a\n//test:a\n", b"duplicate Bazel test target labels"),
(b"//test:a\n", b"no Bazel test targets selected for shard 2/2"),
):
with self.subTest(targets=targets):
result = subprocess.run(
[sys.executable, str(script), "--shard", "2", "--shard-count", "2"],
input=targets,
capture_output=True,
check=False,
)
self.assertNotEqual(result.returncode, 0)
self.assertEqual(result.stdout, b"")
self.assertIn(error, result.stderr)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,253 @@
# Windows Bazel duration weights; columns: target<TAB>seconds.
# Seeded from 24 successful public openai/codex Windows job logs across six main
# runs, September 21-23, 2026. Public GitHub Actions run IDs:
# 35638529858, 35665540272, 35694732932, 35912411800, 35919297566, 35924169500.
# To refresh, take the median summed inner-run time (N * average) from clean,
# uncached PASSED summaries, excluding partial cache hits and FLAKY results.
# Round up to positive integer seconds. These weights exclude build/download time.
# Every queried target is assigned; missing weights default to 1 and stale entries are ignored.
//codex-rs/agent-graph-store:agent-graph-store-unit-tests 76
//codex-rs/agent-identity:agent-identity-unit-tests 66
//codex-rs/agent-roles:agent-roles-unit-tests 48
//codex-rs/analytics:analytics-unit-tests 29
//codex-rs/app-server-client:app-server-client-unit-tests 51
//codex-rs/app-server-daemon:app-server-daemon-unit-tests 4
//codex-rs/app-server-protocol:app-server-protocol-unit-tests 19
//codex-rs/app-server-test-client:app-server-test-client-unit-tests 25
//codex-rs/app-server-test-client:codex-app-server-test-client-bin-unit-tests 1
//codex-rs/app-server-transport:app-server-transport-unit-tests 65
//codex-rs/app-server/tests/common:common-unit-tests 26
//codex-rs/app-server:app-server-all-test-windows-cross 2835
//codex-rs/app-server:app-server-unit-tests 399
//codex-rs/app-server:codex-app-server-bin-unit-tests 48
//codex-rs/app-server:codex-app-server-test-notify-capture-bin-unit-tests 1
//codex-rs/app-server:exec-server-bin-unit-tests 1
//codex-rs/app-server:test_notify_capture-bin-unit-tests 1
//codex-rs/apply-patch:apply-patch-all-test-windows-cross 50
//codex-rs/apply-patch:apply-patch-unit-tests 48
//codex-rs/apply-patch:apply_patch-bin-unit-tests 24
//codex-rs/arg0:arg0-unit-tests 24
//codex-rs/backend-client:backend-client-unit-tests 41
//codex-rs/chatgpt:chatgpt-all-test-windows-cross 26
//codex-rs/chatgpt:chatgpt-unit-tests 27
//codex-rs/cli:cli-app_server-test-windows-cross 3
//codex-rs/cli:cli-app_server_daemon-test-windows-cross 1
//codex-rs/cli:cli-cloud_auth-test-windows-cross 47
//codex-rs/cli:cli-cloud_config-test-windows-cross 3
//codex-rs/cli:cli-daemon_startup-test-windows-cross 4
//codex-rs/cli:cli-daemon_telemetry-test-windows-cross 1
//codex-rs/cli:cli-debug_clear_memories-test-windows-cross 4
//codex-rs/cli:cli-debug_models-test-windows-cross 2
//codex-rs/cli:cli-delete-test-windows-cross 2
//codex-rs/cli:cli-doctor_enterprise_network-test-windows-cross 3
//codex-rs/cli:cli-doctor_path_safety-test-windows-cross 47
//codex-rs/cli:cli-exec_server-test-windows-cross 39
//codex-rs/cli:cli-exec_server_websocket_auth-test-windows-cross 4
//codex-rs/cli:cli-execpolicy-test-windows-cross 2
//codex-rs/cli:cli-features-test-windows-cross 3
//codex-rs/cli:cli-login-test-windows-cross 4
//codex-rs/cli:cli-marketplace_add-test-windows-cross 2
//codex-rs/cli:cli-marketplace_remove-test-windows-cross 1
//codex-rs/cli:cli-marketplace_upgrade-test-windows-cross 2
//codex-rs/cli:cli-mcp_add_remove-test-windows-cross 3
//codex-rs/cli:cli-mcp_list-test-windows-cross 2
//codex-rs/cli:cli-mcp_login-test-windows-cross 2
//codex-rs/cli:cli-plugin_cli-test-windows-cross 7
//codex-rs/cli:cli-queue-test-windows-cross 1
//codex-rs/cli:cli-sandbox_cloud_config-test-windows-cross 48
//codex-rs/cli:cli-sandbox_network_proxy-test-windows-cross 1
//codex-rs/cli:cli-sandbox_tty-test-windows-cross 1
//codex-rs/cli:cli-unit-tests 2
//codex-rs/cli:cli-update-test-windows-cross 47
//codex-rs/cli:cli-worktree-test-windows-cross 12
//codex-rs/cli:codex-bin-unit-tests 60
//codex-rs/cli:logs_client-bin-unit-tests 1
//codex-rs/cloud-config:cloud-config-unit-tests 47
//codex-rs/cloud-tasks-client:cloud-tasks-client-unit-tests 35
//codex-rs/cloud-tasks-mock-client:cloud-tasks-mock-client-unit-tests 59
//codex-rs/cloud-tasks:cloud-tasks-env_filter-test-windows-cross 1
//codex-rs/cloud-tasks:cloud-tasks-unit-tests 1
//codex-rs/code-mode-host:code-mode-host-grpc-test-windows-cross 28
//codex-rs/code-mode-host:code-mode-host-grpc_notifications-test-windows-cross 25
//codex-rs/code-mode-host:code-mode-host-grpc_tcp-test-windows-cross 1
//codex-rs/code-mode-host:code-mode-host-grpc_timing-test-windows-cross 7
//codex-rs/code-mode-host:code-mode-host-stdio-test-windows-cross 11
//codex-rs/code-mode-host:code-mode-host-unit-tests 2
//codex-rs/code-mode-host:codex-code-mode-host-bin-unit-tests 1
//codex-rs/code-mode-protocol:code-mode-protocol-unit-tests 62
//codex-rs/code-mode-runtime:code-mode-runtime-array_sort-test-windows-cross 24
//codex-rs/code-mode-runtime:code-mode-runtime-jit-test-windows-cross 1
//codex-rs/code-mode-runtime:code-mode-runtime-unit-tests 7
//codex-rs/code-mode:code-mode-unit-tests 49
//codex-rs/codex-api:codex-api-clients-test-windows-cross 75
//codex-rs/codex-api:codex-api-models_integration-test-windows-cross 66
//codex-rs/codex-api:codex-api-realtime_websocket_e2e-test-windows-cross 63
//codex-rs/codex-api:codex-api-realtime_websocket_tls-test-windows-cross 66
//codex-rs/codex-api:codex-api-sse_end_to_end-test-windows-cross 48
//codex-rs/codex-api:codex-api-unit-tests 60
//codex-rs/codex-home:codex-home-unit-tests 13
//codex-rs/codex-mcp:codex-mcp-unit-tests 61
//codex-rs/config-schema:codex-write-config-schema-bin-unit-tests 48
//codex-rs/config:config-unit-tests 75
//codex-rs/connectors:connectors-unit-tests 39
//codex-rs/context-fragments:context-fragments-unit-tests 59
//codex-rs/core-api:core-api-unit-tests 1
//codex-rs/core-plugins:core-plugins-unit-tests 20
//codex-rs/core/tests/common:common-unit-tests 48
//codex-rs/core:core-all-test-windows-cross 3162
//codex-rs/core:core-mcp_trace_propagation-test-windows-cross 2
//codex-rs/core:core-responses_headers-test-windows-cross 5
//codex-rs/core:core-unit-tests 251
//codex-rs/exec-server-protocol:exec-server-protocol-unit-tests 48
//codex-rs/exec-server/tests/support:support-unit-tests 48
//codex-rs/exec-server:exec-server-accepted_websocket-test-windows-cross 1
//codex-rs/exec-server:exec-server-capability_discovery-test-windows-cross 1
//codex-rs/exec-server:exec-server-chatgpt_cloudflare_affinity-test-windows-cross 1
//codex-rs/exec-server:exec-server-deferred_environment-test-windows-cross 1
//codex-rs/exec-server:exec-server-environment-test-windows-cross 10
//codex-rs/exec-server:exec-server-environment_config-test-windows-cross 1
//codex-rs/exec-server:exec-server-exec_process-test-windows-cross 1
//codex-rs/exec-server:exec-server-file_stream-test-windows-cross 1
//codex-rs/exec-server:exec-server-file_system_unix-test-windows-cross 1
//codex-rs/exec-server:exec-server-file_system_windows-test-windows-cross 11
//codex-rs/exec-server:exec-server-forward-test-windows-cross 10
//codex-rs/exec-server:exec-server-health-test-windows-cross 1
//codex-rs/exec-server:exec-server-http_client-test-windows-cross 2
//codex-rs/exec-server:exec-server-http_request-test-windows-cross 1
//codex-rs/exec-server:exec-server-http_request_logging-test-windows-cross 3
//codex-rs/exec-server:exec-server-initialize-test-windows-cross 1
//codex-rs/exec-server:exec-server-macos_fs_spawn-test-windows-cross 1
//codex-rs/exec-server:exec-server-process-test-windows-cross 4
//codex-rs/exec-server:exec-server-relay-test-windows-cross 8
//codex-rs/exec-server:exec-server-selected_capability_roots-test-windows-cross 1
//codex-rs/exec-server:exec-server-unit-tests 116
//codex-rs/exec-server:exec-server-websocket-test-windows-cross 1
//codex-rs/exec:codex-exec-bin-unit-tests 1
//codex-rs/exec:exec-all-test-windows-cross 331
//codex-rs/exec:exec-event_processor_with_json_output-test-windows-cross 1
//codex-rs/exec:exec-unit-tests 47
//codex-rs/ext/agent-message-board:agent-message-board-local_board-test-windows-cross 46
//codex-rs/ext/agent-message-board:agent-message-board-unit-tests 30
//codex-rs/ext/agent:agent-agent_service-test-windows-cross 3
//codex-rs/ext/agent:agent-unit-tests 1
//codex-rs/ext/connectors:connectors-unit-tests 47
//codex-rs/ext/extension-api:extension-api-capabilities-test-windows-cross 14
//codex-rs/ext/extension-api:extension-api-registry-test-windows-cross 31
//codex-rs/ext/extension-api:extension-api-state-test-windows-cross 57
//codex-rs/ext/extension-api:extension-api-unit-tests 35
//codex-rs/ext/git-attribution:git-attribution-unit-tests 30
//codex-rs/ext/goal:goal-accounting-test-windows-cross 1
//codex-rs/ext/goal:goal-goal_extension_backend-test-windows-cross 9
//codex-rs/ext/goal:goal-steering-test-windows-cross 1
//codex-rs/ext/goal:goal-unit-tests 47
//codex-rs/ext/guardian-reviewer:guardian-reviewer-unit-tests 36
//codex-rs/ext/guardian-v2:guardian-v2-unit-tests 50
//codex-rs/ext/history-notes:history-notes-history_notes_extension-test-windows-cross 1
//codex-rs/ext/history-notes:history-notes-image_model_input-test-windows-cross 2
//codex-rs/ext/history-notes:history-notes-unit-tests 1
//codex-rs/ext/image-generation:image-generation-unit-tests 47
//codex-rs/ext/mcp:mcp-hosted_apps_mcp-test-windows-cross 26
//codex-rs/ext/mcp:mcp-plugin_mcp-test-windows-cross 5
//codex-rs/ext/mcp:mcp-unit-tests 48
//codex-rs/ext/memories:memories-unit-tests 28
//codex-rs/ext/queue:queue-queue_service-test-windows-cross 9
//codex-rs/ext/queue:queue-unit-tests 25
//codex-rs/ext/skills:skills-executor_file_system_authority-test-windows-cross 36
//codex-rs/ext/skills:skills-skills_extension-test-windows-cross 7
//codex-rs/ext/skills:skills-unit-tests 8
//codex-rs/ext/web-search:web-search-unit-tests 1
//codex-rs/external-agent-migration:external-agent-migration-unit-tests 4
//codex-rs/features:features-unit-tests 47
//codex-rs/feedback:feedback-unit-tests 77
//codex-rs/file-system:file-system-unit-tests 48
//codex-rs/git-utils:git-utils-unit-tests 83
//codex-rs/guardian-context:guardian-context-cache_prefix-test-windows-cross 66
//codex-rs/guardian-context:guardian-context-unit-tests 67
//codex-rs/history:history-unit-tests 59
//codex-rs/hooks:hooks-unit-tests 16
//codex-rs/hooks:write_hooks_schema_fixtures-bin-unit-tests 48
//codex-rs/lmstudio:lmstudio-unit-tests 1
//codex-rs/login:login-all-test-windows-cross 5
//codex-rs/login:login-unit-tests 320
//codex-rs/memories/read:read-unit-tests 62
//codex-rs/memories/write:write-unit-tests 20
//codex-rs/message-history:message-history-unit-tests 74
//codex-rs/model-provider-info:model-provider-info-unit-tests 63
//codex-rs/model-provider:model-provider-unit-tests 64
//codex-rs/models-manager:models-manager-unit-tests 35
//codex-rs/mxc-sandbox:mxc-sandbox-unit-tests 36
//codex-rs/network-proxy:codex-network-proxy-bin-unit-tests 48
//codex-rs/network-proxy:network-proxy-unit-tests 85
//codex-rs/network-proxy:network-proxy-windows_stable_ingress-test-windows-cross 37
//codex-rs/ollama:ollama-unit-tests 1
//codex-rs/otel:otel-tests-test-windows-cross 17
//codex-rs/otel:otel-unit-tests 48
//codex-rs/plugin:plugin-unit-tests 74
//codex-rs/prompts:prompts-unit-tests 62
//codex-rs/protocol:protocol-unit-tests 67
//codex-rs/response-debug-context:response-debug-context-unit-tests 66
//codex-rs/rmcp-client:rmcp-client-foreign_stdio_cwd-test-windows-cross 48
//codex-rs/rmcp-client:rmcp-client-mcp_2026_discovery-test-windows-cross 4
//codex-rs/rmcp-client:rmcp-client-mcp_2026_message_limits-test-windows-cross 4
//codex-rs/rmcp-client:rmcp-client-mcp_2026_mrtr-test-windows-cross 2
//codex-rs/rmcp-client:rmcp-client-mcp_2026_oauth_discovery-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-mcp_2026_sse_discovery-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-mcp_2026_stdio-test-windows-cross 39
//codex-rs/rmcp-client:rmcp-client-mcp_2026_stdio_discovery-test-windows-cross 2
//codex-rs/rmcp-client:rmcp-client-mcp_events-test-windows-cross 2
//codex-rs/rmcp-client:rmcp-client-process_group_cleanup-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-resources-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-stdio_descriptor_boundary-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-stdio_message_limits-test-windows-cross 3
//codex-rs/rmcp-client:rmcp-client-stdio_stderr_cleanup-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-streamable_http_oauth_startup-test-windows-cross 6
//codex-rs/rmcp-client:rmcp-client-streamable_http_oauth_store_pinning-test-windows-cross 38
//codex-rs/rmcp-client:rmcp-client-streamable_http_oauth_tool_call-test-windows-cross 2
//codex-rs/rmcp-client:rmcp-client-streamable_http_recovery-test-windows-cross 51
//codex-rs/rmcp-client:rmcp-client-streamable_http_remote-test-windows-cross 3
//codex-rs/rmcp-client:rmcp-client-streamable_http_test_support-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-streamable_http_user_agent-test-windows-cross 1
//codex-rs/rmcp-client:rmcp-client-unit-tests 50
//codex-rs/rmcp-client:rmcp_test_server-bin-unit-tests 39
//codex-rs/rmcp-client:test_mcp_2026_discovery_stdio_server-bin-unit-tests 43
//codex-rs/rmcp-client:test_mcp_2026_stdio_server-bin-unit-tests 25
//codex-rs/rmcp-client:test_stdio_server-bin-unit-tests 41
//codex-rs/rmcp-client:test_streamable_http_server-bin-unit-tests 40
//codex-rs/rollout-trace:rollout-trace-unit-tests 76
//codex-rs/rollout:rollout-unit-tests 56
//codex-rs/sandboxing:sandboxing-unit-tests 74
//codex-rs/secrets:secrets-unit-tests 57
//codex-rs/shell-command:shell-command-unit-tests 60
//codex-rs/shell-escalation:codex-execve-wrapper-bin-unit-tests 62
//codex-rs/shell-escalation:shell-escalation-unit-tests 60
//codex-rs/skills:skills-unit-tests 59
//codex-rs/state:state-unit-tests 242
//codex-rs/test-binary-support:test-binary-support-unit-tests 48
//codex-rs/thread-manager-sample:codex-thread-manager-sample-bin-unit-tests 47
//codex-rs/thread-store:thread-store-unit-tests 95
//codex-rs/tools:tools-json_schema_policy_fixtures-test-windows-cross 34
//codex-rs/tools:tools-unit-tests 37
//codex-rs/tui:codex-tui-bin-unit-tests 2
//codex-rs/tui:md-events-bin-unit-tests 1
//codex-rs/tui:tui-all-test-windows-cross 36
//codex-rs/tui:tui-manager_dependency_regression-test-windows-cross 2
//codex-rs/tui:tui-test_backend-test-windows-cross 25
//codex-rs/tui:tui-unit-tests 1003
//codex-rs/utils/approval-presets:approval-presets-unit-tests 66
//codex-rs/utils/audio:audio-unit-tests 76
//codex-rs/utils/cli:cli-unit-tests 64
//codex-rs/utils/git-discovery:git-discovery-unit-tests 59
//codex-rs/utils/oss:oss-unit-tests 1
//codex-rs/utils/output-truncation:output-truncation-unit-tests 60
//codex-rs/utils/plugins:plugins-unit-tests 36
//codex-rs/utils/sandbox-summary:sandbox-summary-unit-tests 66
//codex-rs/windows-sandbox-rs:codex-command-runner-bin-unit-tests 1
//codex-rs/windows-sandbox-rs:codex-windows-managed-deny-probe-bin-unit-tests 1
//codex-rs/windows-sandbox-rs:codex-windows-sandbox-setup-bin-unit-tests 1
//codex-rs/windows-sandbox-rs:windows-sandbox-rs-helper_manifest-test-windows-cross 1
//codex-rs/windows-sandbox-rs:windows-sandbox-rs-unit-tests 23
//codex-rs/windows-sandbox-service:codex-windows-sandbox-service-bin-unit-tests 46
//codex-rs/windows-sandbox-service:windows-sandbox-service-unit-tests 12
//codex-rs/worktree:worktree-settings-test-windows-cross 59
//codex-rs/worktree:worktree-unit-tests 76
//codex-rs/worktree:worktree-worktree-test-windows-cross 92
1 # Windows Bazel duration weights; columns: target<TAB>seconds.
2 # Seeded from 24 successful public openai/codex Windows job logs across six main
3 # runs, September 21-23, 2026. Public GitHub Actions run IDs:
4 # 35638529858, 35665540272, 35694732932, 35912411800, 35919297566, 35924169500.
5 # To refresh, take the median summed inner-run time (N * average) from clean,
6 # uncached PASSED summaries, excluding partial cache hits and FLAKY results.
7 # Round up to positive integer seconds. These weights exclude build/download time.
8 # Every queried target is assigned; missing weights default to 1 and stale entries are ignored.
9 //codex-rs/agent-graph-store:agent-graph-store-unit-tests 76
10 //codex-rs/agent-identity:agent-identity-unit-tests 66
11 //codex-rs/agent-roles:agent-roles-unit-tests 48
12 //codex-rs/analytics:analytics-unit-tests 29
13 //codex-rs/app-server-client:app-server-client-unit-tests 51
14 //codex-rs/app-server-daemon:app-server-daemon-unit-tests 4
15 //codex-rs/app-server-protocol:app-server-protocol-unit-tests 19
16 //codex-rs/app-server-test-client:app-server-test-client-unit-tests 25
17 //codex-rs/app-server-test-client:codex-app-server-test-client-bin-unit-tests 1
18 //codex-rs/app-server-transport:app-server-transport-unit-tests 65
19 //codex-rs/app-server/tests/common:common-unit-tests 26
20 //codex-rs/app-server:app-server-all-test-windows-cross 2835
21 //codex-rs/app-server:app-server-unit-tests 399
22 //codex-rs/app-server:codex-app-server-bin-unit-tests 48
23 //codex-rs/app-server:codex-app-server-test-notify-capture-bin-unit-tests 1
24 //codex-rs/app-server:exec-server-bin-unit-tests 1
25 //codex-rs/app-server:test_notify_capture-bin-unit-tests 1
26 //codex-rs/apply-patch:apply-patch-all-test-windows-cross 50
27 //codex-rs/apply-patch:apply-patch-unit-tests 48
28 //codex-rs/apply-patch:apply_patch-bin-unit-tests 24
29 //codex-rs/arg0:arg0-unit-tests 24
30 //codex-rs/backend-client:backend-client-unit-tests 41
31 //codex-rs/chatgpt:chatgpt-all-test-windows-cross 26
32 //codex-rs/chatgpt:chatgpt-unit-tests 27
33 //codex-rs/cli:cli-app_server-test-windows-cross 3
34 //codex-rs/cli:cli-app_server_daemon-test-windows-cross 1
35 //codex-rs/cli:cli-cloud_auth-test-windows-cross 47
36 //codex-rs/cli:cli-cloud_config-test-windows-cross 3
37 //codex-rs/cli:cli-daemon_startup-test-windows-cross 4
38 //codex-rs/cli:cli-daemon_telemetry-test-windows-cross 1
39 //codex-rs/cli:cli-debug_clear_memories-test-windows-cross 4
40 //codex-rs/cli:cli-debug_models-test-windows-cross 2
41 //codex-rs/cli:cli-delete-test-windows-cross 2
42 //codex-rs/cli:cli-doctor_enterprise_network-test-windows-cross 3
43 //codex-rs/cli:cli-doctor_path_safety-test-windows-cross 47
44 //codex-rs/cli:cli-exec_server-test-windows-cross 39
45 //codex-rs/cli:cli-exec_server_websocket_auth-test-windows-cross 4
46 //codex-rs/cli:cli-execpolicy-test-windows-cross 2
47 //codex-rs/cli:cli-features-test-windows-cross 3
48 //codex-rs/cli:cli-login-test-windows-cross 4
49 //codex-rs/cli:cli-marketplace_add-test-windows-cross 2
50 //codex-rs/cli:cli-marketplace_remove-test-windows-cross 1
51 //codex-rs/cli:cli-marketplace_upgrade-test-windows-cross 2
52 //codex-rs/cli:cli-mcp_add_remove-test-windows-cross 3
53 //codex-rs/cli:cli-mcp_list-test-windows-cross 2
54 //codex-rs/cli:cli-mcp_login-test-windows-cross 2
55 //codex-rs/cli:cli-plugin_cli-test-windows-cross 7
56 //codex-rs/cli:cli-queue-test-windows-cross 1
57 //codex-rs/cli:cli-sandbox_cloud_config-test-windows-cross 48
58 //codex-rs/cli:cli-sandbox_network_proxy-test-windows-cross 1
59 //codex-rs/cli:cli-sandbox_tty-test-windows-cross 1
60 //codex-rs/cli:cli-unit-tests 2
61 //codex-rs/cli:cli-update-test-windows-cross 47
62 //codex-rs/cli:cli-worktree-test-windows-cross 12
63 //codex-rs/cli:codex-bin-unit-tests 60
64 //codex-rs/cli:logs_client-bin-unit-tests 1
65 //codex-rs/cloud-config:cloud-config-unit-tests 47
66 //codex-rs/cloud-tasks-client:cloud-tasks-client-unit-tests 35
67 //codex-rs/cloud-tasks-mock-client:cloud-tasks-mock-client-unit-tests 59
68 //codex-rs/cloud-tasks:cloud-tasks-env_filter-test-windows-cross 1
69 //codex-rs/cloud-tasks:cloud-tasks-unit-tests 1
70 //codex-rs/code-mode-host:code-mode-host-grpc-test-windows-cross 28
71 //codex-rs/code-mode-host:code-mode-host-grpc_notifications-test-windows-cross 25
72 //codex-rs/code-mode-host:code-mode-host-grpc_tcp-test-windows-cross 1
73 //codex-rs/code-mode-host:code-mode-host-grpc_timing-test-windows-cross 7
74 //codex-rs/code-mode-host:code-mode-host-stdio-test-windows-cross 11
75 //codex-rs/code-mode-host:code-mode-host-unit-tests 2
76 //codex-rs/code-mode-host:codex-code-mode-host-bin-unit-tests 1
77 //codex-rs/code-mode-protocol:code-mode-protocol-unit-tests 62
78 //codex-rs/code-mode-runtime:code-mode-runtime-array_sort-test-windows-cross 24
79 //codex-rs/code-mode-runtime:code-mode-runtime-jit-test-windows-cross 1
80 //codex-rs/code-mode-runtime:code-mode-runtime-unit-tests 7
81 //codex-rs/code-mode:code-mode-unit-tests 49
82 //codex-rs/codex-api:codex-api-clients-test-windows-cross 75
83 //codex-rs/codex-api:codex-api-models_integration-test-windows-cross 66
84 //codex-rs/codex-api:codex-api-realtime_websocket_e2e-test-windows-cross 63
85 //codex-rs/codex-api:codex-api-realtime_websocket_tls-test-windows-cross 66
86 //codex-rs/codex-api:codex-api-sse_end_to_end-test-windows-cross 48
87 //codex-rs/codex-api:codex-api-unit-tests 60
88 //codex-rs/codex-home:codex-home-unit-tests 13
89 //codex-rs/codex-mcp:codex-mcp-unit-tests 61
90 //codex-rs/config-schema:codex-write-config-schema-bin-unit-tests 48
91 //codex-rs/config:config-unit-tests 75
92 //codex-rs/connectors:connectors-unit-tests 39
93 //codex-rs/context-fragments:context-fragments-unit-tests 59
94 //codex-rs/core-api:core-api-unit-tests 1
95 //codex-rs/core-plugins:core-plugins-unit-tests 20
96 //codex-rs/core/tests/common:common-unit-tests 48
97 //codex-rs/core:core-all-test-windows-cross 3162
98 //codex-rs/core:core-mcp_trace_propagation-test-windows-cross 2
99 //codex-rs/core:core-responses_headers-test-windows-cross 5
100 //codex-rs/core:core-unit-tests 251
101 //codex-rs/exec-server-protocol:exec-server-protocol-unit-tests 48
102 //codex-rs/exec-server/tests/support:support-unit-tests 48
103 //codex-rs/exec-server:exec-server-accepted_websocket-test-windows-cross 1
104 //codex-rs/exec-server:exec-server-capability_discovery-test-windows-cross 1
105 //codex-rs/exec-server:exec-server-chatgpt_cloudflare_affinity-test-windows-cross 1
106 //codex-rs/exec-server:exec-server-deferred_environment-test-windows-cross 1
107 //codex-rs/exec-server:exec-server-environment-test-windows-cross 10
108 //codex-rs/exec-server:exec-server-environment_config-test-windows-cross 1
109 //codex-rs/exec-server:exec-server-exec_process-test-windows-cross 1
110 //codex-rs/exec-server:exec-server-file_stream-test-windows-cross 1
111 //codex-rs/exec-server:exec-server-file_system_unix-test-windows-cross 1
112 //codex-rs/exec-server:exec-server-file_system_windows-test-windows-cross 11
113 //codex-rs/exec-server:exec-server-forward-test-windows-cross 10
114 //codex-rs/exec-server:exec-server-health-test-windows-cross 1
115 //codex-rs/exec-server:exec-server-http_client-test-windows-cross 2
116 //codex-rs/exec-server:exec-server-http_request-test-windows-cross 1
117 //codex-rs/exec-server:exec-server-http_request_logging-test-windows-cross 3
118 //codex-rs/exec-server:exec-server-initialize-test-windows-cross 1
119 //codex-rs/exec-server:exec-server-macos_fs_spawn-test-windows-cross 1
120 //codex-rs/exec-server:exec-server-process-test-windows-cross 4
121 //codex-rs/exec-server:exec-server-relay-test-windows-cross 8
122 //codex-rs/exec-server:exec-server-selected_capability_roots-test-windows-cross 1
123 //codex-rs/exec-server:exec-server-unit-tests 116
124 //codex-rs/exec-server:exec-server-websocket-test-windows-cross 1
125 //codex-rs/exec:codex-exec-bin-unit-tests 1
126 //codex-rs/exec:exec-all-test-windows-cross 331
127 //codex-rs/exec:exec-event_processor_with_json_output-test-windows-cross 1
128 //codex-rs/exec:exec-unit-tests 47
129 //codex-rs/ext/agent-message-board:agent-message-board-local_board-test-windows-cross 46
130 //codex-rs/ext/agent-message-board:agent-message-board-unit-tests 30
131 //codex-rs/ext/agent:agent-agent_service-test-windows-cross 3
132 //codex-rs/ext/agent:agent-unit-tests 1
133 //codex-rs/ext/connectors:connectors-unit-tests 47
134 //codex-rs/ext/extension-api:extension-api-capabilities-test-windows-cross 14
135 //codex-rs/ext/extension-api:extension-api-registry-test-windows-cross 31
136 //codex-rs/ext/extension-api:extension-api-state-test-windows-cross 57
137 //codex-rs/ext/extension-api:extension-api-unit-tests 35
138 //codex-rs/ext/git-attribution:git-attribution-unit-tests 30
139 //codex-rs/ext/goal:goal-accounting-test-windows-cross 1
140 //codex-rs/ext/goal:goal-goal_extension_backend-test-windows-cross 9
141 //codex-rs/ext/goal:goal-steering-test-windows-cross 1
142 //codex-rs/ext/goal:goal-unit-tests 47
143 //codex-rs/ext/guardian-reviewer:guardian-reviewer-unit-tests 36
144 //codex-rs/ext/guardian-v2:guardian-v2-unit-tests 50
145 //codex-rs/ext/history-notes:history-notes-history_notes_extension-test-windows-cross 1
146 //codex-rs/ext/history-notes:history-notes-image_model_input-test-windows-cross 2
147 //codex-rs/ext/history-notes:history-notes-unit-tests 1
148 //codex-rs/ext/image-generation:image-generation-unit-tests 47
149 //codex-rs/ext/mcp:mcp-hosted_apps_mcp-test-windows-cross 26
150 //codex-rs/ext/mcp:mcp-plugin_mcp-test-windows-cross 5
151 //codex-rs/ext/mcp:mcp-unit-tests 48
152 //codex-rs/ext/memories:memories-unit-tests 28
153 //codex-rs/ext/queue:queue-queue_service-test-windows-cross 9
154 //codex-rs/ext/queue:queue-unit-tests 25
155 //codex-rs/ext/skills:skills-executor_file_system_authority-test-windows-cross 36
156 //codex-rs/ext/skills:skills-skills_extension-test-windows-cross 7
157 //codex-rs/ext/skills:skills-unit-tests 8
158 //codex-rs/ext/web-search:web-search-unit-tests 1
159 //codex-rs/external-agent-migration:external-agent-migration-unit-tests 4
160 //codex-rs/features:features-unit-tests 47
161 //codex-rs/feedback:feedback-unit-tests 77
162 //codex-rs/file-system:file-system-unit-tests 48
163 //codex-rs/git-utils:git-utils-unit-tests 83
164 //codex-rs/guardian-context:guardian-context-cache_prefix-test-windows-cross 66
165 //codex-rs/guardian-context:guardian-context-unit-tests 67
166 //codex-rs/history:history-unit-tests 59
167 //codex-rs/hooks:hooks-unit-tests 16
168 //codex-rs/hooks:write_hooks_schema_fixtures-bin-unit-tests 48
169 //codex-rs/lmstudio:lmstudio-unit-tests 1
170 //codex-rs/login:login-all-test-windows-cross 5
171 //codex-rs/login:login-unit-tests 320
172 //codex-rs/memories/read:read-unit-tests 62
173 //codex-rs/memories/write:write-unit-tests 20
174 //codex-rs/message-history:message-history-unit-tests 74
175 //codex-rs/model-provider-info:model-provider-info-unit-tests 63
176 //codex-rs/model-provider:model-provider-unit-tests 64
177 //codex-rs/models-manager:models-manager-unit-tests 35
178 //codex-rs/mxc-sandbox:mxc-sandbox-unit-tests 36
179 //codex-rs/network-proxy:codex-network-proxy-bin-unit-tests 48
180 //codex-rs/network-proxy:network-proxy-unit-tests 85
181 //codex-rs/network-proxy:network-proxy-windows_stable_ingress-test-windows-cross 37
182 //codex-rs/ollama:ollama-unit-tests 1
183 //codex-rs/otel:otel-tests-test-windows-cross 17
184 //codex-rs/otel:otel-unit-tests 48
185 //codex-rs/plugin:plugin-unit-tests 74
186 //codex-rs/prompts:prompts-unit-tests 62
187 //codex-rs/protocol:protocol-unit-tests 67
188 //codex-rs/response-debug-context:response-debug-context-unit-tests 66
189 //codex-rs/rmcp-client:rmcp-client-foreign_stdio_cwd-test-windows-cross 48
190 //codex-rs/rmcp-client:rmcp-client-mcp_2026_discovery-test-windows-cross 4
191 //codex-rs/rmcp-client:rmcp-client-mcp_2026_message_limits-test-windows-cross 4
192 //codex-rs/rmcp-client:rmcp-client-mcp_2026_mrtr-test-windows-cross 2
193 //codex-rs/rmcp-client:rmcp-client-mcp_2026_oauth_discovery-test-windows-cross 1
194 //codex-rs/rmcp-client:rmcp-client-mcp_2026_sse_discovery-test-windows-cross 1
195 //codex-rs/rmcp-client:rmcp-client-mcp_2026_stdio-test-windows-cross 39
196 //codex-rs/rmcp-client:rmcp-client-mcp_2026_stdio_discovery-test-windows-cross 2
197 //codex-rs/rmcp-client:rmcp-client-mcp_events-test-windows-cross 2
198 //codex-rs/rmcp-client:rmcp-client-process_group_cleanup-test-windows-cross 1
199 //codex-rs/rmcp-client:rmcp-client-resources-test-windows-cross 1
200 //codex-rs/rmcp-client:rmcp-client-stdio_descriptor_boundary-test-windows-cross 1
201 //codex-rs/rmcp-client:rmcp-client-stdio_message_limits-test-windows-cross 3
202 //codex-rs/rmcp-client:rmcp-client-stdio_stderr_cleanup-test-windows-cross 1
203 //codex-rs/rmcp-client:rmcp-client-streamable_http_oauth_startup-test-windows-cross 6
204 //codex-rs/rmcp-client:rmcp-client-streamable_http_oauth_store_pinning-test-windows-cross 38
205 //codex-rs/rmcp-client:rmcp-client-streamable_http_oauth_tool_call-test-windows-cross 2
206 //codex-rs/rmcp-client:rmcp-client-streamable_http_recovery-test-windows-cross 51
207 //codex-rs/rmcp-client:rmcp-client-streamable_http_remote-test-windows-cross 3
208 //codex-rs/rmcp-client:rmcp-client-streamable_http_test_support-test-windows-cross 1
209 //codex-rs/rmcp-client:rmcp-client-streamable_http_user_agent-test-windows-cross 1
210 //codex-rs/rmcp-client:rmcp-client-unit-tests 50
211 //codex-rs/rmcp-client:rmcp_test_server-bin-unit-tests 39
212 //codex-rs/rmcp-client:test_mcp_2026_discovery_stdio_server-bin-unit-tests 43
213 //codex-rs/rmcp-client:test_mcp_2026_stdio_server-bin-unit-tests 25
214 //codex-rs/rmcp-client:test_stdio_server-bin-unit-tests 41
215 //codex-rs/rmcp-client:test_streamable_http_server-bin-unit-tests 40
216 //codex-rs/rollout-trace:rollout-trace-unit-tests 76
217 //codex-rs/rollout:rollout-unit-tests 56
218 //codex-rs/sandboxing:sandboxing-unit-tests 74
219 //codex-rs/secrets:secrets-unit-tests 57
220 //codex-rs/shell-command:shell-command-unit-tests 60
221 //codex-rs/shell-escalation:codex-execve-wrapper-bin-unit-tests 62
222 //codex-rs/shell-escalation:shell-escalation-unit-tests 60
223 //codex-rs/skills:skills-unit-tests 59
224 //codex-rs/state:state-unit-tests 242
225 //codex-rs/test-binary-support:test-binary-support-unit-tests 48
226 //codex-rs/thread-manager-sample:codex-thread-manager-sample-bin-unit-tests 47
227 //codex-rs/thread-store:thread-store-unit-tests 95
228 //codex-rs/tools:tools-json_schema_policy_fixtures-test-windows-cross 34
229 //codex-rs/tools:tools-unit-tests 37
230 //codex-rs/tui:codex-tui-bin-unit-tests 2
231 //codex-rs/tui:md-events-bin-unit-tests 1
232 //codex-rs/tui:tui-all-test-windows-cross 36
233 //codex-rs/tui:tui-manager_dependency_regression-test-windows-cross 2
234 //codex-rs/tui:tui-test_backend-test-windows-cross 25
235 //codex-rs/tui:tui-unit-tests 1003
236 //codex-rs/utils/approval-presets:approval-presets-unit-tests 66
237 //codex-rs/utils/audio:audio-unit-tests 76
238 //codex-rs/utils/cli:cli-unit-tests 64
239 //codex-rs/utils/git-discovery:git-discovery-unit-tests 59
240 //codex-rs/utils/oss:oss-unit-tests 1
241 //codex-rs/utils/output-truncation:output-truncation-unit-tests 60
242 //codex-rs/utils/plugins:plugins-unit-tests 36
243 //codex-rs/utils/sandbox-summary:sandbox-summary-unit-tests 66
244 //codex-rs/windows-sandbox-rs:codex-command-runner-bin-unit-tests 1
245 //codex-rs/windows-sandbox-rs:codex-windows-managed-deny-probe-bin-unit-tests 1
246 //codex-rs/windows-sandbox-rs:codex-windows-sandbox-setup-bin-unit-tests 1
247 //codex-rs/windows-sandbox-rs:windows-sandbox-rs-helper_manifest-test-windows-cross 1
248 //codex-rs/windows-sandbox-rs:windows-sandbox-rs-unit-tests 23
249 //codex-rs/windows-sandbox-service:codex-windows-sandbox-service-bin-unit-tests 46
250 //codex-rs/windows-sandbox-service:windows-sandbox-service-unit-tests 12
251 //codex-rs/worktree:worktree-settings-test-windows-cross 59
252 //codex-rs/worktree:worktree-unit-tests 76
253 //codex-rs/worktree:worktree-worktree-test-windows-cross 92
+17 -22
View File
@@ -160,6 +160,11 @@ jobs:
shell: pwsh
run: python .github/scripts/test_run_bazel_with_buildbuddy.py
- name: Test Windows Bazel target selector
if: matrix.shard == 1
shell: pwsh
run: python -m unittest discover -s .github/scripts -p test_select_windows_bazel_targets.py
- name: Prepare Bazel CI
id: prepare_bazel
uses: ./.github/actions/prepare-bazel-ci
@@ -180,29 +185,19 @@ jobs:
set -euo pipefail
bazel_test_query='tests(//...) except tests(//third_party/v8:all) except attr(tags, "manual", tests(//...))'
mapfile -t bazel_targets < <(
./.github/scripts/run-bazel-query-ci.sh --output=label -- "${bazel_test_query}" \
| LC_ALL=C sort
)
bazel_targets_file="$(mktemp)"
selected_targets_file="$(mktemp)"
trap 'rm -f "${bazel_targets_file}" "${selected_targets_file}"' EXIT
selected_targets=()
for bazel_target in "${bazel_targets[@]}"; do
target_bucket="$(
printf '%s\n' "${bazel_target}" \
| cksum \
| awk -v shard_count="${BAZEL_TEST_SHARD_COUNT}" '{ print ($1 % shard_count) + 1 }'
)"
if [[ "${target_bucket}" == "${BAZEL_TEST_SHARD}" ]]; then
selected_targets+=("${bazel_target}")
fi
done
if [[ ${#selected_targets[@]} -eq 0 ]]; then
echo "No Bazel test targets selected for Windows shard ${BAZEL_TEST_SHARD}/${BAZEL_TEST_SHARD_COUNT}." >&2
exit 1
fi
echo "Selected ${#selected_targets[@]} of ${#bazel_targets[@]} Bazel test targets for Windows shard ${BAZEL_TEST_SHARD}/${BAZEL_TEST_SHARD_COUNT}."
# Keep query and selection in the foreground so failures cannot leave
# different jobs assigning different partial target lists.
./.github/scripts/run-bazel-query-ci.sh --output=label -- "${bazel_test_query}" \
| LC_ALL=C sort > "${bazel_targets_file}"
python .github/scripts/select_windows_bazel_targets.py \
--shard "${BAZEL_TEST_SHARD}" \
--shard-count "${BAZEL_TEST_SHARD_COUNT}" \
< "${bazel_targets_file}" > "${selected_targets_file}"
mapfile -t selected_targets < "${selected_targets_file}"
bazel_test_args=(
test