Add anthropics/buffa plugin v0.5.2#2333
Conversation
|
I think we might want to make a top-level anthropics org for this, instead of under community - also re: connect-rust. |
Sure thing I'll redraft as part of updating to the new versions I'll likely release next week. |
c42c7b7 to
507d069
Compare
507d069 to
2f986f3
Compare
| @@ -0,0 +1,4 @@ | |||
| source: | |||
There was a problem hiding this comment.
I think there's supposed to be a crates section here? See the prost plugin as an ezample
There was a problem hiding this comment.
changed to crate ref instead of github ref 👍
2f986f3 to
8f27d26
Compare
There was a problem hiding this comment.
To ensure reproducible builds, we check in a checksum file of generated code using the plugin. This verifies e2e code generation is functional and also ensures that the codegen doesn't change across builds.
https://github.com/bufbuild/plugins/blob/main/CONTRIBUTING.md#creating-a-new-plugin
To create the files, run make test PLUGINS=anthropics/buffa:latest and check in the plugin.sum files created under tests/testdata/buf.build/anthropics/.
| @@ -0,0 +1,15 @@ | |||
| # syntax=docker/dockerfile:1.19 | |||
| FROM rust:1.91.1-alpine3.22 AS builder | |||
There was a problem hiding this comment.
We should update this branch to latest main then we can update this image to the latest base image:
| FROM rust:1.91.1-alpine3.22 AS builder | |
| FROM rust:1.95.0-alpine3.23@sha256:606fd313a0f49743ee2a7bd49a0914bab7deedb12791f3a846a34a4711db7ed2 AS builder |
| RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked --mount=type=cache,target=/root/target \ | ||
| cargo install protoc-gen-buffa --version 0.3.0 --locked --root /app | ||
|
|
||
| FROM gcr.io/distroless/static-debian12:latest@sha256:87bce11be0af225e4ca761c40babb06d6d559f5767fbf7dc3c47f0f1a466b92c AS base |
There was a problem hiding this comment.
| FROM gcr.io/distroless/static-debian12:latest@sha256:87bce11be0af225e4ca761c40babb06d6d559f5767fbf7dc3c47f0f1a466b92c AS base | |
| FROM gcr.io/distroless/static-debian13:latest@sha256:47b2d72ff90843eb8a768b5c2f89b40741843b639d065b9b937b07cd59b479c6 AS base |
Seems reasonable to me to enable both — since generated SDKs aren't configurable, I think including all of the features makes sense to me (users who want more control can fall back to local generation).
What would be most helpful here is actually if both buffa and connect-rust included the |
|
@stefanvanburen buffa has a plugin for local usage, protoc-gen-buffa-packaging, which produces a consolidated mod.rs separately from the core plugin. This was the structure that @bufdev wanted me to use because that plugin requires |
|
[claude code] We'll add a connect-rust will get the same opt and also emit Targeting v0.4.1 for both. I'll update these PRs once that's released. Separately: as far as I can tell |
@iainmcgin sounds good, thanks for your persistence with this, it's appreciated!
You're basically on-the-nose here, unfortunately: with basically every other package ecosystem, it's relatively straightforward to package up plugin output; Rust is a different story, and the BSR has some workarounds here to handle |
…73) Adds a `file_per_package` option to `CodeGenConfig` (and the `protoc-gen-buffa` CLI) that emits one `<dotted.package>.rs` per proto package instead of the default per-proto-file split. The single file inlines what the `<pkg>.mod.rs` stitcher would otherwise `include!`, producing the identical `__buffa::` module structure. ## Why BSR's cargo-SDK pipeline assembles `lib.rs` server-side by splitting each output filename on `.` and building a nested `pub mod` tree — the same convention prost's per-package output follows. Our default per-file output (`pet.v1.pet.rs`, `pet.v1.pet.__view.rs`, `pet.v1.mod.rs`, ...) would synthesize to garbage under that algorithm. With `file_per_package=true` set in the BSR plugin manifest's `registry.opts`, our output slots into the existing synthesis with no special-casing on Buf's side. See bufbuild/plugins#2333. This mode is correct under `strategy: directory` for `PACKAGE_DIRECTORY_MATCH`-clean modules (one directory == one package, so each invocation sees a complete package), so it does not introduce a `strategy: all` requirement. ## Implementation - `PackageSections` intermediate holds per-section `Vec<TokenStream>`s; `generate_package_mod` now consumes it uniformly. The per-file path builds sections from `include!` token streams; the per-package path inlines the content directly. Module structure is identical between modes. - `package_to_filename()` helper for `<pkg>.rs` naming. - `GeneratedFileKind::PackageMod` is reused for the single-file output. ## Deferred (Low review findings) - `OutputLayout` enum instead of `bool` — only one alternate layout exists; revisit if more emerge. - Unnamed-package output is `__buffa.rs`, which under BSR's synthesis would double-nest. Buf's `PACKAGE_DEFINED` lint (MINIMAL group) makes this a near-zero case for SDK gen, and it mirrors the existing per-file path's behavior.
8f27d26 to
f3c4492
Compare
|
[claude code] Updated to @stefanvanburen following up from the earlier discussion — |
|
Taking a look at the latest changes today. Will let you know if there are any further changes necessary to work with gen SDKs. |
f3c4492 to
f83ec94
Compare
|
[claude code] Superseded by #2334, which now contains both |
Adds the `protoc-gen-buffa` and `protoc-gen-connect-rust` plugins for Rust protobuf and ConnectRPC code generation, under the new top-level `anthropics` org as requested in earlier review. This PR contains both plugins, so it can land on its own. (It was originally stacked on #2333, which adds `anthropics/buffa` alone — #2333 is now superseded by this PR.) ## buffa [buffa](https://github.com/anthropics/buffa) is a zero-copy Rust Protobuf implementation with: - **Editions support** (2023/2024) and full proto2/proto3 coverage - **Zero-copy view types** - borrowed `&str`/`&[u8]` field access without owned allocation - **no_std + alloc** compatible - **Proto3 JSON mapping** with serde integration - **Conformance**: passes the protobuf conformance suite (5539 binary+JSON tests, 0 expected failures) Crates on crates.io: [`buffa`](https://crates.io/crates/buffa), [`buffa-types`](https://crates.io/crates/buffa-types), [`protoc-gen-buffa`](https://crates.io/crates/protoc-gen-buffa). `protoc-gen-buffa` generates message types. With `file_per_package=true` (set in `opts`), it emits **one `<dotted.package>.rs` file per proto package**: `foo/v1/bar.proto` and `foo/v1/baz.proto` both land in `foo.v1.rs`. No subdirectories, no `mod.rs`. This matches the prost/tonic filename convention the BSR Rust SDK `lib.rs` synthesis already understands. ## connect-rust [connect-rust](https://github.com/anthropics/connect-rust) is a Tower-based Rust implementation of the ConnectRPC protocol: - **Three protocols**: Connect, gRPC, gRPC-Web - same service impl handles all three - **Full conformance**: 3600 server tests, 2580/1454/2838 client tests across Connect/gRPC/gRPC-Web - **Zero-copy request handling** via buffa view types - `request.name` is a `&str` borrow into the decoded buffer - **Tower integration**: composes with axum, hyper, tower middleware Crates on crates.io: [`connectrpc`](https://crates.io/crates/connectrpc), [`connectrpc-codegen`](https://crates.io/crates/connectrpc-codegen), [`connectrpc-build`](https://crates.io/crates/connectrpc-build). `protoc-gen-connect-rust` emits **service stubs only** - server traits, typed clients, monomorphic dispatchers. Message types come from `buf.build/anthropics/buffa` (declared in `deps:`). Generated stubs reference message types via absolute Rust paths configured with `extern_path`. It also takes `file_per_package`, mirroring the `anthropics/buffa` opt. **Dockerfile note**: the `protoc-gen-connect-rust` binary is a `[[bin]]` target inside the `connectrpc-codegen` crate, so `cargo install connectrpc-codegen` is what produces it. ## extern_path handling `protoc-gen-connect-rust` needs an `extern_path=.=<rust_path>` (or shorthand `buffa_module=<rust_path>`) catch-all so it knows where the buffa-generated message types live. Per @stefanvanburen's review, `opts:` is left as just `[file_per_package]` — the BSR injects `extern_path` from the `deps:` chain at SDK build time using the same prost syntax as tonic. The standalone test harness has no dep chain, so this PR adds a `testOverrideOptions` entry passing a placeholder `extern_path=.=crate` — the same pattern `neoeinstein-prost-crate` (`no_features`) and `neoeinstein-tonic` (`no_include`) use to make their isolated test runs succeed without affecting production opts. `plugin.sum` files for both plugins (`eliza` and `petapis`) are checked in; `make test PLUGINS="anthropics/buffa anthropics/connect-rust"` passes.
Adds the
protoc-gen-buffaplugin for Rust protobuf code generation, under the new top-levelanthropicsorg as requested in earlier review.About buffa
buffa is a zero-copy Rust Protobuf implementation with:
&str/&[u8]field access without owned allocationCrates are on crates.io:
buffa,buffa-types,protoc-gen-buffa.Output convention
With
file_per_package=true(set inopts), the plugin emits one<dotted.package>.rsfile per proto package:foo/v1/bar.protoandfoo/v1/baz.protoboth land infoo.v1.rs. No subdirectories, nomod.rs. This matches the prost/tonic filename convention the BSR Rust SDKlib.rssynthesis already understands, so no special-casing should be required on the BSR side.plugin.sumfiles forelizaandpetapisare checked in (make test PLUGINS=anthropics/buffa).Related: #2334 (anthropics/connect-rust) declares this plugin as a dep, so this one needs to land first.