Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/echo/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
common --enable_bzlmod --experimental_proto_descriptor_sets_include_source_info
43 changes: 43 additions & 0 deletions examples/echo/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright 2021-2025 Buf Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

load("@gazelle//:def.bzl", "gazelle", "gazelle_binary")
load("@rules_buf//buf:defs.bzl", "buf_format")

exports_files(
["buf.yaml"],
visibility = ["//visibility:public"],
)

gazelle(
name = "gazelle",
gazelle = ":gazelle-buf",
)

# gazelle:prefix echo
# gazelle:go_generate_proto false
gazelle_binary(
name = "gazelle-buf",
languages = [
"@gazelle//language/proto", # Built-in rule from gazelle for Protos.
# Any languages that depend on Gazelle's proto plugin must come after it.
"@rules_buf//gazelle/buf:buf", # Loads the Buf extension
"@gazelle//language/go",
],
visibility = ["//visibility:public"],
)

buf_format(
name = "buf_format",
)
49 changes: 49 additions & 0 deletions examples/echo/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright 2021-2025 Buf Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"Bazel dependencies"

bazel_dep(name = "rules_buf", version = "0.0.0", dev_dependency = True)
bazel_dep(name = "gazelle", version = "0.36.0", dev_dependency = True)
bazel_dep(name = "protobuf", version = "29.1", repo_name = "com_google_protobuf")
bazel_dep(name = "rules_proto", version = "7.0.2")
bazel_dep(name = "rules_go", version = "0.54.1")

local_path_override(
module_name = "rules_buf",
path = "../..",
)

go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

go_sdk.from_file(go_mod = "//:go.mod")

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")


use_repo(
go_deps,
"org_golang_google_protobuf",
"com_connectrpc_connect",
"org_golang_x_net"
)

buf = use_extension("@rules_buf//buf:extensions.bzl", "buf")

# Override the default version of buf
buf.toolchains(version = "v1.47.2", sha256 = "1b37b75dc0a777a0cba17fa2604bc9906e55bb4c578823d8b7a8fe3fc9fe4439")

# Allow people to use `bazel run @rules_buf_toolchains//:buf -- --version`
use_repo(buf, "rules_buf_toolchains")
261 changes: 261 additions & 0 deletions examples/echo/MODULE.bazel.lock

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions examples/echo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Echo

A minimal but complete example of using buf with bazel via rules_buf.


## Generation

We generate the files using `buf` directly, this lets us use remote plugins and managed mode. We can do so from within bazel:

```sh
bazel run @rules_buf_toolchains//:buf -- generate
```

Everytime we generate the files we can run, gazelle to auto generate the BUILD files:

```sh
bazel run //:gazelle
```

This will generate the language rules based on the configured gazelle plugins.

## Running the server

The server can be started using `bazel run //cmd/echo:echo` and we can use `buf curl` to test:

```sh
buf curl http://localhost:8080/echo.v1.EchoService/Echo --schema
```
1 change: 1 addition & 0 deletions examples/echo/WORKSPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Marker that this folder is the root of a Bazel workspace
16 changes: 16 additions & 0 deletions examples/echo/buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: v2
clean: true
managed:
enabled: true
override:
- file_option: go_package_prefix
value: echo/gen
plugins:
- remote: buf.build/protocolbuffers/go:v1.36.6
out: gen
opt:
- paths=source_relative
- remote: buf.build/connectrpc/go:v1.18.1
out: gen
opt:
- paths=source_relative
9 changes: 9 additions & 0 deletions examples/echo/buf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: v2
modules:
- path: proto
lint:
use:
- STANDARD
breaking:
use:
- FILE
21 changes: 21 additions & 0 deletions examples/echo/cmd/echo/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("@rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "echo_lib",
srcs = ["main.go"],
importpath = "echo/cmd/echo",
visibility = ["//visibility:private"],
deps = [
"//gen/echo/v1:echo",
"//gen/echo/v1/echov1connect",
"@com_connectrpc_connect//:connect",
"@org_golang_x_net//http2",
"@org_golang_x_net//http2/h2c",
],
)

go_binary(
name = "echo",
embed = [":echo_lib"],
visibility = ["//visibility:public"],
)
64 changes: 64 additions & 0 deletions examples/echo/cmd/echo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package main

import (
"context"
"echo/gen/echo/v1"
"echo/gen/echo/v1/echov1connect"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"

"connectrpc.com/connect"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)

var _ echov1connect.EchoServiceHandler = (*echoServer)(nil)

type echoServer struct {
}

// Echo implements echov1connect.EchoServiceHandler.
func (e *echoServer) Echo(ctx context.Context, req *connect.Request[echov1.EchoRequest]) (*connect.Response[echov1.EchoResponse], error) {
return connect.NewResponse(&echov1.EchoResponse{
Message: req.Msg.GetMessage(),
}), nil
}

func main() {
mux := http.NewServeMux()
mux.Handle(echov1connect.NewEchoServiceHandler(&echoServer{}))
addr := "localhost:8080"
if port := os.Getenv("PORT"); port != "" {
addr = ":" + port
}
srv := &http.Server{
Addr: addr,
Handler: h2c.NewHandler(
mux,
&http2.Server{},
),
ReadHeaderTimeout: time.Second,
ReadTimeout: 5 * time.Minute,
WriteTimeout: 5 * time.Minute,
MaxHeaderBytes: 8 * 1024, // 8KiB
}
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
go func() {
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("HTTP listen and serve: %v", err)
}
}()

<-signals
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("HTTP shutdown: %v", err) //nolint:gocritic
}
}
12 changes: 12 additions & 0 deletions examples/echo/gen/echo/v1/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
load("@rules_go//go:def.bzl", "go_library")

go_library(
name = "echo",
srcs = ["echo.pb.go"],
importpath = "echo/gen/echo/v1",
visibility = ["//visibility:public"],
deps = [
"@org_golang_google_protobuf//reflect/protoreflect",
"@org_golang_google_protobuf//runtime/protoimpl",
],
)
Loading