From 69db1c26b4fe4474ab4c9df1c9701efac8bedde1 Mon Sep 17 00:00:00 2001 From: JulienDarve <86800349+JulienDarve@users.noreply.github.com> Date: Fri, 11 Sep 2026 01:28:52 -0700 Subject: [PATCH] [CI/Build][Rust Frontend] Publish vllm-proto on crates.io (#56365) Co-authored-by: OpenAI Codex Co-authored-by: Bugen Zhao Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Signed-off-by: Julien Darve Signed-off-by: Bugen Zhao --- .github/workflows/proto-crate.yml | 70 +++++++++++++++++++++++++++++ .pre-commit-config.yaml | 4 +- rust/Cargo.lock | 17 +++++-- rust/Cargo.toml | 2 + rust/proto/Cargo.toml | 22 +++++++++ rust/proto/README.md | 50 +++++++++++++++++++++ rust/{src/server => proto}/build.rs | 2 +- rust/proto/src/lib.rs | 6 +++ rust/src/server/Cargo.toml | 7 +-- rust/src/server/src/grpc/mod.rs | 4 +- 10 files changed, 168 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/proto-crate.yml create mode 100644 rust/proto/Cargo.toml rename rust/{src/server => proto}/build.rs (88%) create mode 100644 rust/proto/src/lib.rs diff --git a/.github/workflows/proto-crate.yml b/.github/workflows/proto-crate.yml new file mode 100644 index 0000000000..43be5c8c92 --- /dev/null +++ b/.github/workflows/proto-crate.yml @@ -0,0 +1,70 @@ +name: Rust proto crate + +on: + pull_request: + paths: + - "rust/proto/**" + - "rust/Cargo.toml" + - "rust/Cargo.lock" + - "rust-toolchain.toml" + - ".github/workflows/proto-crate.yml" + push: + tags: + - "proto-v*" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + semver: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: obi1kenobi/cargo-semver-checks-action@6b69fcf40e9b5fb17adeb57e4b6ecd020649a239 # v2 + with: + manifest-path: rust/proto/Cargo.toml + package: vllm-proto + + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - run: rustup show active-toolchain + - name: Check release version + if: github.event_name == 'push' + run: | + version=$(cargo metadata --manifest-path rust/Cargo.toml --no-deps --format-version 1 | + jq -er '.packages[] | select(.name == "vllm-proto") | .version') + if [[ "$GITHUB_REF_NAME" != "proto-v$version" ]]; then + echo "Tag $GITHUB_REF_NAME does not match vllm-proto version $version" >&2 + exit 1 + fi + - name: Verify package + run: cargo publish --manifest-path rust/proto/Cargo.toml --locked --dry-run + + publish: + needs: [check, semver] + if: github.repository == 'vllm-project/vllm' && github.event_name == 'push' + runs-on: ubuntu-latest + environment: crates-io + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.sha }} + - run: rustup show active-toolchain + - name: Verify package before authentication + run: cargo publish --manifest-path rust/proto/Cargo.toml --locked --dry-run + - uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5 + id: auth + - name: Publish + env: + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} + run: cargo publish --manifest-path rust/proto/Cargo.toml --locked diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0954c53cb2..d1d0e9e3d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -285,7 +285,7 @@ repos: pass_filenames: false require_serial: true stages: [pre-commit] # Only run locally as Buildkite will cover this - files: ^rust/(Cargo\.toml|src/.*/Cargo\.toml)$ + files: ^rust/(Cargo\.toml|proto/Cargo\.toml|src/.*/Cargo\.toml)$ - id: rust-cargo-sort name: Rust - Sort Cargo manifest sections entry: tools/pre_commit/rust-check.sh sort --workspace @@ -293,7 +293,7 @@ repos: pass_filenames: false require_serial: true stages: [pre-commit] # Only run locally as Buildkite will cover this - files: ^rust/(Cargo\.toml|src/.*/Cargo\.toml)$ + files: ^rust/(Cargo\.toml|proto/Cargo\.toml|src/.*/Cargo\.toml)$ - id: rust-cargo-fmt name: Rust - Format code entry: tools/pre_commit/rust-check.sh fmt diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 7cd52d6b1c..bf19fd3225 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -5938,6 +5938,18 @@ dependencies = [ "xgrammar-structural-tag", ] +[[package]] +name = "vllm-proto" +version = "0.1.0" +dependencies = [ + "prost", + "prost-types", + "protox", + "tonic", + "tonic-prost", + "tonic-prost-build", +] + [[package]] name = "vllm-server" version = "0.1.0" @@ -5960,9 +5972,7 @@ dependencies = [ "libc", "llm-multimodal", "openssl", - "prost", "prost-types", - "protox", "rmp-serde", "rmpv", "serde", @@ -5982,8 +5992,6 @@ dependencies = [ "tokio-util", "tonic", "tonic-health", - "tonic-prost", - "tonic-prost-build", "tower", "tower-http", "tracing", @@ -5997,6 +6005,7 @@ dependencies = [ "vllm-engine-core-client", "vllm-llm", "vllm-metrics", + "vllm-proto", "vllm-text", "vllm-tokenizer", "zeromq", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index a9421e7c4a..75104642c3 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "proto", "src/bench", "src/build-info", "src/chat", @@ -146,6 +147,7 @@ vllm-llm = { path = "src/llm" } vllm-managed-engine = { path = "src/managed-engine" } vllm-metrics = { path = "src/metrics" } vllm-parser = { path = "src/parser" } +vllm-proto = { version = "0.1.0", path = "proto" } vllm-server = { path = "src/server" } vllm-text = { path = "src/text" } vllm-tokenizer = { path = "src/tokenizer" } diff --git a/rust/proto/Cargo.toml b/rust/proto/Cargo.toml new file mode 100644 index 0000000000..3084c8c5b3 --- /dev/null +++ b/rust/proto/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "vllm-proto" +version = "0.1.0" +edition.workspace = true +license.workspace = true +description = "Protobuf messages and gRPC bindings for the vLLM Rust frontend" +repository = "https://github.com/vllm-project/vllm" +readme = "README.md" +include = ["*.proto", "src/**", "build.rs", "Cargo.toml", "README.md"] + +[dependencies] +prost.workspace = true +prost-types.workspace = true +tonic.workspace = true +tonic-prost.workspace = true + +[build-dependencies] +protox.workspace = true +tonic-prost-build.workspace = true + +[lints] +workspace = true diff --git a/rust/proto/README.md b/rust/proto/README.md index a9960f3bb8..3c5dbe0d3a 100644 --- a/rust/proto/README.md +++ b/rust/proto/README.md @@ -10,3 +10,53 @@ The schema is published to `buf.build/vllm-project/vllm`: - Buf commits and generated SDK versions are immutable and can be pinned by consumers. 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. + +## Rust crate + +`vllm-proto` exposes the Prost message types and Tonic client and server modules for both APIs: + +```toml +[dependencies] +vllm-proto = "0.1" +``` + +For example, import `vllm_proto::inference_client::InferenceClient` or +`vllm_proto::control_client::ControlClient`. The vLLM frontend uses this same crate. +The package includes the canonical `.proto` files and generates bindings during +compilation using `protox` and `tonic-prost-build`. Consumers do not need Buf +credentials, the vLLM checkout, or a separately installed `protoc`. + +### Versioning and releases + +The crate has its own version in `Cargo.toml`, independent of the vLLM release +number and the other Rust workspace crates. Release it when changes to the +schema, generated Rust API, or dependencies require a new version. Review both +Rust API and protobuf wire compatibility when choosing the version bump; +a wire-compatible schema addition can still break Rust callers. + +On pull requests and releases, `cargo-semver-checks` compares the crate with its +latest published version. Include any required version bump in the protocol +change PR. This check becomes available after the first manual publication. + +1. Update the crate version and the `vllm-proto` workspace dependency together, + and update `rust/Cargo.lock`. +2. Run `cargo publish --manifest-path rust/proto/Cargo.toml --locked --dry-run` + and the frontend gRPC tests. Record the tested vLLM releases or revisions in + the release notes; matching crate versions alone do not establish runtime compatibility. +3. After the change merges, create a `proto-v` tag on that commit. + The `proto-crate.yml` workflow checks that the tag matches the crate version, + verifies the package, and publishes it to crates.io. + +Use `proto-v*` tags so they do not trigger Buf's `v*` release workflow. There is +no scheduled crate publication. Pull requests and manual workflow runs only +verify packaging, including on forks. Retry a failed release by rerunning its +tag workflow; crates.io versions cannot be overwritten. + +### Publisher setup + +A vLLM maintainer must publish the first version and establish the crate's owners. +For subsequent releases, configure [crates.io Trusted Publishing](https://crates.io/docs/trusted-publishing) +for repository `vllm-project/vllm`, workflow `proto-crate.yml`, and environment +`crates-io`. Configure that GitHub environment to allow `proto-v*` release tags. +Only tag pushes in the upstream repository can publish; forks do not obtain +publishing credentials. diff --git a/rust/src/server/build.rs b/rust/proto/build.rs similarity index 88% rename from rust/src/server/build.rs rename to rust/proto/build.rs index 1a2ba8a6b0..27cae50772 100644 --- a/rust/src/server/build.rs +++ b/rust/proto/build.rs @@ -3,7 +3,7 @@ fn main() -> Result<(), Box> { let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let proto_dir = std::path::PathBuf::from(format!("{manifest_dir}/../../proto")); + let proto_dir = std::path::PathBuf::from(manifest_dir); let protos = [ proto_dir.join("control.proto"), proto_dir.join("inference.proto"), diff --git a/rust/proto/src/lib.rs b/rust/proto/src/lib.rs new file mode 100644 index 0000000000..d4d44ea099 --- /dev/null +++ b/rust/proto/src/lib.rs @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright contributors to the vLLM project + +//! Protobuf messages and gRPC clients and servers for vLLM's Inference and Control APIs. + +tonic::include_proto!("vllm"); diff --git a/rust/src/server/Cargo.toml b/rust/src/server/Cargo.toml index 6f5e95e93f..e4d12bc96b 100644 --- a/rust/src/server/Cargo.toml +++ b/rust/src/server/Cargo.toml @@ -19,7 +19,6 @@ itertools.workspace = true libc.workspace = true llm-multimodal.workspace = true openssl.workspace = true -prost.workspace = true prost-types.workspace = true rmpv.workspace = true serde.workspace = true @@ -37,7 +36,6 @@ tokio-stream.workspace = true tokio-util.workspace = true tonic.workspace = true tonic-health.workspace = true -tonic-prost.workspace = true tower.workspace = true tower-http.workspace = true tracing.workspace = true @@ -51,12 +49,9 @@ vllm-chat.workspace = true vllm-engine-core-client.workspace = true vllm-llm.workspace = true vllm-metrics.workspace = true +vllm-proto.workspace = true vllm-text.workspace = true -[build-dependencies] -protox.workspace = true -tonic-prost-build.workspace = true - [dev-dependencies] anyhow.workspace = true async-openai = { workspace = true, features = ["full"] } diff --git a/rust/src/server/src/grpc/mod.rs b/rust/src/server/src/grpc/mod.rs index 06c7c9259e..3c96afd9b8 100644 --- a/rust/src/server/src/grpc/mod.rs +++ b/rust/src/server/src/grpc/mod.rs @@ -9,9 +9,7 @@ mod health; mod inference; /// Generated protobuf/gRPC types for the `vllm` package. -pub mod pb { - tonic::include_proto!("vllm"); -} +pub use vllm_proto as pb; pub(crate) use control::ControlGrpcService; pub use control::ControlServiceImpl;