[CI/Build][Rust Frontend] Publish vllm-proto on crates.io (#56365)

Co-authored-by: OpenAI Codex <noreply@openai.com> Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Signed-off-by: Julien Darve <jdarve@NVIDIA.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>

JulienDarve committed Sep 11, 2026 at 01:28 UTC 69db1c26b4fe4474ab4c9df1c9701efac8bedde1
10 files changed +168 -16
.github/workflows/proto-crate.yml new
+70
@@ -0,0 +1,70 @@
1 +name: Rust proto crate
2 +
3 +on:
4 + pull_request:
5 + paths:
6 + - "rust/proto/**"
7 + - "rust/Cargo.toml"
8 + - "rust/Cargo.lock"
9 + - "rust-toolchain.toml"
10 + - ".github/workflows/proto-crate.yml"
11 + push:
12 + tags:
13 + - "proto-v*"
14 + workflow_dispatch:
15 +
16 +permissions:
17 + contents: read
18 +
19 +concurrency:
20 + group: ${{ github.workflow }}-${{ github.ref }}
21 + cancel-in-progress: ${{ github.event_name == 'pull_request' }}
22 +
23 +jobs:
24 + semver:
25 + runs-on: ubuntu-latest
26 + steps:
27 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
28 + - uses: obi1kenobi/cargo-semver-checks-action@6b69fcf40e9b5fb17adeb57e4b6ecd020649a239 # v2
29 + with:
30 + manifest-path: rust/proto/Cargo.toml
31 + package: vllm-proto
32 +
33 + check:
34 + runs-on: ubuntu-latest
35 + steps:
36 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
37 + - run: rustup show active-toolchain
38 + - name: Check release version
39 + if: github.event_name == 'push'
40 + run: |
41 + version=$(cargo metadata --manifest-path rust/Cargo.toml --no-deps --format-version 1 |
42 + jq -er '.packages[] | select(.name == "vllm-proto") | .version')
43 + if [[ "$GITHUB_REF_NAME" != "proto-v$version" ]]; then
44 + echo "Tag $GITHUB_REF_NAME does not match vllm-proto version $version" >&2
45 + exit 1
46 + fi
47 + - name: Verify package
48 + run: cargo publish --manifest-path rust/proto/Cargo.toml --locked --dry-run
49 +
50 + publish:
51 + needs: [check, semver]
52 + if: github.repository == 'vllm-project/vllm' && github.event_name == 'push'
53 + runs-on: ubuntu-latest
54 + environment: crates-io
55 + permissions:
56 + contents: read
57 + id-token: write
58 + steps:
59 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
60 + with:
61 + ref: ${{ github.sha }}
62 + - run: rustup show active-toolchain
63 + - name: Verify package before authentication
64 + run: cargo publish --manifest-path rust/proto/Cargo.toml --locked --dry-run
65 + - uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5
66 + id: auth
67 + - name: Publish
68 + env:
69 + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
70 + run: cargo publish --manifest-path rust/proto/Cargo.toml --locked
.pre-commit-config.yaml
+2 -2
@@ -285,7 +285,7 @@ repos:
285 pass_filenames: false
286 require_serial: true
287 stages: [pre-commit] # Only run locally as Buildkite will cover this
288 - files: ^rust/(Cargo\.toml|src/.*/Cargo\.toml)$
288 + files: ^rust/(Cargo\.toml|proto/Cargo\.toml|src/.*/Cargo\.toml)$
289 - id: rust-cargo-sort
290 name: Rust - Sort Cargo manifest sections
291 entry: tools/pre_commit/rust-check.sh sort --workspace
@@ -293,7 +293,7 @@ repos:
293 pass_filenames: false
294 require_serial: true
295 stages: [pre-commit] # Only run locally as Buildkite will cover this
296 - files: ^rust/(Cargo\.toml|src/.*/Cargo\.toml)$
296 + files: ^rust/(Cargo\.toml|proto/Cargo\.toml|src/.*/Cargo\.toml)$
297 - id: rust-cargo-fmt
298 name: Rust - Format code
299 entry: tools/pre_commit/rust-check.sh fmt
rust/Cargo.lock
+13 -4
@@ -5938,6 +5938,18 @@ dependencies = [
5938 "xgrammar-structural-tag",
5939 ]
5940
5941 +[[package]]
5942 +name = "vllm-proto"
5943 +version = "0.1.0"
5944 +dependencies = [
5945 + "prost",
5946 + "prost-types",
5947 + "protox",
5948 + "tonic",
5949 + "tonic-prost",
5950 + "tonic-prost-build",
5951 +]
5952 +
5953 [[package]]
5954 name = "vllm-server"
5955 version = "0.1.0"
@@ -5960,9 +5972,7 @@ dependencies = [
5972 "libc",
5973 "llm-multimodal",
5974 "openssl",
5963 - "prost",
5975 "prost-types",
5965 - "protox",
5976 "rmp-serde",
5977 "rmpv",
5978 "serde",
@@ -5982,8 +5992,6 @@ dependencies = [
5992 "tokio-util",
5993 "tonic",
5994 "tonic-health",
5985 - "tonic-prost",
5986 - "tonic-prost-build",
5995 "tower",
5996 "tower-http",
5997 "tracing",
@@ -5997,6 +6005,7 @@ dependencies = [
6005 "vllm-engine-core-client",
6006 "vllm-llm",
6007 "vllm-metrics",
6008 + "vllm-proto",
6009 "vllm-text",
6010 "vllm-tokenizer",
6011 "zeromq",
rust/Cargo.toml
+2
@@ -1,5 +1,6 @@
1 [workspace]
2 members = [
3 + "proto",
4 "src/bench",
5 "src/build-info",
6 "src/chat",
@@ -146,6 +147,7 @@ vllm-llm = { path = "src/llm" }
147 vllm-managed-engine = { path = "src/managed-engine" }
148 vllm-metrics = { path = "src/metrics" }
149 vllm-parser = { path = "src/parser" }
150 +vllm-proto = { version = "0.1.0", path = "proto" }
151 vllm-server = { path = "src/server" }
152 vllm-text = { path = "src/text" }
153 vllm-tokenizer = { path = "src/tokenizer" }
rust/proto/Cargo.toml new
+22
@@ -0,0 +1,22 @@
1 +[package]
2 +name = "vllm-proto"
3 +version = "0.1.0"
4 +edition.workspace = true
5 +license.workspace = true
6 +description = "Protobuf messages and gRPC bindings for the vLLM Rust frontend"
7 +repository = "https://github.com/vllm-project/vllm"
8 +readme = "README.md"
9 +include = ["*.proto", "src/**", "build.rs", "Cargo.toml", "README.md"]
10 +
11 +[dependencies]
12 +prost.workspace = true
13 +prost-types.workspace = true
14 +tonic.workspace = true
15 +tonic-prost.workspace = true
16 +
17 +[build-dependencies]
18 +protox.workspace = true
19 +tonic-prost-build.workspace = true
20 +
21 +[lints]
22 +workspace = true
rust/proto/README.md
+50
@@ -10,3 +10,53 @@ The schema is published to `buf.build/vllm-project/vllm`:
10 - Buf commits and generated SDK versions are immutable and can be pinned by consumers.
11
12 Repository setup requires a `BUF_TOKEN` GitHub Actions secret with permission to create and push the public Buf module. Register the Prost and Tonic generated SDKs for the `main` and `nightly` labels once so subsequent pushes generate them automatically.
13 +
14 +## Rust crate
15 +
16 +`vllm-proto` exposes the Prost message types and Tonic client and server modules for both APIs:
17 +
18 +```toml
19 +[dependencies]
20 +vllm-proto = "0.1"
21 +```
22 +
23 +For example, import `vllm_proto::inference_client::InferenceClient` or
24 +`vllm_proto::control_client::ControlClient`. The vLLM frontend uses this same crate.
25 +The package includes the canonical `.proto` files and generates bindings during
26 +compilation using `protox` and `tonic-prost-build`. Consumers do not need Buf
27 +credentials, the vLLM checkout, or a separately installed `protoc`.
28 +
29 +### Versioning and releases
30 +
31 +The crate has its own version in `Cargo.toml`, independent of the vLLM release
32 +number and the other Rust workspace crates. Release it when changes to the
33 +schema, generated Rust API, or dependencies require a new version. Review both
34 +Rust API and protobuf wire compatibility when choosing the version bump;
35 +a wire-compatible schema addition can still break Rust callers.
36 +
37 +On pull requests and releases, `cargo-semver-checks` compares the crate with its
38 +latest published version. Include any required version bump in the protocol
39 +change PR. This check becomes available after the first manual publication.
40 +
41 +1. Update the crate version and the `vllm-proto` workspace dependency together,
42 + and update `rust/Cargo.lock`.
43 +2. Run `cargo publish --manifest-path rust/proto/Cargo.toml --locked --dry-run`
44 + and the frontend gRPC tests. Record the tested vLLM releases or revisions in
45 + the release notes; matching crate versions alone do not establish runtime compatibility.
46 +3. After the change merges, create a `proto-v<version>` tag on that commit.
47 + The `proto-crate.yml` workflow checks that the tag matches the crate version,
48 + verifies the package, and publishes it to crates.io.
49 +
50 +Use `proto-v*` tags so they do not trigger Buf's `v*` release workflow. There is
51 +no scheduled crate publication. Pull requests and manual workflow runs only
52 +verify packaging, including on forks. Retry a failed release by rerunning its
53 +tag workflow; crates.io versions cannot be overwritten.
54 +
55 +### Publisher setup
56 +
57 +A vLLM maintainer must publish the first version and establish the crate's owners.
58 +For subsequent releases, configure [crates.io Trusted Publishing](https://crates.io/docs/trusted-publishing)
59 +for repository `vllm-project/vllm`, workflow `proto-crate.yml`, and environment
60 +`crates-io`. Configure that GitHub environment to allow `proto-v*` release tags.
61 +Only tag pushes in the upstream repository can publish; forks do not obtain
62 +publishing credentials.
rust/proto/build.rs renamed
+1 -1
@@ -3,7 +3,7 @@
3
4 fn main() -> Result<(), Box<dyn std::error::Error>> {
5 let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
6 - let proto_dir = std::path::PathBuf::from(format!("{manifest_dir}/../../proto"));
6 + let proto_dir = std::path::PathBuf::from(manifest_dir);
7 let protos = [
8 proto_dir.join("control.proto"),
9 proto_dir.join("inference.proto"),
rust/proto/src/lib.rs new
+6
@@ -0,0 +1,6 @@
1 +// SPDX-License-Identifier: Apache-2.0
2 +// SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 +
4 +//! Protobuf messages and gRPC clients and servers for vLLM's Inference and Control APIs.
5 +
6 +tonic::include_proto!("vllm");
rust/src/server/Cargo.toml
+1 -6
@@ -19,7 +19,6 @@ itertools.workspace = true
19 libc.workspace = true
20 llm-multimodal.workspace = true
21 openssl.workspace = true
22 -prost.workspace = true
22 prost-types.workspace = true
23 rmpv.workspace = true
24 serde.workspace = true
@@ -37,7 +36,6 @@ tokio-stream.workspace = true
36 tokio-util.workspace = true
37 tonic.workspace = true
38 tonic-health.workspace = true
40 -tonic-prost.workspace = true
39 tower.workspace = true
40 tower-http.workspace = true
41 tracing.workspace = true
@@ -51,12 +49,9 @@ vllm-chat.workspace = true
49 vllm-engine-core-client.workspace = true
50 vllm-llm.workspace = true
51 vllm-metrics.workspace = true
52 +vllm-proto.workspace = true
53 vllm-text.workspace = true
54
56 -[build-dependencies]
57 -protox.workspace = true
58 -tonic-prost-build.workspace = true
59 -
55 [dev-dependencies]
56 anyhow.workspace = true
57 async-openai = { workspace = true, features = ["full"] }
rust/src/server/src/grpc/mod.rs
+1 -3
@@ -9,9 +9,7 @@ mod health;
9 mod inference;
10
11 /// Generated protobuf/gRPC types for the `vllm` package.
12 -pub mod pb {
13 - tonic::include_proto!("vllm");
14 -}
12 +pub use vllm_proto as pb;
13
14 pub(crate) use control::ControlGrpcService;
15 pub use control::ControlServiceImpl;