From f9b8e03bd7ee1d0edb441c94a93a350d5b06ed3b Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 5 Aug 2022 12:36:35 -0700 Subject: [PATCH] feat: update Tonic and Prost dependencies (#364) This branch updates the console crates' dependency on `tonic` to v0.8.0 and `prost` to 0.11.0. In addition, I've added a [`cargo xtask`][xtask] command for manually regenerating the generated protobuf bindings. This is necessary as the current approach, regenerating the bindings in an integration test, does not work when the protos fail to compile (which they do after the Tonic update). Since running the crate's tests requires compiling the crate, if the proto bindings don't compile, we can't re-run the test. [xtask]: https://github.com/matklad/cargo-xtask BREAKING CHANGE: This commit updates the public dependencies `prost` and `tonic` to semver-incompatible versions (v0.11.0 and v0.8.0, respectively). This is a breaking change for users who are integrating the `console-api` protos with their own `tonic` servers or clients. --- .cargo/config | 5 +- .github/workflows/ci.yaml | 5 ++ Cargo.lock | 47 ++++++----- Cargo.toml | 3 +- console-api/Cargo.toml | 12 +-- console-api/src/generated/google.protobuf.rs | 0 .../src/generated/rs.tokio.console.common.rs | 27 +++++++ .../generated/rs.tokio.console.instrument.rs | 40 +++++++--- .../generated/rs.tokio.console.resources.rs | 11 +++ .../src/generated/rs.tokio.console.tasks.rs | 16 +++- .../src/generated/rs.tokio.console.trace.rs | 38 ++++++--- console-api/tests/bootstrap.rs | 64 +++++++++------ console-subscriber/Cargo.toml | 6 +- console-subscriber/src/stats.rs | 8 +- tokio-console/Cargo.toml | 6 +- xtask/Cargo.toml | 14 ++++ xtask/src/main.rs | 80 +++++++++++++++++++ 17 files changed, 298 insertions(+), 84 deletions(-) create mode 100644 console-api/src/generated/google.protobuf.rs create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs diff --git a/.cargo/config b/.cargo/config index 16f1e73ac..f2ea191eb 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,2 +1,5 @@ [build] -rustflags = ["--cfg", "tokio_unstable"] \ No newline at end of file +rustflags = ["--cfg", "tokio_unstable"] + +[alias] +xtask = "run --manifest-path ./xtask/Cargo.toml --" \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index bd41a4a4d..7f321f945 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -75,6 +75,11 @@ jobs: override: true - uses: Swatinem/rust-cache@v1 + - name: Install Protoc + uses: arduino/setup-protoc@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Run cargo test (API) uses: actions-rs/cargo@v1 with: diff --git a/Cargo.lock b/Cargo.lock index cc901b32e..b1f35352d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -238,15 +238,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "cmake" -version = "0.1.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" -dependencies = [ - "cc", -] - [[package]] name = "color-eyre" version = "0.5.11" @@ -277,9 +268,10 @@ dependencies = [ [[package]] name = "console-api" -version = "0.3.0" +version = "0.4.0" dependencies = [ "prost", + "prost-build", "prost-types", "tonic", "tonic-build", @@ -1069,9 +1061,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bd5316aa8f5c82add416dfbc25116b84b748a21153f512917e8143640a71bbd" +checksum = "399c3c31cdec40583bb68f0b18403400d01ec4289c383aa047560439952c4dd7" dependencies = [ "bytes", "prost-derive", @@ -1079,13 +1071,11 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328f9f29b82409216decb172d81e936415d21245befa79cd34c3f29d87d1c50b" +checksum = "7f835c582e6bd972ba8347313300219fed5bfa52caf175298d860b61ff6069bb" dependencies = [ "bytes", - "cfg-if", - "cmake", "heck", "itertools", "lazy_static", @@ -1101,9 +1091,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df35198f0777b75e9ff669737c6da5136b59dba33cf5a010a6d1cc4d56defc6f" +checksum = "7345d5f0e08c0536d7ac7229952590239e77abf0a0100a1b1d890add6ea96364" dependencies = [ "anyhow", "itertools", @@ -1114,9 +1104,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926681c118ae6e512a3ccefd4abbe5521a14f4cc1e207356d4d00c0b7f2006fd" +checksum = "d30bc806a29b347314be074ff0608ef8e547286e8ea68b061a2fe55689edc01f" dependencies = [ "bytes", "prost", @@ -1528,9 +1518,9 @@ dependencies = [ [[package]] name = "tonic" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1a361140b1af3f548e0a5105126b3fc737542f6cd4947b66419c80be07db22" +checksum = "498f271adc46acce75d66f639e4d35b31b2394c295c82496727dafa16d465dd2" dependencies = [ "async-stream", "async-trait", @@ -1560,9 +1550,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d17087af5c80e5d5fc8ba9878e60258065a0a757e35efe7a05b7904bece1943" +checksum = "2fbcd2800e34e743b9ae795867d5f77b535d3a3be69fd731e39145719752df8c" dependencies = [ "prettyplease", "proc-macro2", @@ -1910,3 +1900,12 @@ name = "windows_x86_64_msvc" version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "tonic-build", +] diff --git a/Cargo.toml b/Cargo.toml index 0f289d821..153d99d70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "tokio-console", "console-subscriber", - "console-api" + "console-api", + "xtask" ] resolver = "2" diff --git a/console-api/Cargo.toml b/console-api/Cargo.toml index 009ed725d..f01d08a08 100644 --- a/console-api/Cargo.toml +++ b/console-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "console-api" -version = "0.3.0" +version = "0.4.0" license = "MIT" edition = "2021" rust-version = "1.58.0" @@ -29,19 +29,21 @@ keywords = [ transport = ["tonic-build/transport", "tonic/transport"] [dependencies] -tonic = { version = "0.7", default-features = false, features = [ +tonic = { version = "0.8", default-features = false, features = [ "prost", "codegen", "transport", ] } -prost = "0.10" -prost-types = "0.10" +prost = "0.11" +prost-types = "0.11" tracing-core = "0.1.17" [dev-dependencies] -tonic-build = { version = "0.7", default-features = false, features = [ +tonic-build = { version = "0.8", default-features = false, features = [ "prost", "transport" ] } +# explicit dep so we can get the version with fixed whitespace. +prost-build = "0.11.1" [package.metadata.docs.rs] all-features = true diff --git a/console-api/src/generated/google.protobuf.rs b/console-api/src/generated/google.protobuf.rs new file mode 100644 index 000000000..e69de29bb diff --git a/console-api/src/generated/rs.tokio.console.common.rs b/console-api/src/generated/rs.tokio.console.common.rs index d9a77c8d3..d651148e3 100644 --- a/console-api/src/generated/rs.tokio.console.common.rs +++ b/console-api/src/generated/rs.tokio.console.common.rs @@ -165,6 +165,18 @@ pub mod metadata { /// Indicates metadata is associated with an event. Event = 1, } + impl Kind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Kind::Span => "SPAN", + Kind::Event => "EVENT", + } + } + } /// Describes the level of verbosity of a span or event. /// /// Corresponds to `Level` in the `tracing` crate. @@ -191,6 +203,21 @@ pub mod metadata { /// Designates very low priority, often extremely verbose, information. Trace = 4, } + impl Level { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Level::Error => "ERROR", + Level::Warn => "WARN", + Level::Info => "INFO", + Level::Debug => "DEBUG", + Level::Trace => "TRACE", + } + } + } } /// Contains stats about objects that can be polled. Currently these can be: /// - tasks that have been spawned diff --git a/console-api/src/generated/rs.tokio.console.instrument.rs b/console-api/src/generated/rs.tokio.console.instrument.rs index bf1f570ab..e39c9331c 100644 --- a/console-api/src/generated/rs.tokio.console.instrument.rs +++ b/console-api/src/generated/rs.tokio.console.instrument.rs @@ -30,7 +30,7 @@ pub struct ResumeRequest { /// - we can use one single timestamp for all the data /// - we can have all the new_metadata in one place /// - things such as async ops and resource ops do not make sense -/// on their own as they have relations to tasks and resources +/// on their own as they have relations to tasks and resources #[derive(Clone, PartialEq, ::prost::Message)] pub struct Update { /// The system time when this update was recorded. @@ -64,6 +64,7 @@ pub struct ResumeResponse { pub mod instrument_client { #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + use tonic::codegen::http::Uri; /// `InstrumentServer` implements `Instrument` as a service. #[derive(Debug, Clone)] pub struct InstrumentClient { @@ -84,19 +85,24 @@ pub mod instrument_client { where T: tonic::client::GrpcService, T::Error: Into, - T::ResponseBody: Default + Body + Send + 'static, + T::ResponseBody: Body + Send + 'static, ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } pub fn with_interceptor( inner: T, interceptor: F, ) -> InstrumentClient> where F: tonic::service::Interceptor, + T::ResponseBody: Default, T: tonic::codegen::Service< http::Request, Response = http::Response< @@ -109,19 +115,19 @@ pub mod instrument_client { { InstrumentClient::new(InterceptedService::new(inner, interceptor)) } - /// Compress requests with `gzip`. + /// Compress requests with the given encoding. /// /// This requires the server to support it otherwise it might respond with an /// error. #[must_use] - pub fn send_gzip(mut self) -> Self { - self.inner = self.inner.send_gzip(); + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); self } - /// Enable decompressing responses with `gzip`. + /// Enable decompressing responses. #[must_use] - pub fn accept_gzip(mut self) -> Self { - self.inner = self.inner.accept_gzip(); + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); self } /// Produces a stream of updates representing the behavior of the instrumented async runtime. @@ -258,8 +264,8 @@ pub mod instrument_server { #[derive(Debug)] pub struct InstrumentServer { inner: _Inner, - accept_compression_encodings: (), - send_compression_encodings: (), + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, } struct _Inner(Arc); impl InstrumentServer { @@ -283,6 +289,18 @@ pub mod instrument_server { { InterceptedService::new(Self::new(inner), interceptor) } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } } impl tonic::codegen::Service> for InstrumentServer where @@ -491,7 +509,7 @@ pub mod instrument_server { write!(f, "{:?}", self.0) } } - impl tonic::transport::NamedService for InstrumentServer { + impl tonic::server::NamedService for InstrumentServer { const NAME: &'static str = "rs.tokio.console.instrument.Instrument"; } } diff --git a/console-api/src/generated/rs.tokio.console.resources.rs b/console-api/src/generated/rs.tokio.console.resources.rs index 10c014758..714391461 100644 --- a/console-api/src/generated/rs.tokio.console.resources.rs +++ b/console-api/src/generated/rs.tokio.console.resources.rs @@ -80,6 +80,17 @@ pub mod resource { /// `TIMER` signals that this is a timer resource, e.g. waiting for a sleep to finish. Timer = 0, } + impl Known { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Known::Timer => "TIMER", + } + } + } /// Every resource is either a known kind or an other (unknown) kind. #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Kind { diff --git a/console-api/src/generated/rs.tokio.console.tasks.rs b/console-api/src/generated/rs.tokio.console.tasks.rs index 10915a6c5..6ff543bc9 100644 --- a/console-api/src/generated/rs.tokio.console.tasks.rs +++ b/console-api/src/generated/rs.tokio.console.tasks.rs @@ -47,7 +47,7 @@ pub struct TaskDetails { /// /// This is either: /// - the raw binary representation of a HdrHistogram.rs `Histogram` - /// serialized to binary in the V2 format (legacy) + /// serialized to binary in the V2 format (legacy) /// - a binary histogram plus details on outliers (current) #[prost(oneof="task_details::PollTimesHistogram", tags="3, 4")] pub poll_times_histogram: ::core::option::Option, @@ -58,7 +58,7 @@ pub mod task_details { /// /// This is either: /// - the raw binary representation of a HdrHistogram.rs `Histogram` - /// serialized to binary in the V2 format (legacy) + /// serialized to binary in the V2 format (legacy) /// - a binary histogram plus details on outliers (current) #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum PollTimesHistogram { @@ -125,6 +125,18 @@ pub mod task { /// (such as `tokio::task::spawn_blocking`). Blocking = 1, } + impl Kind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Kind::Spawn => "SPAWN", + Kind::Blocking => "BLOCKING", + } + } + } } /// Task performance statistics. #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/console-api/src/generated/rs.tokio.console.trace.rs b/console-api/src/generated/rs.tokio.console.trace.rs index ed3e98991..13c2843a5 100644 --- a/console-api/src/generated/rs.tokio.console.trace.rs +++ b/console-api/src/generated/rs.tokio.console.trace.rs @@ -84,6 +84,7 @@ pub mod trace_event { pub mod trace_client { #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + use tonic::codegen::http::Uri; /// Allows observers to stream trace events for a given `WatchRequest` filter. #[derive(Debug, Clone)] pub struct TraceClient { @@ -104,19 +105,24 @@ pub mod trace_client { where T: tonic::client::GrpcService, T::Error: Into, - T::ResponseBody: Default + Body + Send + 'static, + T::ResponseBody: Body + Send + 'static, ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } pub fn with_interceptor( inner: T, interceptor: F, ) -> TraceClient> where F: tonic::service::Interceptor, + T::ResponseBody: Default, T: tonic::codegen::Service< http::Request, Response = http::Response< @@ -129,19 +135,19 @@ pub mod trace_client { { TraceClient::new(InterceptedService::new(inner, interceptor)) } - /// Compress requests with `gzip`. + /// Compress requests with the given encoding. /// /// This requires the server to support it otherwise it might respond with an /// error. #[must_use] - pub fn send_gzip(mut self) -> Self { - self.inner = self.inner.send_gzip(); + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); self } - /// Enable decompressing responses with `gzip`. + /// Enable decompressing responses. #[must_use] - pub fn accept_gzip(mut self) -> Self { - self.inner = self.inner.accept_gzip(); + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); self } /// Produces a stream of trace events for the given filter. @@ -192,8 +198,8 @@ pub mod trace_server { #[derive(Debug)] pub struct TraceServer { inner: _Inner, - accept_compression_encodings: (), - send_compression_encodings: (), + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, } struct _Inner(Arc); impl TraceServer { @@ -217,6 +223,18 @@ pub mod trace_server { { InterceptedService::new(Self::new(inner), interceptor) } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } } impl tonic::codegen::Service> for TraceServer where @@ -310,7 +328,7 @@ pub mod trace_server { write!(f, "{:?}", self.0) } } - impl tonic::transport::NamedService for TraceServer { + impl tonic::server::NamedService for TraceServer { const NAME: &'static str = "rs.tokio.console.trace.Trace"; } } diff --git a/console-api/tests/bootstrap.rs b/console-api/tests/bootstrap.rs index ed48c6a13..27c629cf4 100644 --- a/console-api/tests/bootstrap.rs +++ b/console-api/tests/bootstrap.rs @@ -1,38 +1,56 @@ -use std::{path::PathBuf, process::Command}; +use std::{fs, path::PathBuf, process::Command}; #[test] fn bootstrap() { - let iface_files = &[ - "proto/trace.proto", - "proto/common.proto", - "proto/tasks.proto", - "proto/instrument.proto", - "proto/resources.proto", - "proto/async_ops.proto", - ]; - let dirs = &["proto"]; + let root_dir = PathBuf::from(std::env!("CARGO_MANIFEST_DIR")); + let proto_dir = root_dir.join("proto"); + let proto_ext = std::ffi::OsStr::new("proto"); + let proto_files = fs::read_dir(&proto_dir).and_then(|dir| { + dir.filter_map(|entry| { + (|| { + let entry = entry?; + if entry.file_type()?.is_dir() { + return Ok(None); + } - let out_dir = PathBuf::from(std::env!("CARGO_MANIFEST_DIR")) - .join("src") - .join("generated"); + let path = entry.path(); + if path.extension() != Some(proto_ext) { + return Ok(None); + } - tonic_build::configure() + Ok(Some(path)) + })() + .transpose() + }) + .collect::, _>>() + }); + let proto_files = match proto_files { + Ok(files) => files, + Err(error) => panic!("failed to list proto files: {}", error), + }; + + let out_dir = root_dir.join("src").join("generated"); + + if let Err(error) = tonic_build::configure() .build_client(true) .build_server(true) + .emit_rerun_if_changed(false) .protoc_arg("--experimental_allow_proto3_optional") - .out_dir(format!("{}", out_dir.display())) - .compile(iface_files, dirs) - .unwrap(); + .out_dir(&out_dir) + .compile(&proto_files[..], &[proto_dir]) + { + panic!("failed to compile `console-api` protobuf: {}", error); + } let status = Command::new("git") .arg("diff") .arg("--exit-code") .arg("--") - .arg(format!("{}", out_dir.display())) - .status() - .unwrap(); - - if !status.success() { - panic!("You should commit the protobuf files"); + .arg(out_dir) + .status(); + match status { + Ok(status) if !status.success() => panic!("You should commit the protobuf files"), + Err(error) => panic!("failed to run `git diff`: {}", error), + Ok(_) => {} } } diff --git a/console-subscriber/Cargo.toml b/console-subscriber/Cargo.toml index aec867f43..82a68a5a6 100644 --- a/console-subscriber/Cargo.toml +++ b/console-subscriber/Cargo.toml @@ -35,8 +35,8 @@ crossbeam-utils = "0.8.7" tokio = { version = "^1.15", features = ["sync", "time", "macros", "tracing"] } tokio-stream = "0.1" thread_local = "1.1.3" -console-api = { version = "0.3.0", path = "../console-api", features = ["transport"] } -tonic = { version = "0.7", features = ["transport"] } +console-api = { version = "0.4.0", path = "../console-api", features = ["transport"] } +tonic = { version = "0.8", features = ["transport"] } tracing-core = "0.1.24" tracing = "0.1.26" tracing-subscriber = { version = "0.3.11", default-features = false, features = ["fmt", "registry"] } @@ -46,7 +46,7 @@ hdrhistogram = { version = "7.3.0", default-features = false, features = ["seria # feature to also enable `tracing-subscriber`'s parking_lot feature flag. parking_lot_crate = { package = "parking_lot", version = "0.11", optional = true } humantime = "2.1.0" -prost-types = "0.10.0" +prost-types = "0.11.0" # Required for recording: serde = { version = "1", features = ["derive"] } diff --git a/console-subscriber/src/stats.rs b/console-subscriber/src/stats.rs index 32fb364f1..24848307d 100644 --- a/console-subscriber/src/stats.rs +++ b/console-subscriber/src/stats.rs @@ -532,7 +532,13 @@ impl ToProto for PollStats { last_poll_ended: timestamps .last_poll_ended .map(|at| base_time.to_timestamp(at)), - busy_time: Some(timestamps.busy_time.into()), + busy_time: Some(timestamps.busy_time.try_into().unwrap_or_else(|error| { + eprintln!( + "failed to convert busy time to protobuf duration: {}", + error + ); + Default::default() + })), } } } diff --git a/tokio-console/Cargo.toml b/tokio-console/Cargo.toml index b5be2873e..ed332a7ea 100644 --- a/tokio-console/Cargo.toml +++ b/tokio-console/Cargo.toml @@ -27,16 +27,16 @@ keywords = [ [dependencies] atty = "0.2" -console-api = { version = "0.3.0", path = "../console-api", features = ["transport"] } +console-api = { version = "0.4.0", path = "../console-api", features = ["transport"] } clap = { version = "3", features = ["cargo", "derive", "env"] } tokio = { version = "1", features = ["full", "rt-multi-thread"] } -tonic = { version = "0.7", features = ["transport"] } +tonic = { version = "0.8", features = ["transport"] } futures = "0.3" tui = { version = "0.16.0", default-features = false, features = ["crossterm"] } tracing = "0.1" tracing-subscriber = { version = "0.3.0", features = ["env-filter"] } tracing-journald = { version = "0.2", optional = true } -prost-types = "0.10" +prost-types = "0.11" crossterm = { version = "0.20", features = ["event-stream"] } color-eyre = { version = "0.5", features = ["issue-url"] } hdrhistogram = { version = "7.3.0", default-features = false, features = ["serialization"] } diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 000000000..09f60941a --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "xtask" +version = "0.1.0" +license = "MIT" +edition = "2021" +rust-version = "1.56.0" +publish = false + +[dependencies] +tonic-build = { version = "0.8", default-features = false, features = [ + "prost", "transport" +] } +clap = { version = "3", features = ["derive"] } +color-eyre = "0.5" \ No newline at end of file diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 000000000..807dd2f1f --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,80 @@ +use clap::Parser; +use color_eyre::{ + eyre::{ensure, WrapErr}, + Result, +}; +use std::{fs, path::PathBuf}; + +/// tokio-console dev tasks +#[derive(Debug, clap::Parser)] +struct Args { + #[clap(subcommand)] + cmd: Command, +} + +#[derive(Debug, clap::Subcommand)] +enum Command { + /// Generate `console-api` protobuf bindings. + GenProto, +} + +fn main() -> Result<()> { + color_eyre::install()?; + Args::parse().cmd.run() +} + +impl Command { + fn run(&self) -> Result<()> { + match self { + Self::GenProto => gen_proto(), + } + } +} + +fn gen_proto() -> Result<()> { + eprintln!("generating `console-api` protos..."); + + let api_dir = { + let mut mydir = PathBuf::from(std::env!("CARGO_MANIFEST_DIR")); + ensure!(mydir.pop(), "manifest path should not be relative!"); + mydir.join("console-api") + }; + + let proto_dir = api_dir.join("proto"); + let proto_ext = std::ffi::OsStr::new("proto"); + let proto_files = fs::read_dir(&proto_dir) + .with_context(|| { + format!( + "failed to read protobuf directory `{}`", + proto_dir.display() + ) + })? + .filter_map(|entry| { + (|| { + let entry = entry?; + if entry.file_type()?.is_dir() { + return Ok(None); + } + + let path = entry.path(); + if path.extension() != Some(proto_ext) { + return Ok(None); + } + + Ok(Some(path)) + })() + .transpose() + }) + .collect::>>()?; + + let out_dir = api_dir.join("src").join("generated"); + + tonic_build::configure() + .build_client(true) + .build_server(true) + .emit_rerun_if_changed(false) + .protoc_arg("--experimental_allow_proto3_optional") + .out_dir(&out_dir) + .compile(&proto_files[..], &[proto_dir]) + .context("failed to compile protobuf files") +}