diff --git a/cli/test/integration/cli/cli_test.go b/cli/test/integration/cli/cli_test.go index fe4fda17c9f..d54d2cd29e3 100644 --- a/cli/test/integration/cli/cli_test.go +++ b/cli/test/integration/cli/cli_test.go @@ -47,7 +47,8 @@ func TestBazelVersion(t *testing.T) { func TestBazelRun(t *testing.T) { ws := testcli.NewWorkspace(t) testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_binary(name = "fail", srcs = ["fail.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "fail", srcs = ["fail.sh"])`, "fail.sh": `exit 1`, }) testfs.MakeExecutable(t, ws, "fail.sh") @@ -60,7 +61,8 @@ func TestBazelRun(t *testing.T) { func TestParseGlobalFlags(t *testing.T) { ws := testcli.NewWorkspace(t) testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "print_args.sh": `echo $@`, }) testfs.MakeExecutable(t, ws, "print_args.sh") @@ -183,6 +185,7 @@ func newBazelrcWorkspace(t *testing.T) string { ws := testcli.NewWorkspace(t) testfs.WriteAllFileContents(t, ws, map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_test.bzl", "sh_test") sh_test(name = "needs_required_rc", srcs = ["needs_required_rc.sh"]) `, "needs_required_rc.sh": `#!/usr/bin/env bash @@ -210,6 +213,7 @@ func TestWorkspaceBazelrcAppliedOnce(t *testing.T) { testfs.WriteAllFileContents(t, ws, map[string]string{ ".bazelrc": `test --test_arg=workspace-rc`, "BUILD": ` +load("@rules_shell//shell:sh_test.bzl", "sh_test") sh_test(name = "assert_single_workspace_rc_arg", srcs = ["assert_single_workspace_rc_arg.sh"]) `, "assert_single_workspace_rc_arg.sh": `#!/usr/bin/env bash @@ -313,7 +317,8 @@ func TestBazelRunWithLocalPlugin(t *testing.T) { ws := testcli.NewWorkspace(t) testgit.ConfigureRemoteOrigin(t, ws, "https://secretUser:secretToken@github.com/test-org/test-repo") testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_binary(name = "echo", srcs = ["echo.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "echo", srcs = ["echo.sh"])`, "echo.sh": "echo $@", }) testfs.MakeExecutable(t, ws, "echo.sh") @@ -396,7 +401,8 @@ func TestBazelBuildWithBuildBuddyServices(t *testing.T) { ws := testcli.NewWorkspace(t) testgit.ConfigureRemoteOrigin(t, ws, "https://secretUser:secretToken@github.com/test-org/test-repo") testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_binary(name = "nop", srcs = ["nop.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "nop", srcs = ["nop.sh"])`, "nop.sh": "", }) testfs.MakeExecutable(t, ws, "nop.sh") @@ -468,7 +474,8 @@ func TestTerminalOutput(t *testing.T) { sleep 0.1 done `, - "BUILD": `sh_test(name = "test", srcs = ["test.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_test.bzl", "sh_test") +sh_test(name = "test", srcs = ["test.sh"])`, }) term := testcli.PTY(t) @@ -491,6 +498,7 @@ func TestTargetPatternFile(t *testing.T) { test:pattern-file --target_pattern_file=targets.txt `, "BUILD": ` +load("@rules_shell//shell:sh_test.bzl", "sh_test") sh_test(name = "pass", srcs = ["pass.sh"]) sh_test(name = "fail", srcs = ["fail.sh"]) `, @@ -516,7 +524,8 @@ sh_test(name = "fail", srcs = ["fail.sh"]) func TestQueryFile(t *testing.T) { ws := testcli.NewWorkspace(t) testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_test(name = "nop", srcs = ["nop.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_test.bzl", "sh_test") +sh_test(name = "nop", srcs = ["nop.sh"])`, "nop.sh": "", "targets.txt": "//:nop", }) diff --git a/enterprise/server/test/integration/ci_runner/ci_runner_test.go b/enterprise/server/test/integration/ci_runner/ci_runner_test.go index 6c8babcffa5..96276c290b8 100644 --- a/enterprise/server/test/integration/ci_runner/ci_runner_test.go +++ b/enterprise/server/test/integration/ci_runner/ci_runner_test.go @@ -69,6 +69,7 @@ actions: workspaceContentsWithTestsAndNoBuildBuddyYAML = map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_test.bzl", "sh_test") sh_test(name = "pass", srcs = ["pass.sh"]) sh_test(name = "fail", srcs = ["fail.sh"]) `, @@ -78,6 +79,7 @@ sh_test(name = "fail", srcs = ["fail.sh"]) workspaceContentsWithTestsAndBuildBuddyYAML = map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_test.bzl", "sh_test") sh_test(name = "pass", srcs = ["pass.sh"]) sh_test(name = "fail", srcs = ["fail.sh"]) `, @@ -95,7 +97,8 @@ actions: } workspaceContentsWithRunScript = map[string]string{ - "BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "print_args.sh": "echo 'args: {{' $@ '}}'", "buildbuddy.yaml": ` actions: @@ -109,7 +112,8 @@ actions: } workspaceContentsWithEnvVars = map[string]string{ - "BUILD": `sh_test(name = "check_env", srcs = ["check_env.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_test.bzl", "sh_test") +sh_test(name = "check_env", srcs = ["check_env.sh"])`, "check_env.sh": ` if [[ "$TEST_SECRET_1" != "test_secret_1_value" ]]; then @@ -135,7 +139,8 @@ actions: } workspaceContentsWithLocalEnvironmentalErrorAction = map[string]string{ - "BUILD": `sh_binary(name = "exit", srcs = ["exit.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "exit", srcs = ["exit.sh"])`, "exit.sh": `exit "$1"`, "buildbuddy.yaml": ` actions: @@ -149,7 +154,8 @@ actions: } workspaceContentsWithExitScriptAndMergeDisabled = map[string]string{ - "BUILD": `sh_binary(name = "exit", srcs = ["exit.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "exit", srcs = ["exit.sh"])`, "exit.sh": `exit "$1"`, "buildbuddy.yaml": ` actions: @@ -165,6 +171,8 @@ actions: workspaceContentsWithArtifactUploads = map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +load("@rules_shell//shell:sh_test.bzl", "sh_test") sh_test(name = "pass", srcs = ["pass.sh"]) sh_binary(name = "check_artifacts_dir", srcs = ["check_artifacts_dir.sh"]) `, @@ -191,7 +199,8 @@ actions: } workspaceContentsWithGitLog = map[string]string{ - "BUILD": `sh_binary(name = "log", srcs = ["log.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "log", srcs = ["log.sh"])`, "log.sh": ` cd "$BUILD_WORKSPACE_DIRECTORY" git log @@ -440,7 +449,8 @@ func TestCIRunner_RunsBashCommands_BazelWithOptions(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { workspaceContents := map[string]string{ - "BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "print_args.sh": "echo 'args: {{' $@ '}}'", "buildbuddy.yaml": ` actions: @@ -484,7 +494,8 @@ func TestCIRunner_AppliesCustomBazelrc(t *testing.T) { ".bazelrc": ` common --invocation_id=00000000-0000-0000-0000-000000000000 `, - "BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "print_args.sh": "echo 'args: {{' $@ '}}'", "buildbuddy.yaml": ` actions: @@ -503,7 +514,8 @@ actions: { name: "Does not have a workspace .bazelrc", workspaceContents: map[string]string{ - "BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "print_args.sh": "echo 'args: {{' $@ '}}'", "buildbuddy.yaml": ` actions: @@ -526,7 +538,8 @@ actions: "subdir/.bazelrc": ` common --invocation_id=00000000-0000-0000-0000-000000000000 `, - "subdir/BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "subdir/BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "subdir/print_args.sh": "echo 'args: {{' $@ '}}'", "buildbuddy.yaml": ` actions: @@ -618,7 +631,8 @@ func TestCIRunner_StartupOptionsDontRestartBazelServer(t *testing.T) { // Run a bazel command with a startup option workspaceContents := map[string]string{ - "BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "print_args.sh": "echo 'args: {{' $@ '}}'", "buildbuddy.yaml": ` actions: @@ -655,7 +669,8 @@ actions: func TestCIRunner_SetsMaxIdleSecsToZero(t *testing.T) { wsPath := testfs.MakeTempDir(t) workspaceContents := map[string]string{ - "BUILD": `sh_binary(name = "print_args", srcs = ["print_args.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "print_args", srcs = ["print_args.sh"])`, "print_args.sh": "echo 'args: {{' $@ '}}'", "buildbuddy.yaml": ` actions: @@ -1512,7 +1527,8 @@ func TestGitCleanExclude(t *testing.T) { wsPath := testfs.MakeTempDir(t) targetRepoPath, commitSHA := makeGitRepo(t, map[string]string{ - "BUILD": `sh_binary(name = "check_repo", srcs = ["check_repo.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "check_repo", srcs = ["check_repo.sh"])`, "check_repo.sh": ` cd "$BUILD_WORKSPACE_DIRECTORY" echo "not_excluded.txt exists:" $([[ -e not_excluded.txt ]] && echo yes || echo no) @@ -1562,7 +1578,8 @@ func TestBazelWorkspaceDir(t *testing.T) { wsPath := testfs.MakeTempDir(t) repoPath, _ := makeGitRepo(t, map[string]string{ - "subdir/BUILD": `sh_test(name = "pass", srcs = ["pass.sh"])`, + "subdir/BUILD": `load("@rules_shell//shell:sh_test.bzl", "sh_test") +sh_test(name = "pass", srcs = ["pass.sh"])`, "subdir/pass.sh": "", "subdir/.bazelrc": ` # This role should take priority over the CI role. @@ -1608,7 +1625,8 @@ func TestHostedBazel_ApplyingAndDiscardingPatches(t *testing.T) { wsPath := testfs.MakeTempDir(t) targetRepoPath, _ := makeGitRepo(t, map[string]string{ - "BUILD": `sh_test(name = "pass", srcs = ["pass.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_test.bzl", "sh_test") +sh_test(name = "pass", srcs = ["pass.sh"])`, "pass.sh": "exit 0", }) @@ -1926,6 +1944,7 @@ func TestArtifactUploads_GRPCLog(t *testing.T) { func TestArtifactUploads_JVMLog(t *testing.T) { workspaceSimulateOOM := map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_test.bzl", "sh_test") sh_test(name = "simulate_oom", srcs = ["simulate_oom.sh"]) `, "simulate_oom.sh": ` @@ -2033,7 +2052,8 @@ func TestTimeout(t *testing.T) { func TestBazelLock(t *testing.T) { wsPath := testfs.MakeTempDir(t) repoPath, _ := makeGitRepo(t, map[string]string{ - "BUILD": `sh_test(name = "sleep_test", srcs = ["sleep_test.sh"], tags = ["no-sandbox"])`, + "BUILD": `load("@rules_shell//shell:sh_test.bzl", "sh_test") +sh_test(name = "sleep_test", srcs = ["sleep_test.sh"], tags = ["no-sandbox"])`, "sleep_test.sh": `touch "$TEST_STARTED" && sleep 99999999`, "buildbuddy.yaml": ` actions: diff --git a/enterprise/server/test/integration/cli/stream_run_logs/stream_run_logs_test.go b/enterprise/server/test/integration/cli/stream_run_logs/stream_run_logs_test.go index 3852f1c239c..914c9f2a075 100644 --- a/enterprise/server/test/integration/cli/stream_run_logs/stream_run_logs_test.go +++ b/enterprise/server/test/integration/cli/stream_run_logs/stream_run_logs_test.go @@ -55,7 +55,8 @@ func (f *fakeWriteEventLogClient) CloseAndRecv() (*elpb.WriteEventLogResponse, e func TestWithBuild(t *testing.T) { ws := testcli.NewWorkspace(t) testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_binary(name = "echo", srcs = ["echo.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "echo", srcs = ["echo.sh"])`, "echo.sh": `#!/bin/bash echo "hello world" echo "goodbye world" @@ -101,7 +102,8 @@ echo "goodbye world" func TestFailingCommand(t *testing.T) { ws := testcli.NewWorkspace(t) testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_binary(name = "echo", srcs = ["echo.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "echo", srcs = ["echo.sh"])`, "echo.sh": `#!/bin/bash echo "bad script!" exit 5 @@ -254,7 +256,8 @@ echo "hello world" func TestSignalForwarding(t *testing.T) { ws := testcli.NewWorkspace(t) testfs.WriteAllFileContents(t, ws, map[string]string{ - "BUILD": `sh_binary(name = "sleeper", srcs = ["sleeper.sh"])`, + "BUILD": `load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +sh_binary(name = "sleeper", srcs = ["sleeper.sh"])`, "sleeper.sh": `#!/bin/bash echo "script started!" sleep 99999 diff --git a/enterprise/server/test/integration/workflow/workflow_test.go b/enterprise/server/test/integration/workflow/workflow_test.go index 170f846e603..cbeb2b12f86 100644 --- a/enterprise/server/test/integration/workflow/workflow_test.go +++ b/enterprise/server/test/integration/workflow/workflow_test.go @@ -50,6 +50,7 @@ const ( func simpleRepo() map[string]string { return map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") sh_binary( name = "nop", srcs = ["nop.sh"], @@ -78,6 +79,7 @@ func simpleRepoUseCLI(t *testing.T) map[string]string { bazelrcPath := filepath.Join(os.Getenv("TEST_TMPDIR"), fmt.Sprintf("bazel-%s.bazelrc", testbazel.Version)) return map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") sh_binary( name = "nop", srcs = ["nop.sh"], @@ -105,6 +107,7 @@ actions: func repoWithSlowScript() map[string]string { return map[string]string{ "BUILD": ` +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") sh_binary( name = "sleep_forever_test", srcs = ["sleep_forever_test.sh"], diff --git a/server/testutil/testbazel/testbazel.go b/server/testutil/testbazel/testbazel.go index 45743d21329..8f2671be304 100644 --- a/server/testutil/testbazel/testbazel.go +++ b/server/testutil/testbazel/testbazel.go @@ -47,9 +47,22 @@ var ( // given workspace dir if they don't already exist. The lockfile that is written // is sufficient for bazel to not make any network requests when using built-in // rules such as genrule, sh_binary, and sh_test. +// +// A bazel_dep on @rules_shell is unconditionally added (if not already +// present) so that test BUILD files can uniformly load sh_binary / sh_test +// from @rules_shell. This is required on Bazel 9 (where they're no longer +// native) and harmless on Bazel 8. func InitModule(t testing.TB, workspaceDir string) { - if !testfs.Exists(t, workspaceDir, "MODULE.bazel") { - testfs.WriteFile(t, workspaceDir, "MODULE.bazel", "") + var module string + if testfs.Exists(t, workspaceDir, "MODULE.bazel") { + module = testfs.ReadFileAsString(t, workspaceDir, "MODULE.bazel") + } + if !strings.Contains(module, `"rules_shell"`) { + if module != "" && !strings.HasSuffix(module, "\n") { + module += "\n" + } + module += `bazel_dep(name = "rules_shell", version = "0.6.1")` + "\n" + testfs.WriteFile(t, workspaceDir, "MODULE.bazel", module) } if !testfs.Exists(t, workspaceDir, "MODULE.bazel.lock") { lockfileContents := testfs.ReadFileAsString(t, "", lockfilePath(t)) diff --git a/server/util/bazel/defs.bzl b/server/util/bazel/defs.bzl index 530f7b3fdeb..c4fd7ed3976 100644 --- a/server/util/bazel/defs.bzl +++ b/server/util/bazel/defs.bzl @@ -105,8 +105,12 @@ def bazel_pkg_tar(name, versions = [], **kwargs): major_version = int(version.split(".")[0]) warm_repository_cache = major_version >= 8 - # For Bazel 9+, sh_binary and sh_test are no longer native rules. - use_rules_shell = major_version >= 9 + # Always warm @rules_shell. On Bazel 9+ it's strictly required + # (sh_binary / sh_test are no longer native). On Bazel 8 it's + # optional but cheap, and lets test-written BUILD files use a + # single `load("@rules_shell//shell:...")` form that works on + # both versions. + use_rules_shell = major_version >= 8 extract_bazel_installation( name = "bazel-{}_extract_installation".format(version), bazel = ":bazel-{}_crossplatform".format(version),