mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
Keep cross Bazel builds test-free
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
RELEASE_SCRIPT = REPO_ROOT / "scripts" / "list-bazel-release-targets.sh"
|
||||
CLIPPY_SCRIPT = REPO_ROOT / "scripts" / "list-bazel-clippy-targets.sh"
|
||||
|
||||
|
||||
class BazelTargetListsTest(unittest.TestCase):
|
||||
def run_selector(
|
||||
self,
|
||||
script: Path,
|
||||
*args: str,
|
||||
production_targets: tuple[str, ...] = (
|
||||
"//codex-rs/cli:codex",
|
||||
"//codex-rs/core:core",
|
||||
),
|
||||
test_targets: tuple[str, ...] = (
|
||||
"//codex-rs/core:core-unit-tests-bin",
|
||||
"//codex-rs/core:core-all-test-bin",
|
||||
"//codex-rs/core:core-all-test-windows-cross-bin",
|
||||
),
|
||||
fail_query_containing: str = "",
|
||||
) -> tuple[subprocess.CompletedProcess[str], list[list[str]]]:
|
||||
with TemporaryDirectory() as temp_dir:
|
||||
temp_path = Path(temp_dir)
|
||||
query_log = temp_path / "queries.jsonl"
|
||||
fake_query = temp_path / "fake-bazel-query.py"
|
||||
fake_query.write_text(
|
||||
"""#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
with Path(os.environ["QUERY_LOG"]).open("a", encoding="utf-8") as query_log:
|
||||
query_log.write(json.dumps(sys.argv[1:]) + "\\n")
|
||||
|
||||
query = sys.argv[-1]
|
||||
if os.environ["FAIL_QUERY_CONTAINING"] and os.environ["FAIL_QUERY_CONTAINING"] in query:
|
||||
raise SystemExit("injected query failure")
|
||||
if "rust_(binary|library|proc_macro) rule" in query:
|
||||
print(os.environ["PRODUCTION_TARGETS"])
|
||||
elif "rust_test rule" in query:
|
||||
print(os.environ["TEST_TARGETS"])
|
||||
else:
|
||||
raise SystemExit(f"unexpected query: {query}")
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
fake_query.chmod(0o755)
|
||||
|
||||
env = os.environ.copy()
|
||||
env.update(
|
||||
{
|
||||
"CODEX_BAZEL_QUERY_SCRIPT": str(fake_query),
|
||||
"FAIL_QUERY_CONTAINING": fail_query_containing,
|
||||
"PRODUCTION_TARGETS": "\n".join(production_targets),
|
||||
"QUERY_LOG": str(query_log),
|
||||
"TEST_TARGETS": "\n".join(test_targets),
|
||||
}
|
||||
)
|
||||
result = subprocess.run(
|
||||
["bash", str(script), *args],
|
||||
cwd=REPO_ROOT,
|
||||
env=env,
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
queries = [
|
||||
json.loads(line)
|
||||
for line in query_log.read_text(encoding="utf-8").splitlines()
|
||||
]
|
||||
return result, queries
|
||||
|
||||
def test_release_targets_are_sorted_explicit_production_rules(self) -> None:
|
||||
result, queries = self.run_selector(
|
||||
RELEASE_SCRIPT,
|
||||
production_targets=(
|
||||
"//codex-rs/core:core",
|
||||
"//codex-rs/cli:codex",
|
||||
),
|
||||
)
|
||||
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(
|
||||
result.stdout.splitlines(),
|
||||
["//codex-rs/cli:codex", "//codex-rs/core:core"],
|
||||
)
|
||||
self.assertEqual(len(queries), 1)
|
||||
self.assertIn("rust_(binary|library|proc_macro) rule", queries[0][-1])
|
||||
self.assertIn("//visibility:public", queries[0][-1])
|
||||
self.assertNotIn("rust_test rule", queries[0][-1])
|
||||
|
||||
def test_release_targets_fail_when_discovery_is_empty(self) -> None:
|
||||
result, _ = self.run_selector(RELEASE_SCRIPT, production_targets=())
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("No Bazel release-build targets found.", result.stderr)
|
||||
|
||||
def test_native_clippy_adds_manual_native_test_binaries(self) -> None:
|
||||
result, queries = self.run_selector(CLIPPY_SCRIPT)
|
||||
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(
|
||||
result.stdout.splitlines(),
|
||||
[
|
||||
"//codex-rs/cli:codex",
|
||||
"//codex-rs/core:core",
|
||||
"//codex-rs/core:core-all-test-bin",
|
||||
"//codex-rs/core:core-unit-tests-bin",
|
||||
],
|
||||
)
|
||||
self.assertEqual(len(queries), 2)
|
||||
self.assertIn("rust_test rule", queries[1][-1])
|
||||
|
||||
def test_cross_clippy_never_queries_or_returns_test_rules(self) -> None:
|
||||
result, queries = self.run_selector(
|
||||
CLIPPY_SCRIPT,
|
||||
"--windows-cross-compile",
|
||||
)
|
||||
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(
|
||||
result.stdout.splitlines(),
|
||||
["//codex-rs/cli:codex", "//codex-rs/core:core"],
|
||||
)
|
||||
self.assertEqual(len(queries), 1)
|
||||
self.assertNotIn("rust_test rule", queries[0][-1])
|
||||
|
||||
def test_native_clippy_prints_nothing_when_test_discovery_fails(self) -> None:
|
||||
result, queries = self.run_selector(
|
||||
CLIPPY_SCRIPT,
|
||||
fail_query_containing="rust_test rule",
|
||||
)
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertEqual(result.stdout, "")
|
||||
self.assertEqual(len(queries), 2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -84,6 +84,48 @@ jobs:
|
||||
shell: bash
|
||||
run: ./scripts/check-module-bazel-lock.sh
|
||||
|
||||
- name: Check build-only Bazel target selectors exclude tests
|
||||
if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
check_build_only_selector() {
|
||||
local selector_name="$1"
|
||||
shift
|
||||
|
||||
local target_lines
|
||||
target_lines="$("$@")"
|
||||
if [[ -z "${target_lines}" ]]; then
|
||||
echo "${selector_name} returned no targets." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local targets=()
|
||||
while IFS= read -r target; do
|
||||
targets+=("${target}")
|
||||
done <<< "${target_lines}"
|
||||
|
||||
local selected_tests
|
||||
selected_tests="$(
|
||||
./.github/scripts/run-bazel-query-ci.sh \
|
||||
--output=label \
|
||||
-- "tests(set(${targets[*]}))"
|
||||
)"
|
||||
if [[ -n "${selected_tests}" ]]; then
|
||||
echo "${selector_name} included Bazel test rules:" >&2
|
||||
printf '%s\n' "${selected_tests}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_build_only_selector \
|
||||
verify-release-build \
|
||||
bash ./scripts/list-bazel-release-targets.sh
|
||||
check_build_only_selector \
|
||||
windows-cross-clippy \
|
||||
./scripts/list-bazel-clippy-targets.sh --windows-cross-compile
|
||||
|
||||
- name: bazel test //...
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
|
||||
@@ -5,6 +5,8 @@ set -euo pipefail
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
|
||||
query_script="${CODEX_BAZEL_QUERY_SCRIPT:-./.github/scripts/run-bazel-query-ci.sh}"
|
||||
|
||||
windows_cross_compile=0
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
@@ -22,31 +24,43 @@ done
|
||||
# Resolve the dynamic targets before printing anything so callers do not
|
||||
# continue with a partial list if `bazel query` fails. Target discovery is
|
||||
# local on all platforms.
|
||||
production_targets="$(
|
||||
"${query_script}" \
|
||||
--output=label \
|
||||
-- 'attr(visibility, "//visibility:public", kind("rust_(binary|library|proc_macro) rule", //codex-rs/... except //codex-rs/v8-poc/...))' \
|
||||
| LC_ALL=C sort
|
||||
)"
|
||||
|
||||
if [[ -z "${production_targets}" ]]; then
|
||||
echo "No Bazel clippy production targets found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $windows_cross_compile -eq 1 ]]; then
|
||||
# Build-only cross-compilation has no target-platform test runner. Lint the
|
||||
# complete production surface without analyzing rust_test or
|
||||
# workspace_root_test rules.
|
||||
printf '%s\n' "${production_targets}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
manual_rust_test_targets="$(
|
||||
./.github/scripts/run-bazel-query-ci.sh \
|
||||
"${query_script}" \
|
||||
--output=label \
|
||||
-- 'kind("rust_test rule", attr(tags, "manual", //codex-rs/... except //codex-rs/v8-poc/...))'
|
||||
)"
|
||||
if [[ "${RUNNER_OS:-}" != "Windows" ]]; then
|
||||
# Non-Windows clippy jobs lint the native test binaries; the
|
||||
# Windows-cross binaries exist only for the fast Windows test leg.
|
||||
manual_rust_test_targets="$(printf '%s\n' "${manual_rust_test_targets}" | grep -v -- '-windows-cross-bin$' || true)"
|
||||
elif [[ $windows_cross_compile -eq 1 ]]; then
|
||||
# `bazel query` is intentionally pre-analysis and does not remove targets
|
||||
# made incompatible by `target_compatible_with`. Sharded integration tests
|
||||
# add native-only manual helpers such as `core-all-test-bin`, plus separate
|
||||
# `core-all-test-windows-cross-bin` helpers for the Windows cross leg. Keep
|
||||
# the Windows helpers and unit-test helpers, but do not pass the native-only
|
||||
# sharded integration helpers as explicit clippy targets.
|
||||
manual_rust_test_targets="$(printf '%s\n' "${manual_rust_test_targets}" | grep -v -- '-test-bin$' || true)"
|
||||
fi
|
||||
|
||||
printf '%s\n' \
|
||||
"//codex-rs/..." \
|
||||
"-//codex-rs/v8-poc:all"
|
||||
manual_rust_test_targets="$(
|
||||
printf '%s\n' "${manual_rust_test_targets}" \
|
||||
| grep -v -- '-windows-cross-bin$' \
|
||||
| LC_ALL=C sort \
|
||||
|| true
|
||||
)"
|
||||
|
||||
# `--config=clippy` on the `workspace_root_test` wrappers does not lint the
|
||||
# underlying `rust_test` binaries. Add the internal manual `*-unit-tests-bin`
|
||||
# targets explicitly so inline `#[cfg(test)]` code is linted like
|
||||
# `cargo clippy --tests`.
|
||||
printf '%s\n' "${manual_rust_test_targets}"
|
||||
printf '%s\n' "${production_targets}"
|
||||
if [[ -n "${manual_rust_test_targets}" ]]; then
|
||||
printf '%s\n' "${manual_rust_test_targets}"
|
||||
fi
|
||||
|
||||
@@ -5,12 +5,22 @@ set -euo pipefail
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
|
||||
# Keep this list focused on first-party Rust targets whose compile surface can
|
||||
# differ when `cfg(not(debug_assertions))` becomes active.
|
||||
#
|
||||
# Exclude the experimental `v8-poc` target because it pulls in expensive V8
|
||||
# build machinery that is unrelated to the release-only Rust regression this
|
||||
# workflow is meant to catch.
|
||||
printf '%s\n' \
|
||||
"//codex-rs/..." \
|
||||
"-//codex-rs/v8-poc:all"
|
||||
query_script="${CODEX_BAZEL_QUERY_SCRIPT:-./.github/scripts/run-bazel-query-ci.sh}"
|
||||
|
||||
# Enumerate explicit first-party production targets instead of returning a
|
||||
# recursive package pattern. A recursive build pattern also selects rust_test
|
||||
# and workspace_root_test rules, which makes build-only cross-compilation
|
||||
# depend on a target-platform test execution toolchain.
|
||||
production_targets="$(
|
||||
"${query_script}" \
|
||||
--output=label \
|
||||
-- 'attr(visibility, "//visibility:public", kind("rust_(binary|library|proc_macro) rule", //codex-rs/... except //codex-rs/v8-poc/...))' \
|
||||
| LC_ALL=C sort
|
||||
)"
|
||||
|
||||
if [[ -z "${production_targets}" ]]; then
|
||||
echo "No Bazel release-build targets found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "${production_targets}"
|
||||
|
||||
Reference in New Issue
Block a user