Skip to content

Commit a2bde7a

Browse files
committed
bes.BuildEventServer WIP: gRPC listener prints TestResult test.xml paths
1 parent ceda219 commit a2bde7a

3 files changed

Lines changed: 143 additions & 18 deletions

File tree

go.mod

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module github.com/buildkite/test-engine-client
22

3-
go 1.21
3+
go 1.23.0
44

5-
toolchain go1.22.4
5+
toolchain go1.24.0
66

77
require (
88
github.com/buildkite/roko v1.3.1
@@ -11,19 +11,22 @@ require (
1111

1212
require (
1313
drjosh.dev/zzglob v0.4.0
14+
github.com/buildbarn/bb-portal v0.0.0-20250220144241-94f72e8e190c
1415
github.com/google/uuid v1.6.0
1516
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
1617
github.com/olekukonko/tablewriter v0.0.5
1718
github.com/pact-foundation/pact-go/v2 v2.0.10
18-
golang.org/x/net v0.33.0
19+
golang.org/x/net v0.35.0
1920
golang.org/x/sys v0.30.0
21+
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb
22+
google.golang.org/grpc v1.70.0
23+
google.golang.org/protobuf v1.36.5
2024
)
2125

2226
require (
2327
github.com/hashicorp/logutils v1.0.0 // indirect
2428
github.com/mattn/go-runewidth v0.0.9 // indirect
25-
golang.org/x/text v0.21.0 // indirect
26-
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
27-
google.golang.org/grpc v1.67.3 // indirect
28-
google.golang.org/protobuf v1.36.3 // indirect
29+
golang.org/x/text v0.22.0 // indirect
30+
google.golang.org/genproto/googleapis/api v0.0.0-20250227231956-55c901821b1e // indirect
31+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e // indirect
2932
)

go.sum

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
drjosh.dev/zzglob v0.4.0 h1:gOb46aIHyHG8BlYpvZZM4dqR2dpsbKtI82IbYVAYIj4=
22
drjosh.dev/zzglob v0.4.0/go.mod h1:c3V3WPyfG+81h/bNOalEaba0jEQl16i9efSAmWOeOw8=
3+
github.com/buildbarn/bb-portal v0.0.0-20250220144241-94f72e8e190c h1:qLnyVD+ND7Ll3p9Lw0Z7Vk5HirKRZcBRJzHELYe5Z84=
4+
github.com/buildbarn/bb-portal v0.0.0-20250220144241-94f72e8e190c/go.mod h1:GHZ5lGzUtz9LQ2oHt8EweXn0zS8t2sCD9bNBw9R9s8E=
35
github.com/buildkite/roko v1.3.1 h1:t7K30ceLLYn6k7hQP4oq1c7dVlhgD5nRcuSRDEEnY1s=
46
github.com/buildkite/roko v1.3.1/go.mod h1:23R9e6nHxgedznkwwfmqZ6+0VJZJZ2Sg/uVcp2cP46I=
57
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
68
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9+
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
10+
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
11+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
12+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
13+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
14+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
715
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
816
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
917
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -22,18 +30,32 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
2230
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2331
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
2432
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
25-
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
26-
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
33+
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
34+
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
35+
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
36+
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
37+
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
38+
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
39+
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
40+
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
41+
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
42+
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
43+
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
44+
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
2745
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
2846
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
29-
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
30-
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
31-
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
32-
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
33-
google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8=
34-
google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s=
35-
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
36-
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
47+
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
48+
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
49+
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
50+
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
51+
google.golang.org/genproto/googleapis/api v0.0.0-20250227231956-55c901821b1e h1:nsxey/MfoGzYNduN0NN/+hqP9iiCIYsrVbXb/8hjFM8=
52+
google.golang.org/genproto/googleapis/api v0.0.0-20250227231956-55c901821b1e/go.mod h1:Xsh8gBVxGCcbV8ZeTB9wI5XPyZ5RvC6V3CTeeplHbiA=
53+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e h1:YA5lmSs3zc/5w+xsRcHqpETkaYyK63ivEPzNTcUUlSA=
54+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
55+
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
56+
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
57+
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
58+
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
3759
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
3860
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3961
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=

internal/bes/bes.go

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
package bes
22

33
import (
4+
"context"
45
"fmt"
6+
"io"
7+
"log/slog"
58
"net"
9+
10+
bb_bes "github.com/buildbarn/bb-portal/third_party/bazel/gen/bes"
11+
12+
"google.golang.org/genproto/googleapis/devtools/build/v1"
13+
"google.golang.org/grpc"
14+
"google.golang.org/grpc/codes"
15+
"google.golang.org/grpc/status"
16+
"google.golang.org/protobuf/encoding/protojson"
17+
"google.golang.org/protobuf/types/known/emptypb"
618
)
719

820
var host = "127.0.0.1"
921
var port = 60242 // 0 for OS-allocated
1022

23+
type BuildEventServer struct {
24+
}
25+
1126
func Listen() error {
1227
addr := fmt.Sprintf("%s:%d", host, port)
1328
listener, err := net.Listen("tcp", addr)
@@ -16,7 +31,92 @@ func Listen() error {
1631
}
1732
fmt.Println("Bazel BES listener: grpc://" + listener.Addr().String())
1833

19-
// TODO
34+
opts := []grpc.ServerOption{}
35+
grpcServer := grpc.NewServer(opts...)
36+
37+
build.RegisterPublishBuildEventServer(grpcServer, newServer())
38+
grpcServer.Serve(listener)
2039

2140
return nil
2241
}
42+
43+
func newServer() build.PublishBuildEventServer {
44+
return BuildEventServer{}
45+
}
46+
47+
// PublishLifecycleEvent handles life cycle events.
48+
func (s BuildEventServer) PublishLifecycleEvent(ctx context.Context, request *build.PublishLifecycleEventRequest) (*emptypb.Empty, error) {
49+
slog.DebugContext(ctx, "Received event", "event", protojson.Format(request.BuildEvent.GetEvent()))
50+
return &emptypb.Empty{}, nil
51+
}
52+
53+
// PublishBuildToolEventStream handles a build tool event stream.
54+
// bktec thanks buildbarn/bb-portal for the basis of this :D
55+
func (s BuildEventServer) PublishBuildToolEventStream(stream build.PublishBuildEvent_PublishBuildToolEventStreamServer) error {
56+
ctx := stream.Context()
57+
58+
slog.InfoContext(ctx, "Stream started")
59+
60+
for {
61+
req, err := stream.Recv()
62+
if err == io.EOF {
63+
slog.InfoContext(ctx, "Stream finished")
64+
return nil
65+
} else if err != nil {
66+
slog.ErrorContext(ctx, "Recv failed", "err", err)
67+
return err
68+
}
69+
70+
streamID := req.OrderedBuildEvent.GetStreamId()
71+
seq := req.OrderedBuildEvent.GetSequenceNumber()
72+
73+
event := req.GetOrderedBuildEvent().GetEvent()
74+
slog.DebugContext(ctx, "stream event", "seq", seq, "event", event)
75+
76+
if event.GetBazelEvent() == nil {
77+
slog.DebugContext(ctx, "not a bazel event", seq, seq)
78+
continue
79+
}
80+
81+
var bazelEvent bb_bes.BuildEvent
82+
if err = event.GetBazelEvent().UnmarshalTo(&bazelEvent); err != nil {
83+
//return fmt.Errorf("unmarshaling bazel event: %w", err)
84+
slog.InfoContext(ctx, "error unmarshalling")
85+
}
86+
87+
// slog.InfoContext(ctx, "unmarshalled bazel event", "event", &bazelEvent)
88+
89+
payload := bazelEvent.GetPayload()
90+
if testResult, ok := payload.(*bb_bes.BuildEvent_TestResult); ok {
91+
r := testResult.TestResult
92+
files := []string{}
93+
for _, x := range r.GetTestActionOutput() {
94+
if x.GetName() == "test.xml" {
95+
files = append(files, x.GetUri())
96+
}
97+
}
98+
slog.InfoContext(ctx, "TestResult",
99+
"status", r.GetStatus(),
100+
"cached", r.GetCachedLocally(),
101+
"dur", r.GetTestAttemptDuration().AsDuration().String(),
102+
"files", files,
103+
)
104+
}
105+
106+
// ack
107+
ack := &build.PublishBuildToolEventStreamResponse{StreamId: streamID, SequenceNumber: seq}
108+
if err := stream.Send(ack); err != nil {
109+
grpcErr := status.Convert(err)
110+
if grpcErr.Code() == codes.Unavailable &&
111+
grpcErr.Message() == "transport is closing" {
112+
return nil
113+
}
114+
115+
slog.ErrorContext(ctx, "ack failed",
116+
"err", err,
117+
"stream", streamID,
118+
"seq", seq,
119+
)
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)