Skip to content

Commit edf4d2f

Browse files
feat(client): allow usage of protox instead of system protoc (#1590)
1 parent e6dc63f commit edf4d2f

8 files changed

Lines changed: 51 additions & 21 deletions

File tree

.github/workflows/per-pr.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ jobs:
3232
- run: cargo test-lint
3333
- run: cargo check
3434
- run: cargo check --features experimental
35+
- name: Check vendored proto compilation
36+
run: cargo check --features temporalio-client/vendored-protox
37+
env:
38+
PROTOC: /does/not/exist
39+
CARGO_TARGET_DIR: /tmp/vendored-protox-target
3540
- run: git diff --exit-code
3641

3742
test:

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ relevant information.
3838
`temporalio-sdk`, and Rust 1.88 for the other crates.
3939

4040
### Added
41+
* `temporalio-client` now provides a `vendored-protox` feature for compiling protobuf definitions
42+
with `protox`, allowing client and Rust SDK builds without an installed `protoc`.
4143
* `CancelExternalWorkflowError` and `workflow_interceptors::CancelExternalWorkflowResult`
4244
for use in interceptors.
4345
* `WorkflowContextKey` and context-value scopes provide replay-safe, workflow-run-owned context

crates/client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ telemetry = ["dep:opentelemetry"]
2424
core-based-sdk = []
2525
envconfig = ["temporalio-common/envconfig"]
2626
dynamic-tls = ["dep:rustls-native-certs"]
27+
vendored-protox = ["temporalio-common/vendored-protox"]
2728

2829
[dependencies]
2930
anyhow = "1.0"

crates/client/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ while let Some(result) = stream.next().await {
167167
APIs that are still under development require the `experimental` Cargo feature and may change or
168168
be removed before stabilization.
169169

170+
## Building Without `protoc`
171+
172+
Enable the `vendored-protox` Cargo feature to compile protobuf definitions with `protox`
173+
instead of a system `protoc` binary.
174+
170175
## Raw gRPC Access
171176

172177
For operations not covered by the high-level API, access the underlying gRPC service clients

crates/common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ envconfig = ["dep:toml", "dep:dirs"]
3737
serde_serialize = ["temporalio-common-wasm/serde_serialize", "temporalio-protos/serde_serialize"]
3838
core-telemetry-bridge = ["dep:ringbuf", "dep:futures-channel"]
3939
core-based-sdk = ["core-telemetry-bridge", "prometheus", "envconfig"]
40+
vendored-protox = ["temporalio-protos/vendored-protox"]
4041

4142
[dependencies]
4243
anyhow = "1.0"

crates/protos/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ links = "temporalio_protos"
1717
default = []
1818
serde_serialize = []
1919
grpc-clients = ["tonic/channel"]
20+
vendored-protox = ["dep:protox", "prost-types/vendored-protox"]
2021

2122
[dependencies]
2223
anyhow = "1.0"
@@ -34,9 +35,9 @@ pbjson = { workspace = true }
3435

3536
[build-dependencies]
3637
prost = { workspace = true }
37-
prost-types = "0.14"
3838
tonic-prost-build = { workspace = true }
3939
pbjson-build = { workspace = true }
40+
protox = { version = "0.9.1", optional = true }
4041

4142
[lints]
4243
workspace = true

crates/protos/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ that constructs a message with a struct literal, so minor releases may contain b
1313

1414
Most Rust SDK users should use [`temporalio-client`](https://crates.io/crates/temporalio-client) or
1515
[`temporalio-sdk`](https://crates.io/crates/temporalio-sdk) instead.
16+
17+
Enable the `vendored-protox` feature to compile the protobuf definitions with the pure-Rust
18+
`protox` implementation instead of requiring an installed `protoc` binary.

crates/protos/build.rs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
use std::{env, path::PathBuf};
2+
3+
#[cfg(feature = "vendored-protox")]
4+
use prost::Message;
25
use tonic_prost_build::Config;
36

47
static ALWAYS_SERDE: &str = "#[cfg_attr(not(feature = \"serde_serialize\"), \
@@ -50,6 +53,26 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
5053
let out = PathBuf::from(env::var("OUT_DIR").unwrap());
5154
let descriptor_file = out.join("descriptors.bin");
5255
println!("cargo:descriptor_path={}", descriptor_file.display());
56+
let protos = &[
57+
"./protos/local/temporal/sdk/core/core_interface.proto",
58+
"./protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto",
59+
"./protos/api_upstream/temporal/api/workflowservice/v1/service.proto",
60+
"./protos/api_upstream/temporal/api/nexusservices/workerservice/v1/request_response.proto",
61+
"./protos/api_upstream/temporal/api/operatorservice/v1/service.proto",
62+
"./protos/api_upstream/temporal/api/errordetails/v1/message.proto",
63+
"./protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto",
64+
"./protos/testsrv_upstream/temporal/api/testservice/v1/service.proto",
65+
"./protos/grpc/health/v1/health.proto",
66+
"./protos/google/rpc/status.proto",
67+
];
68+
let includes = &[
69+
"./protos/api_upstream",
70+
"./protos/api_cloud_upstream",
71+
"./protos/local",
72+
"./protos/testsrv_upstream",
73+
"./protos/grpc",
74+
"./protos",
75+
];
5376
let mut builder = tonic_prost_build::configure()
5477
// Workflow guests need message structs, while the native common crate enables this
5578
// feature to preserve the generated clients it re-exports today.
@@ -145,6 +168,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
145168
builder = builder.type_attribute(*prefix, SERDE_ATTR);
146169
}
147170

171+
#[cfg(feature = "vendored-protox")]
172+
{
173+
let descriptors = protox::compile(protos, includes)?;
174+
std::fs::write(&descriptor_file, descriptors.encode_to_vec())?;
175+
builder = builder.skip_protoc_run();
176+
}
177+
148178
builder
149179
.file_descriptor_set_path(&descriptor_file)
150180
.compile_with_config(
@@ -153,26 +183,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
153183
c.enable_type_names();
154184
c
155185
},
156-
&[
157-
"./protos/local/temporal/sdk/core/core_interface.proto",
158-
"./protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto",
159-
"./protos/api_upstream/temporal/api/workflowservice/v1/service.proto",
160-
"./protos/api_upstream/temporal/api/nexusservices/workerservice/v1/request_response.proto",
161-
"./protos/api_upstream/temporal/api/operatorservice/v1/service.proto",
162-
"./protos/api_upstream/temporal/api/errordetails/v1/message.proto",
163-
"./protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto",
164-
"./protos/testsrv_upstream/temporal/api/testservice/v1/service.proto",
165-
"./protos/grpc/health/v1/health.proto",
166-
"./protos/google/rpc/status.proto",
167-
],
168-
&[
169-
"./protos/api_upstream",
170-
"./protos/api_cloud_upstream",
171-
"./protos/local",
172-
"./protos/testsrv_upstream",
173-
"./protos/grpc",
174-
"./protos",
175-
],
186+
protos,
187+
includes,
176188
)?;
177189

178190
// TODO [rust-sdk-branch]: support normal JSON and proto JSON serialization

0 commit comments

Comments
 (0)