mirror of
https://github.com/openai/codex.git
synced 2026-11-13 21:30:47 +00:00
Add authenticated GCS caching for Bazel CI and releases (#61187)
## What changed - Authenticate eligible protected `main` runs and Rust release tags with GitHub OIDC. Allow cache uploads only on `main` pushes; use read-only access for manual runs and release tags, and leave pull requests without GCS credentials. - Rename the shared wrapper to `.github/scripts/run_bazel.py` and route Bazel callers through it. Disable the disk cache in GitHub Actions and default macOS GCS connections to 20 while respecting explicit limits. - Gate additional Bazel release artifacts on `CODEX_BAZEL_RELEASES` and cache configuration, sharing the selected build systems across building, signing, and packaging. Keep Cargo as the default and prepare native Windows dependencies for Bazel releases. - Add a `Bazel result` check for the full workflow and extend Bazel job timeouts. ## Testing Add wrapper tests for cache access by event, argument preservation, and macOS connection limits. The wrapper test suite passes. GitOrigin-RevId: d85edbd083acfaa8bafaa8fd5241daed3e9ef871
This commit is contained in:
committed by
copyberry
parent
d0221bc947
commit
4490060db6
@@ -1,5 +1,5 @@
|
||||
<#
|
||||
BuildBuddy cache keys include the action and test environment, so Bazel should
|
||||
Bazel action cache keys include the action and test environment, so Bazel should
|
||||
not inherit the full hosted-runner PATH on Windows. That PATH includes volatile
|
||||
tool entries, such as Maven, that can change independently of this repo and
|
||||
cause avoidable cache misses.
|
||||
|
||||
@@ -53,11 +53,11 @@ fi
|
||||
|
||||
run_bazel() {
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
MSYS2_ARG_CONV_EXCL='*' "$(dirname "${BASH_SOURCE[0]}")/run_bazel_with_buildbuddy.py" "$@"
|
||||
MSYS2_ARG_CONV_EXCL='*' "$(dirname "${BASH_SOURCE[0]}")/run_bazel.py" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
"$(dirname "${BASH_SOURCE[0]}")/run_bazel_with_buildbuddy.py" "$@"
|
||||
"$(dirname "${BASH_SOURCE[0]}")/run_bazel.py" "$@"
|
||||
}
|
||||
|
||||
run_bazel_with_startup_args() {
|
||||
|
||||
@@ -17,11 +17,11 @@ query_expression="${@: -1}"
|
||||
|
||||
run_bazel() {
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
MSYS2_ARG_CONV_EXCL='*' "$(dirname "${BASH_SOURCE[0]}")/run_bazel_with_buildbuddy.py" "$@"
|
||||
MSYS2_ARG_CONV_EXCL='*' "$(dirname "${BASH_SOURCE[0]}")/run_bazel.py" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
"$(dirname "${BASH_SOURCE[0]}")/run_bazel_with_buildbuddy.py" "$@"
|
||||
"$(dirname "${BASH_SOURCE[0]}")/run_bazel.py" "$@"
|
||||
}
|
||||
|
||||
bazel_query_args=(query)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from collections.abc import Mapping
|
||||
from collections.abc import Sequence
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# These configs select remote execution, which is unavailable on CI runners.
|
||||
@@ -92,6 +94,41 @@ def bazel_args_with_remote_config(
|
||||
arg.startswith(option_prefix) for arg in configured_args[:separator_idx]
|
||||
)
|
||||
]
|
||||
# Ephemeral runners already retain active outputs in Bazel's output tree.
|
||||
# Avoid storing a second copy while using the GCS action cache.
|
||||
if env.get("GITHUB_ACTIONS") == "true":
|
||||
cache_args.append("--disk_cache=")
|
||||
bucket = env.get("CODEX_BAZEL_GCS_BUCKET")
|
||||
credentials = env.get("CODEX_BAZEL_GCS_CREDENTIALS")
|
||||
if (
|
||||
bucket
|
||||
and credentials
|
||||
and args[command_idx] in {"build", "test", "run", "coverage"}
|
||||
):
|
||||
if not re.fullmatch(r"[a-z0-9][a-z0-9_-]{1,61}[a-z0-9]", bucket):
|
||||
raise ValueError("Expected a GCS bucket name")
|
||||
if not Path(credentials).is_absolute() or not Path(credentials).is_file():
|
||||
raise ValueError(
|
||||
"Missing GitHub workload identity credentials for the GCS cache"
|
||||
)
|
||||
cache_args.extend(
|
||||
(
|
||||
f"--remote_cache=https://storage.googleapis.com/{bucket}",
|
||||
f"--google_credentials={credentials}",
|
||||
)
|
||||
)
|
||||
# Bound HTTP socket pressure on macOS runners while reusing the GCS cache.
|
||||
if env.get("RUNNER_OS") == "macOS" and not any(
|
||||
arg == "--remote_max_connections"
|
||||
or arg.startswith("--remote_max_connections=")
|
||||
for arg in configured_args[:separator_idx]
|
||||
):
|
||||
cache_args.append("--remote_max_connections=20")
|
||||
if (
|
||||
env.get("GITHUB_EVENT_NAME") != "push"
|
||||
or env.get("GITHUB_REF") != "refs/heads/main"
|
||||
):
|
||||
cache_args.append("--remote_upload_local_results=false")
|
||||
return [
|
||||
*configured_args[:separator_idx],
|
||||
*cache_args,
|
||||
@@ -12,7 +12,7 @@ import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
from run_bazel_with_buildbuddy import bazel_command
|
||||
from run_bazel import bazel_command
|
||||
from rusty_v8_module_bazel import (
|
||||
RustyV8ChecksumError,
|
||||
check_module_bazel,
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
import run_bazel
|
||||
|
||||
|
||||
class RunBazelCiTest(unittest.TestCase):
|
||||
def test_cache_permissions_and_run_arguments(self) -> None:
|
||||
with TemporaryDirectory() as temp_dir:
|
||||
credentials = Path(temp_dir) / "job credentials.json"
|
||||
credentials.touch()
|
||||
for event, ref, authenticated, mode in (
|
||||
("push", "refs/heads/main", True, "write"),
|
||||
("workflow_dispatch", "refs/heads/main", True, "read"),
|
||||
("push", "refs/tags/rust-v1.0.0", True, "read"),
|
||||
("pull_request", "refs/pull/1/merge", False, "local"),
|
||||
):
|
||||
with self.subTest(event=event, ref=ref, authenticated=authenticated):
|
||||
env = {
|
||||
"GITHUB_EVENT_NAME": event,
|
||||
"GITHUB_REF": ref,
|
||||
"CODEX_BAZEL_GCS_BUCKET": "example-public",
|
||||
}
|
||||
if authenticated:
|
||||
env["CODEX_BAZEL_GCS_CREDENTIALS"] = str(credentials)
|
||||
flags = []
|
||||
if mode != "local":
|
||||
flags = [
|
||||
"--remote_cache=https://storage.googleapis.com/example-public",
|
||||
f"--google_credentials={credentials}",
|
||||
]
|
||||
if mode == "read":
|
||||
flags.append("--remote_upload_local_results=false")
|
||||
self.assertEqual(
|
||||
run_bazel.bazel_args_with_remote_config(
|
||||
[
|
||||
"run",
|
||||
"--config=ci-linux",
|
||||
"//:binary",
|
||||
"--",
|
||||
"--user-flag",
|
||||
],
|
||||
env,
|
||||
),
|
||||
["run", "//:binary", *flags, "--", "--user-flag"],
|
||||
)
|
||||
|
||||
def test_macos_cache_connection_limit_respects_explicit_setting(self) -> None:
|
||||
with TemporaryDirectory() as temp_dir:
|
||||
credentials = Path(temp_dir) / "credentials.json"
|
||||
credentials.touch()
|
||||
env = {
|
||||
"RUNNER_OS": "macOS",
|
||||
"GITHUB_EVENT_NAME": "push",
|
||||
"GITHUB_REF": "refs/heads/main",
|
||||
"CODEX_BAZEL_GCS_BUCKET": "example-public",
|
||||
"CODEX_BAZEL_GCS_CREDENTIALS": str(credentials),
|
||||
}
|
||||
for supplied in (
|
||||
[],
|
||||
["--remote_max_connections=8"],
|
||||
["--remote_max_connections", "8"],
|
||||
):
|
||||
with self.subTest(supplied=supplied):
|
||||
configured = run_bazel.bazel_args_with_remote_config(
|
||||
["build", *supplied, "//:binary"], env
|
||||
)
|
||||
expected = [
|
||||
"build",
|
||||
*supplied,
|
||||
"//:binary",
|
||||
"--remote_cache=https://storage.googleapis.com/example-public",
|
||||
f"--google_credentials={credentials}",
|
||||
]
|
||||
if not supplied:
|
||||
expected.append("--remote_max_connections=20")
|
||||
self.assertEqual(configured, expected)
|
||||
|
||||
def test_bazel_command_uses_configured_binary_locally(self) -> None:
|
||||
self.assertEqual(
|
||||
run_bazel.bazel_command(
|
||||
"info",
|
||||
"execution_root",
|
||||
env={"CODEX_BAZEL_BIN": "fake-bazel"},
|
||||
),
|
||||
["fake-bazel", "info", "execution_root"],
|
||||
)
|
||||
|
||||
def test_bazel_command_normalizes_github_actions_startup_options(self) -> None:
|
||||
env = {
|
||||
"BAZEL_OUTPUT_USER_ROOT": "/tmp/bazel-output",
|
||||
"GITHUB_ACTIONS": "true",
|
||||
}
|
||||
|
||||
self.assertEqual(
|
||||
run_bazel.bazel_command("build", "//codex-rs/...", env=env),
|
||||
[
|
||||
"bazel",
|
||||
"--output_user_root=/tmp/bazel-output",
|
||||
"--noexperimental_remote_repo_contents_cache",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
"--disk_cache=",
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
run_bazel.bazel_command(
|
||||
"--experimental_remote_repo_contents_cache",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
env=env,
|
||||
),
|
||||
[
|
||||
"bazel",
|
||||
"--output_user_root=/tmp/bazel-output",
|
||||
"--experimental_remote_repo_contents_cache",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
"--disk_cache=",
|
||||
],
|
||||
)
|
||||
|
||||
def test_bazel_command_uses_configured_local_caches(self) -> None:
|
||||
env = {
|
||||
"BAZEL_REPO_CONTENTS_CACHE": "/tmp/bazel-repo-contents",
|
||||
"BAZEL_REPOSITORY_CACHE": "/tmp/bazel-repository",
|
||||
}
|
||||
|
||||
self.assertEqual(
|
||||
run_bazel.bazel_command(
|
||||
"build",
|
||||
"--config=local",
|
||||
"//codex-rs/...",
|
||||
env=env,
|
||||
),
|
||||
[
|
||||
"bazel",
|
||||
"build",
|
||||
"--config=local",
|
||||
"//codex-rs/...",
|
||||
"--repo_contents_cache=/tmp/bazel-repo-contents",
|
||||
"--repository_cache=/tmp/bazel-repository",
|
||||
],
|
||||
)
|
||||
|
||||
def test_bazel_command_adds_local_caches_before_separator(self) -> None:
|
||||
self.assertEqual(
|
||||
run_bazel.bazel_command(
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
"--",
|
||||
"--program-arg",
|
||||
env={"BAZEL_REPOSITORY_CACHE": "/tmp/bazel-repository"},
|
||||
),
|
||||
[
|
||||
"bazel",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
"--repository_cache=/tmp/bazel-repository",
|
||||
"--",
|
||||
"--program-arg",
|
||||
],
|
||||
)
|
||||
|
||||
def test_main_preserves_spaced_argument_and_child_exit_status(self) -> None:
|
||||
spaced_arg = (
|
||||
r"--test_env=PATH=C:\Program Files\PowerShell\7;C:\Program Files\Git\bin"
|
||||
)
|
||||
child_code = (
|
||||
f"import sys; sys.exit(37 if sys.argv[1] == {spaced_arg!r} else 91)"
|
||||
)
|
||||
env = os.environ.copy()
|
||||
env["CODEX_BAZEL_BIN"] = sys.executable
|
||||
env.pop("BAZEL_OUTPUT_USER_ROOT", None)
|
||||
env.pop("GITHUB_ACTIONS", None)
|
||||
|
||||
result = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(Path(run_bazel.__file__)),
|
||||
"-c",
|
||||
child_code,
|
||||
spaced_arg,
|
||||
],
|
||||
env=env,
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
self.assertEqual(result.returncode, 37, result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,127 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
import run_bazel_with_buildbuddy
|
||||
|
||||
|
||||
class RunBazelWithBuildBuddyTest(unittest.TestCase):
|
||||
def test_bazel_command_uses_configured_binary_locally(self) -> None:
|
||||
self.assertEqual(
|
||||
run_bazel_with_buildbuddy.bazel_command(
|
||||
"info",
|
||||
"execution_root",
|
||||
env={"CODEX_BAZEL_BIN": "fake-bazel"},
|
||||
),
|
||||
["fake-bazel", "info", "execution_root"],
|
||||
)
|
||||
|
||||
def test_bazel_command_normalizes_github_actions_startup_options(self) -> None:
|
||||
env = {
|
||||
"BAZEL_OUTPUT_USER_ROOT": "/tmp/bazel-output",
|
||||
"GITHUB_ACTIONS": "true",
|
||||
}
|
||||
|
||||
self.assertEqual(
|
||||
run_bazel_with_buildbuddy.bazel_command("build", "//codex-rs/...", env=env),
|
||||
[
|
||||
"bazel",
|
||||
"--output_user_root=/tmp/bazel-output",
|
||||
"--noexperimental_remote_repo_contents_cache",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
run_bazel_with_buildbuddy.bazel_command(
|
||||
"--experimental_remote_repo_contents_cache",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
env=env,
|
||||
),
|
||||
[
|
||||
"bazel",
|
||||
"--output_user_root=/tmp/bazel-output",
|
||||
"--experimental_remote_repo_contents_cache",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
],
|
||||
)
|
||||
|
||||
def test_bazel_command_uses_configured_local_caches(self) -> None:
|
||||
env = {
|
||||
"BAZEL_REPO_CONTENTS_CACHE": "/tmp/bazel-repo-contents",
|
||||
"BAZEL_REPOSITORY_CACHE": "/tmp/bazel-repository",
|
||||
}
|
||||
|
||||
self.assertEqual(
|
||||
run_bazel_with_buildbuddy.bazel_command(
|
||||
"build",
|
||||
"--config=local",
|
||||
"//codex-rs/...",
|
||||
env=env,
|
||||
),
|
||||
[
|
||||
"bazel",
|
||||
"build",
|
||||
"--config=local",
|
||||
"//codex-rs/...",
|
||||
"--repo_contents_cache=/tmp/bazel-repo-contents",
|
||||
"--repository_cache=/tmp/bazel-repository",
|
||||
],
|
||||
)
|
||||
|
||||
def test_bazel_command_adds_local_caches_before_separator(self) -> None:
|
||||
self.assertEqual(
|
||||
run_bazel_with_buildbuddy.bazel_command(
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
"--",
|
||||
"--program-arg",
|
||||
env={"BAZEL_REPOSITORY_CACHE": "/tmp/bazel-repository"},
|
||||
),
|
||||
[
|
||||
"bazel",
|
||||
"build",
|
||||
"//codex-rs/...",
|
||||
"--repository_cache=/tmp/bazel-repository",
|
||||
"--",
|
||||
"--program-arg",
|
||||
],
|
||||
)
|
||||
|
||||
def test_main_preserves_spaced_argument_and_child_exit_status(self) -> None:
|
||||
spaced_arg = (
|
||||
r"--test_env=PATH=C:\Program Files\PowerShell\7;C:\Program Files\Git\bin"
|
||||
)
|
||||
child_code = (
|
||||
f"import sys; sys.exit(37 if sys.argv[1] == {spaced_arg!r} else 91)"
|
||||
)
|
||||
env = os.environ.copy()
|
||||
env["CODEX_BAZEL_BIN"] = sys.executable
|
||||
env.pop("BAZEL_OUTPUT_USER_ROOT", None)
|
||||
env.pop("GITHUB_ACTIONS", None)
|
||||
|
||||
result = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(Path(run_bazel_with_buildbuddy.__file__)),
|
||||
"-c",
|
||||
child_code,
|
||||
spaced_arg,
|
||||
],
|
||||
env=env,
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
self.assertEqual(result.returncode, 37, result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -22,7 +22,7 @@ CANARY_PATH_PATTERNS = {
|
||||
".bazelrc",
|
||||
".github/actions/prepare-bazel-ci/**",
|
||||
".github/actions/setup-ci/**",
|
||||
".github/scripts/run_bazel_with_buildbuddy.py",
|
||||
".github/scripts/run_bazel.py",
|
||||
".github/scripts/rusty_v8_bazel.py",
|
||||
".github/scripts/rusty_v8_module_bazel.py",
|
||||
".github/scripts/setup-dev-drive.ps1",
|
||||
|
||||
Reference in New Issue
Block a user