Skip to content

Commit 30e207e

Browse files
authored
[WF] Speed up slow tests (#11376)
These remote runner tests are slow because [we upload 2 50MB binaries](https://github.com/buildbuddy-io/buildbuddy/blob/master/enterprise/server/util/ci_runner_util/ci_runner_util.go#L48) to the in-memory cache, which is very resource constrained in CI I disabled this behavior for most tests, and added one test that tests this behavior. Tests are now running much faster. With `--config=race`: //enterprise/server/test/integration/remote_bazel: [156s](https://app.buildbuddy.io/invocation/563922f0-40a7-4e3f-b018-9481cda8de4b) => [70.561s](https://app.buildbuddy.io/invocation/28df438c-cdd7-41fb-8917-1161b63201a1) //enterprise/server/workflow/service: [82.7s](https://app.buildbuddy.io/invocation/32e25dc1-000a-454e-b9d5-1a135624801f) => [14.7s ](https://app.buildbuddy.io/invocation/62af68fd-7cef-4591-b91a-a3ad6e771a46) etc... The new test still runs really slowly ([139s](https://app.buildbuddy.io/invocation/e1413d9c-b096-49a3-a6e3-8e794042f94e)), but I think it's worth it because this is the prod behavior. In production I don't expect this to be an issue because the upload should short circuit if the binary already exists in the cache
1 parent f0ce114 commit 30e207e

File tree

7 files changed

+97
-4
lines changed

7 files changed

+97
-4
lines changed

enterprise/server/hostedrunner/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ go_test(
5959
"//server/testutil/testenv",
6060
"//server/util/authutil",
6161
"//server/util/platform",
62+
"//server/util/testing/flags",
6263
"@com_github_stretchr_testify//require",
6364
"@com_google_cloud_go_longrunning//autogen/longrunningpb",
6465
"@org_golang_google_genproto_googleapis_bytestream//:bytestream",

enterprise/server/hostedrunner/hostedrunner_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/buildbuddy-io/buildbuddy/server/testutil/testenv"
1515
"github.com/buildbuddy-io/buildbuddy/server/util/authutil"
1616
"github.com/buildbuddy-io/buildbuddy/server/util/platform"
17+
"github.com/buildbuddy-io/buildbuddy/server/util/testing/flags"
1718
"github.com/stretchr/testify/require"
1819
"google.golang.org/grpc"
1920
"google.golang.org/grpc/metadata"
@@ -28,6 +29,10 @@ import (
2829
)
2930

3031
func getEnv(t *testing.T) (*testenv.TestEnv, context.Context) {
32+
// Avoid uploading embedded CI runner binaries to the in-memory cache in
33+
// each test because it's very slow. The executor will add these binaries locally instead.
34+
flags.Set(t, "remote_execution.init_ci_runner_from_cache", false)
35+
3136
te := enterprise_testenv.New(t)
3237
enterprise_testauth.Configure(t, te)
3338
ctx := context.Background()

enterprise/server/test/integration/remote_bazel/BUILD

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ go_test(
3030
"//cli/remotebazel",
3131
"//cli/testutil/testcli",
3232
"//enterprise/server/backends/kms",
33+
"//enterprise/server/cmd/ci_runner/bundle",
3334
"//enterprise/server/execution_service",
3435
"//enterprise/server/githubapp",
3536
"//enterprise/server/hostedrunner",
3637
"//enterprise/server/invocation_search_service",
38+
"//enterprise/server/remote_execution/snaputil",
3739
"//enterprise/server/secrets",
3840
"//enterprise/server/test/integration/remote_execution/rbetest",
3941
"//enterprise/server/util/keystore",
@@ -45,19 +47,21 @@ go_test(
4547
"//proto:eventlog_go_proto",
4648
"//proto:invocation_go_proto",
4749
"//proto:invocation_status_go_proto",
50+
"//proto:remote_execution_go_proto",
4851
"//proto:secrets_go_proto",
4952
"//proto:user_id_go_proto",
5053
"//server/backends/memory_kvstore",
5154
"//server/backends/repo_downloader",
5255
"//server/interfaces",
56+
"//server/remote_cache/digest",
5357
"//server/tables",
54-
"//server/testutil/quarantine",
5558
"//server/testutil/testbazel",
5659
"//server/testutil/testenv",
5760
"//server/testutil/testfs",
5861
"//server/testutil/testgit",
5962
"//server/testutil/testshell",
6063
"//server/util/bazel",
64+
"//server/util/bb",
6165
"//server/util/git",
6266
"//server/util/log",
6367
"//server/util/testing/flags",

enterprise/server/test/integration/remote_bazel/remote_bazel_test.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,21 @@ import (
1616
"github.com/buildbuddy-io/buildbuddy/cli/remotebazel"
1717
"github.com/buildbuddy-io/buildbuddy/cli/testutil/testcli"
1818
"github.com/buildbuddy-io/buildbuddy/enterprise/server/backends/kms"
19+
"github.com/buildbuddy-io/buildbuddy/enterprise/server/cmd/ci_runner/bundle"
1920
"github.com/buildbuddy-io/buildbuddy/enterprise/server/execution_service"
2021
"github.com/buildbuddy-io/buildbuddy/enterprise/server/githubapp"
2122
"github.com/buildbuddy-io/buildbuddy/enterprise/server/hostedrunner"
2223
"github.com/buildbuddy-io/buildbuddy/enterprise/server/invocation_search_service"
24+
"github.com/buildbuddy-io/buildbuddy/enterprise/server/remote_execution/snaputil"
2325
"github.com/buildbuddy-io/buildbuddy/enterprise/server/secrets"
2426
"github.com/buildbuddy-io/buildbuddy/enterprise/server/test/integration/remote_execution/rbetest"
2527
"github.com/buildbuddy-io/buildbuddy/enterprise/server/util/keystore"
2628
"github.com/buildbuddy-io/buildbuddy/enterprise/server/workflow/service"
2729
"github.com/buildbuddy-io/buildbuddy/server/backends/memory_kvstore"
2830
"github.com/buildbuddy-io/buildbuddy/server/backends/repo_downloader"
2931
"github.com/buildbuddy-io/buildbuddy/server/interfaces"
32+
"github.com/buildbuddy-io/buildbuddy/server/remote_cache/digest"
3033
"github.com/buildbuddy-io/buildbuddy/server/tables"
31-
"github.com/buildbuddy-io/buildbuddy/server/testutil/quarantine"
3234
"github.com/buildbuddy-io/buildbuddy/server/testutil/testbazel"
3335
"github.com/buildbuddy-io/buildbuddy/server/testutil/testenv"
3436
"github.com/buildbuddy-io/buildbuddy/server/testutil/testfs"
@@ -49,8 +51,10 @@ import (
4951
elpb "github.com/buildbuddy-io/buildbuddy/proto/eventlog"
5052
inpb "github.com/buildbuddy-io/buildbuddy/proto/invocation"
5153
inspb "github.com/buildbuddy-io/buildbuddy/proto/invocation_status"
54+
repb "github.com/buildbuddy-io/buildbuddy/proto/remote_execution"
5255
spb "github.com/buildbuddy-io/buildbuddy/proto/secrets"
5356
uidpb "github.com/buildbuddy-io/buildbuddy/proto/user_id"
57+
cli_bundle "github.com/buildbuddy-io/buildbuddy/server/util/bb"
5458
)
5559

5660
func init() {
@@ -216,6 +220,10 @@ func TestWithPrivateRepo(t *testing.T) {
216220
}
217221

218222
func runLocalServerAndExecutor(t *testing.T, mockPrivateGithubToken bool, envModifier func(rbeEnv *rbetest.Env, e *testenv.TestEnv)) (*rbetest.Env, *rbetest.BuildBuddyServer, *rbetest.Executor) {
223+
// Avoid uploading embedded CI runner binaries to the in-memory cache in
224+
// each test because it's very slow. The executor will add these binaries locally instead.
225+
flags.Set(t, "remote_execution.init_ci_runner_from_cache", false)
226+
219227
githubToken := ""
220228
repoURL := ""
221229
if mockPrivateGithubToken {
@@ -281,7 +289,6 @@ func runLocalServerAndExecutor(t *testing.T, mockPrivateGithubToken bool, envMod
281289
}
282290

283291
func TestCancel(t *testing.T) {
284-
quarantine.SkipQuarantinedTest(t)
285292
repoDir, _ := makeLocalGitRepo(t, map[string]string{
286293
"BUILD": `
287294
sh_binary(
@@ -656,3 +663,68 @@ func TestBashScript(t *testing.T) {
656663
require.NoError(t, err)
657664
require.Contains(t, string(logResp.GetBuffer()), "Hello from the remote runner!")
658665
}
666+
667+
// In production, the apps upload the ci_runner and bb binaries to the cache so
668+
// executors can fetch the latest versions without upgrading. Writing to the cache
669+
// for tests is very slow, so this behavior is disabled by default.
670+
//
671+
// This test enables the behavior and verifies the binaries can be used correctly.
672+
func TestEmbeddedBinariesFromApp(t *testing.T) {
673+
repoDir, _ := makeLocalGitRepo(t, map[string]string{})
674+
env, bbServer, _ := runLocalServerAndExecutor(t, false, nil)
675+
ctx := env.WithUserID(context.Background(), env.UserID1)
676+
677+
// The flag is disabled in `runLocalServerAndExecutor`. Enable it here.
678+
flags.Set(t, "remote_execution.init_ci_runner_from_cache", true)
679+
680+
require.NotEmpty(t, bundle.CiRunnerBytes)
681+
require.NotEmpty(t, cli_bundle.CLIBytes)
682+
runnerBinDigest, err := digest.Compute(bytes.NewReader(bundle.CiRunnerBytes), repb.DigestFunction_BLAKE3)
683+
require.NoError(t, err)
684+
cliDigest, err := digest.Compute(bytes.NewReader(cli_bundle.CLIBytes), repb.DigestFunction_BLAKE3)
685+
require.NoError(t, err)
686+
687+
// The binaries should not be in the cache to begin with.
688+
casClient := env.GetContentAddressableStorageClient()
689+
findReq := &repb.FindMissingBlobsRequest{
690+
// Hosted runner uploads the CI runner inputs to the snapshot partition.
691+
InstanceName: snaputil.SnapshotPartitionPrefix,
692+
BlobDigests: []*repb.Digest{runnerBinDigest, cliDigest},
693+
DigestFunction: repb.DigestFunction_BLAKE3,
694+
}
695+
findResp, err := casClient.FindMissingBlobs(ctx, findReq)
696+
require.NoError(t, err)
697+
require.Len(t, findResp.GetMissingBlobDigests(), 2)
698+
699+
runRemoteBazelInSeparateProcess(t, repoDir, bbServer.GRPCAddress(),
700+
"--os=linux",
701+
"--arch=amd64",
702+
"--script=echo HELLO!",
703+
fmt.Sprintf("--remote_header=x-buildbuddy-api-key=%s", env.APIKey1),
704+
)
705+
706+
// Verify invocation logs.
707+
bbClient := env.GetBuildBuddyServiceClient()
708+
reqCtx := &ctxpb.RequestContext{
709+
UserId: &uidpb.UserId{Id: env.UserID1},
710+
GroupId: env.GroupID1,
711+
}
712+
searchRsp, err := bbClient.SearchInvocation(ctx, &inpb.SearchInvocationRequest{
713+
RequestContext: reqCtx,
714+
Query: &inpb.InvocationQuery{GroupId: env.GroupID1},
715+
})
716+
require.NoError(t, err)
717+
require.Equal(t, 1, len(searchRsp.GetInvocation()))
718+
719+
logResp, err := bbClient.GetEventLogChunk(ctx, &elpb.GetEventLogChunkRequest{
720+
InvocationId: searchRsp.Invocation[0].InvocationId,
721+
MinLines: math.MaxInt32,
722+
})
723+
require.NoError(t, err)
724+
require.Contains(t, string(logResp.GetBuffer()), "HELLO!")
725+
726+
// Verify that the binaries were uploaded to the cache.
727+
findResp, err = casClient.FindMissingBlobs(ctx, findReq)
728+
require.NoError(t, err)
729+
require.Empty(t, findResp.GetMissingBlobDigests())
730+
}

enterprise/server/test/integration/workflow/workflow_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ func makeRepo(t *testing.T, contents map[string]string) (string, string) {
107107
}
108108

109109
func setup(t *testing.T, gp interfaces.GitProvider) (*rbetest.Env, interfaces.WorkflowService) {
110+
// Avoid uploading embedded CI runner binaries to the in-memory cache in
111+
// each test because it's very slow. The executor will add these binaries locally instead.
112+
flags.Set(t, "remote_execution.init_ci_runner_from_cache", false)
113+
110114
env := rbetest.NewRBETestEnv(t)
111115
var workflowService interfaces.WorkflowService
112116

enterprise/server/util/ci_runner_util/ci_runner_util.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const CLIBinaryName = "bb"
2525
var (
2626
RecycledCIRunnerMaxWait = flag.Duration("remote_execution.ci_runner_recycling_max_wait", 3*time.Second, "Max duration that a ci_runner task should wait for a warm runner before running on a potentially cold runner.")
2727
CIRunnerDefaultTimeout = flag.Duration("remote_execution.ci_runner_default_timeout", 8*time.Hour, "Default timeout applied to all ci runners.")
28+
InitCIRunnerFromCache = flag.Bool("remote_execution.init_ci_runner_from_cache", true, "Whether the apps should upload ci_runner binaries to the cache so executors can fetch the latest versions without upgrading.")
2829
)
2930

3031
// CanInitFromCache The apps are built for linux/amd64. If the ci_runner will run on linux/amd64
@@ -38,7 +39,9 @@ var (
3839
// a ci_runner task. This will guarantee the binary is built for the correct os/arch,
3940
// but it will not update automatically when the apps are upgraded.
4041
func CanInitFromCache(os, arch string) bool {
41-
return (os == "" || os == platform.LinuxOperatingSystemName) && (arch == "" || arch == platform.AMD64ArchitectureName)
42+
return *InitCIRunnerFromCache &&
43+
(os == "" || os == platform.LinuxOperatingSystemName) &&
44+
(arch == "" || arch == platform.AMD64ArchitectureName)
4245
}
4346

4447
// UploadInputRoot If the ci_runner can be properly initialized from the cache,

enterprise/server/workflow/service/service_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ actions:
7373
)
7474

7575
func newTestEnv(t *testing.T) *testenv.TestEnv {
76+
// Avoid uploading embedded CI runner binaries to the in-memory cache in
77+
// each test because it's very slow. The executor will add these binaries locally instead.
78+
flags.Set(t, "remote_execution.init_ci_runner_from_cache", false)
79+
7680
flags.Set(t, "github.app.enabled", true)
7781
te := enterprise_testenv.New(t)
7882
enterprise_testauth.Configure(t, te)

0 commit comments

Comments
 (0)