From 48a7dcd77567f5bb1043f83c038c0d85c9524679 Mon Sep 17 00:00:00 2001 From: alcroito Date: Mon, 29 Apr 2024 17:13:50 +0200 Subject: [PATCH] build(rust): Move cargo dependencies into root Cargo.toml Add a list of workspace lints. Fix lint warnings. --- Cargo.toml | 164 +++++++++++++++++- crates/dyndns/Cargo.toml | 92 +++++----- crates/dyndns/src/config/app_config.rs | 15 +- crates/dyndns/src/db/crud/domain_records.rs | 2 +- .../src/domain_record_api/digital_ocean.rs | 2 +- crates/dyndns/src/ip_fetcher.rs | 5 +- crates/dyndns/src/logger.rs | 2 +- crates/dyndns/src/signal_handlers.rs | 15 +- crates/dyndns/src/types.rs | 2 +- crates/dyndns/src/updater.rs | 4 +- crates/dyndns/src/web/docs.rs | 2 +- .../web/routes/domain_record_ip_changes.rs | 2 +- crates/dyndns/src/web/static_server.rs | 2 +- 13 files changed, 236 insertions(+), 73 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b808b99..3a34a26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,164 @@ [workspace] +members = ["crates/dyndns"] resolver = "2" -members = [ - "crates/dyndns", -] +[workspace.package] +rust-version = "1.76" +edition = "2021" +license = "MIT" + +[workspace.dependencies] +chrono = { version = "0.4", default-features = false, features = [ + "alloc", + "serde", + "clock", +] } +clap = { version = "4", features = ["cargo", "derive"] } +color-eyre = "0.6" +figment = { version = "0.10", features = ["env", "toml", "test"] } +figment_file_provider_adapter = "0.1" +humantime = "2" +humantime-serde = "1" +itertools = "0.12" +native-tls = { version = "0.2", features = ["vendored"] } +once_cell = "1" +reqwest = { version = "0.12", features = ["blocking", "json"] } +secrecy = { version = "0.8", features = ["serde"] } +serde = { version = "1", features = ["derive", "rc"] } +serde_json = "1" +serde_with = "3" +signal-hook = { version = "0.3", features = ["extended-siginfo"] } +tailsome = "1" +tracing = "0.1" +tracing-log = "0.2" +tracing-subscriber = "0.3" +trust-dns-resolver = "0.23" + +# Stats feature dependencies +cfg-if = "1" +diesel = { version = "2", features = ["sqlite", "chrono"]} +diesel_migrations = { version = "2", features = ["sqlite"]} +directories = "5" +libsqlite3-sys = { version = "0.28", features = ["bundled"]} + +# Web server dependencies +aide = { version = "0.13", features = [ + "redoc", + "axum", + "axum-extra", + "macros", +] } +axum = { version = "0.7" } +axum-jsonschema = { version = "0.8", features = [ + "aide", +] } +axum-macros = { version = "0.4" } +futures-util = { version = "0.3" } +http = { version = "1" } +hyper = { version = "1" } +hyper-util = { version = "0" } +mime_guess = { version = "2" } +rust-embed = { version = "8", features = ["debug-embed"]} +schemars = { version = "0.8", features = ["chrono"] } +tower = { version = "0.4", features = ["full"] } +tower-http = { version = "0.5", features = ["full"] } +tokio = { version = "1", features = ["full"] } + +# workspace.build-dependencies (not actually a valid key, so needs to be part of +# regular dependencies) +# Keep anyhow, because vergen depends on it. +anyhow = "1" +vergen = { version = "8", features = [ + "build", + "cargo", + "git", + "gitcl", + "rustc", + "si", +] } + +# workspace.dev-dependencies (not actually a valid key, so needs to be part of +# regular dependencies) +tempfile = "3" + +# An opinionated list of extra clippy lints. Can be overridden where necessary. +# Taken from +# https://github.com/EmbarkStudios/rust-ecosystem/blob/542740e462f7ebf246e0b7170b3fb77cf6c68ec7/lints.rs +# but converted to new 1.74+ Cargo.toml syntax. +# See https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-lints-section + +[workspace.lints.rust] +unsafe_code = "deny" +future_incompatible = "warn" +nonstandard_style = "warn" +rust_2018_idioms = "warn" + +[workspace.lints.clippy] +all = "warn" +await_holding_lock = "warn" +char_lit_as_u8 = "warn" +checked_conversions = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" +doc_markdown = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +exit = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_let_mutex = "warn" +implicit_clone = "warn" +imprecise_flops = "warn" +inefficient_to_string = "warn" +invalid_upcast_comparisons = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +let_unit_value = "warn" +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +manual_ok_or = "warn" +map_err_ignore = "warn" +map_flatten = "warn" +map_unwrap_or = "warn" +match_on_vec_items = "warn" +match_same_arms = "warn" +match_wild_err_arm = "warn" +match_wildcard_for_single_variants = "warn" +mem_forget = "warn" +mismatched_target_os = "warn" +missing_enforced_import_renames = "warn" +mut_mut = "warn" +mutex_integer = "warn" +needless_borrow = "warn" +needless_continue = "warn" +needless_for_each = "warn" +option_option = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +same_functions_in_if_condition = "warn" +semicolon_if_nothing_returned = "warn" +single_match_else = "warn" +string_add_assign = "warn" +string_add = "warn" +string_lit_as_bytes = "warn" +string_to_string = "warn" +todo = "warn" +trait_duplication_in_bounds = "warn" +unimplemented = "warn" +unnested_or_patterns = "warn" +unused_self = "warn" +useless_transmute = "warn" +verbose_file_reads = "warn" +zero_sized_map_values = "warn" diff --git a/crates/dyndns/Cargo.toml b/crates/dyndns/Cargo.toml index 0beb4e7..4cc1e5c 100644 --- a/crates/dyndns/Cargo.toml +++ b/crates/dyndns/Cargo.toml @@ -2,10 +2,11 @@ name = "digitalocean-dyndns" version = "0.6.0" edition = "2021" +license.workspace = true +rust-version.workspace = true description = "Dynamic DNS using DigitalOcean's DNS API" readme = "README.md" repository = "https://github.com/alcroito/digitalocean-dyndns" -license = "MIT" keywords = ["dyndns", "digitalocean"] publish = false build = "build.rs" @@ -41,66 +42,66 @@ web = [ ] [dependencies] -chrono = { version = "0.4", default-features = false, features = [ +chrono = { workspace = true, default-features = false, features = [ "alloc", "serde", "clock", ] } -clap = { version = "4", features = ["cargo", "derive"] } -color-eyre = "0.6" -figment = { version = "0.10", features = ["env", "toml", "test"] } -figment_file_provider_adapter = "0.1" -humantime = "2" -humantime-serde = "1" -itertools = "0.12" -native-tls = { version = "0.2", features = ["vendored"] } -once_cell = "1" -reqwest = { version = "0.12", features = ["blocking", "json"] } -secrecy = { version = "0.8", features = ["serde"] } -serde = { version = "1", features = ["derive", "rc"] } -serde_json = "1" -serde_with = "3" -signal-hook = { version = "0.3", features = ["extended-siginfo"] } -tailsome = "1" -tracing = "0.1" -tracing-log = "0.2" -tracing-subscriber = "0.3" -trust-dns-resolver = "0.23" +clap = { workspace = true, features = ["cargo", "derive"] } +color-eyre.workspace = true +figment = { workspace = true, features = ["env", "toml", "test"] } +figment_file_provider_adapter.workspace = true +humantime.workspace = true +humantime-serde.workspace = true +itertools.workspace = true +native-tls = { workspace = true, features = ["vendored"] } +once_cell.workspace = true +reqwest = { workspace = true, features = ["blocking", "json"] } +secrecy = { workspace = true, features = ["serde"] } +serde = { workspace = true, features = ["derive", "rc"] } +serde_json.workspace = true +serde_with.workspace = true +signal-hook = { workspace = true, features = ["extended-siginfo"] } +tailsome.workspace = true +tracing.workspace = true +tracing-log.workspace = true +tracing-subscriber.workspace = true +trust-dns-resolver.workspace = true # Stats feature dependencies -cfg-if = "1" -diesel = { version = "2", features = ["sqlite", "chrono"], optional = true } -diesel_migrations = { version = "2", features = ["sqlite"], optional = true } -directories = "5" -libsqlite3-sys = { version = "0.28", features = ["bundled"], optional = true } +cfg-if.workspace = true +diesel = { workspace = true, features = ["sqlite", "chrono"], optional = true } +diesel_migrations = { workspace = true, features = ["sqlite"], optional = true } +directories.workspace = true +libsqlite3-sys = { workspace = true, features = ["bundled"], optional = true } # Web server dependencies -aide = { version = "0.13", optional = true, features = [ +aide = { workspace = true, optional = true, features = [ "redoc", "axum", "axum-extra", "macros", ] } -axum = { version = "0.7", optional = true } -axum-jsonschema = { version = "0.8", optional = true, features = [ +axum = { workspace = true, optional = true } +axum-jsonschema = { workspace = true, optional = true, features = [ "aide", ] } -axum-macros = { version = "0.4", optional = true } -futures-util = { version = "0.3", optional = true } -http = { version = "1", optional = true } -hyper = { version = "1", optional = true } -hyper-util = { version = "0", optional = true } -mime_guess = { version = "2", optional = true } -rust-embed = { version = "8", features = ["debug-embed"], optional = true } -schemars = { version = "0.8", optional = true, features = ["chrono"] } -tower = { version = "0.4", features = ["full"], optional = true } -tower-http = { version = "0.5", features = ["full"], optional = true } -tokio = { version = "1", features = ["full"], optional = true } +axum-macros = { workspace = true, optional = true } +futures-util = { workspace = true, optional = true } +http = { workspace = true, optional = true } +hyper = { workspace = true, optional = true } +hyper-util = { workspace = true, optional = true } +mime_guess = { workspace = true, optional = true } +rust-embed = { workspace = true, features = ["debug-embed"], optional = true } +schemars = { workspace = true, optional = true, features = ["chrono"] } +tower = { workspace = true, features = ["full"], optional = true } +tower-http = { workspace = true, features = ["full"], optional = true } +tokio = { workspace = true, features = ["full"], optional = true } [build-dependencies] # Keep anyhow, because vergen depends on it. -anyhow = "1" -vergen = { version = "8", features = [ +anyhow.workspace = true +vergen = { workspace = true, features = [ "build", "cargo", "git", @@ -110,4 +111,7 @@ vergen = { version = "8", features = [ ] } [dev-dependencies] -tempfile = "3" +tempfile.workspace = true + +[lints] +workspace = true diff --git a/crates/dyndns/src/config/app_config.rs b/crates/dyndns/src/config/app_config.rs index 1a02d87..10c43ca 100644 --- a/crates/dyndns/src/config/app_config.rs +++ b/crates/dyndns/src/config/app_config.rs @@ -149,7 +149,7 @@ where impl<'de> Visitor<'de> for LogLevelVisitor { type Value = tracing::Level; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.write_str("a number between 0 and 3 or one of the following strings: error, warn, info, debug, trace") } @@ -160,7 +160,6 @@ where let level = match value { 0 => tracing::Level::INFO, 1 => tracing::Level::DEBUG, - 2 => tracing::Level::TRACE, _ => tracing::Level::TRACE, }; Ok(level) @@ -170,9 +169,11 @@ where where E: de::Error, { - value.parse::().map_err(|_| { - let msg = "error parsing log level: expected one of \"error\", \"warn\", \ - \"info\", \"debug\", \"trace\""; + value.parse::().map_err(|e| { + let msg = format!( + "error parsing log level: expected one of \"error\", \"warn\", \ + \"info\", \"debug\", \"trace\": {e}" + ); E::custom(msg) }) } @@ -190,11 +191,9 @@ where S: serde::Serializer, { let level_u8 = match *level { - tracing::Level::INFO => 0, + tracing::Level::INFO | tracing::Level::WARN | tracing::Level::ERROR => 0, tracing::Level::DEBUG => 1, tracing::Level::TRACE => 2, - tracing::Level::ERROR => 0, - tracing::Level::WARN => 0, }; serializer.serialize_u8(level_u8) } diff --git a/crates/dyndns/src/db/crud/domain_records.rs b/crates/dyndns/src/db/crud/domain_records.rs index 6f750fa..be2296b 100644 --- a/crates/dyndns/src/db/crud/domain_records.rs +++ b/crates/dyndns/src/db/crud/domain_records.rs @@ -38,7 +38,7 @@ pub fn get_domain_records(conn: &mut SqliteConnection) -> Result, ) -> Result> { use super::super::schema::domain_records; let domain_record = diff --git a/crates/dyndns/src/domain_record_api/digital_ocean.rs b/crates/dyndns/src/domain_record_api/digital_ocean.rs index 15df42c..5bb3eee 100644 --- a/crates/dyndns/src/domain_record_api/digital_ocean.rs +++ b/crates/dyndns/src/domain_record_api/digital_ocean.rs @@ -89,7 +89,7 @@ impl DomainRecordApi for DigitalOceanApi { impl Drop for DigitalOceanApi { fn drop(&mut self) { - trace!("DigitalOceanApi object destroyed") + trace!("DigitalOceanApi object destroyed"); } } diff --git a/crates/dyndns/src/ip_fetcher.rs b/crates/dyndns/src/ip_fetcher.rs index 1c4e2cc..2b522f1 100644 --- a/crates/dyndns/src/ip_fetcher.rs +++ b/crates/dyndns/src/ip_fetcher.rs @@ -9,7 +9,7 @@ use trust_dns_resolver::Resolver; use crate::types::{DisplayIpAddrV4AndV6Pretty, IpAddrV4AndV6}; /// IP addresses for OpenDNS Public DNS -/// https://en.wikipedia.org/wiki/OpenDNS +/// [https://en.wikipedia.org/wiki/OpenDNS](https://en.wikipedia.org/wiki/OpenDNS) const OPEN_DNS_IPS: &[IpAddr] = &[ IpAddr::V4(Ipv4Addr::new(208, 67, 222, 222)), IpAddr::V4(Ipv4Addr::new(208, 67, 220, 220)), @@ -26,7 +26,8 @@ pub struct DnsIpFetcher {} impl PublicIpFetcher for DnsIpFetcher { /// Fetch public IP of current machine by querying the OpenDNS myip resolver - /// See https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script/81699#81699 + /// See + /// [Stack Overflow](https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script/81699#81699) fn fetch_public_ips(&self, lookup_ipv4: bool, lookup_ipv6: bool) -> Result { info!("Fetching public IP using OpenDNS"); let hostname_to_lookup = "myip.opendns.com."; diff --git a/crates/dyndns/src/logger.rs b/crates/dyndns/src/logger.rs index ef3b413..cdf2cb5 100644 --- a/crates/dyndns/src/logger.rs +++ b/crates/dyndns/src/logger.rs @@ -21,7 +21,7 @@ pub fn setup_early_logger() -> Result<()> { .init(); TRACING_FILTER_RELOAD_HANDLE .set(reload_handle) - .map_err(|_| eyre!("Could not save tracing filter reload handle")) + .map_err(|e| eyre!("Could not save tracing filter reload handle {e:?}")) } pub fn setup_logger(log_level: &tracing::Level) -> Result<()> { diff --git a/crates/dyndns/src/signal_handlers.rs b/crates/dyndns/src/signal_handlers.rs index 943bad5..1f4f64e 100644 --- a/crates/dyndns/src/signal_handlers.rs +++ b/crates/dyndns/src/signal_handlers.rs @@ -130,6 +130,7 @@ impl AppTerminationHandler { } } + #[allow(clippy::unused_self)] fn notify_threads_to_exit(&self) { #[cfg(feature = "web")] { @@ -219,20 +220,20 @@ impl AppTerminationHandler { for info in signals { let killer_pid_message = info .process - .map(|p| format!(" from pid: {}", p.pid)) - .unwrap_or_else(|| "".to_owned()); + .map_or_else(|| "".to_owned(), |p| format!(" from pid: {}", p.pid)); - let signal_name = signal_hook::low_level::signal_name(info.signal) - .map(|s| s.to_owned()) - .unwrap_or_else(|| { + let signal_name = signal_hook::low_level::signal_name(info.signal).map_or_else( + || { info!("Can't find human readable name for signal: {}", info.signal); info.signal.to_string() - }); + }, + |s| s.to_owned(), + ); info!("Received signal: {}{}", signal_name, killer_pid_message); match info.signal { SIGHUP => { - info!("Ignoring signal because config reloading is not yet supported") + info!("Ignoring signal because config reloading is not yet supported"); } SIGTERM | SIGQUIT | SIGINT => { assert!(TERM_SIGNALS.contains(&info.signal)); diff --git a/crates/dyndns/src/types.rs b/crates/dyndns/src/types.rs index b262c4f..a29fa19 100644 --- a/crates/dyndns/src/types.rs +++ b/crates/dyndns/src/types.rs @@ -47,7 +47,7 @@ impl DomainRecordToUpdate { pub fn fqdn(&self) -> String { if self.hostname_part == "@" { - self.domain_name.to_owned() + self.domain_name.clone() } else { format!("{}.{}", self.hostname_part, self.domain_name) } diff --git a/crates/dyndns/src/updater.rs b/crates/dyndns/src/updater.rs index 0d41c3a..cf8a25d 100644 --- a/crates/dyndns/src/updater.rs +++ b/crates/dyndns/src/updater.rs @@ -47,7 +47,7 @@ impl Updater { "Attempting to update domain record '{}'", record_to_update.fqdn() ); - let records = match domain_record_cache.entry(record_to_update.domain_name.to_string()) { + let records = match domain_record_cache.entry(record_to_update.domain_name.clone()) { std::collections::hash_map::Entry::<_, _>::Vacant(o) => { trace!("Querying records for '{}'", record_to_update.domain_name); let records = self.api.get_domain_records(&record_to_update.domain_name)?; @@ -76,7 +76,7 @@ impl Updater { self.api .update_domain_ip(api_domain_record.id, record_to_update, &curr_ip)?; } else { - info!("Skipping updating IP due to dry run") + info!("Skipping updating IP due to dry run"); } } else { info!("Correct IP already set, nothing to do"); diff --git a/crates/dyndns/src/web/docs.rs b/crates/dyndns/src/web/docs.rs index b11c1e7..a5737c0 100644 --- a/crates/dyndns/src/web/docs.rs +++ b/crates/dyndns/src/web/docs.rs @@ -43,7 +43,7 @@ pub fn docs_routes() -> ApiRouter { router } -pub fn api_docs(api: TransformOpenApi) -> TransformOpenApi { +pub fn api_docs(api: TransformOpenApi<'_>) -> TransformOpenApi<'_> { api.title("ddns Open API") .summary("ddns Open API") .description("ddns Open API") diff --git a/crates/dyndns/src/web/routes/domain_record_ip_changes.rs b/crates/dyndns/src/web/routes/domain_record_ip_changes.rs index 72dad5b..8480bef 100644 --- a/crates/dyndns/src/web/routes/domain_record_ip_changes.rs +++ b/crates/dyndns/src/web/routes/domain_record_ip_changes.rs @@ -15,6 +15,6 @@ pub async fn list_domain_record_ip_changes( Ok(Json(ip_changes)) } -pub fn list_domain_record_ip_changes_docs(op: TransformOperation) -> TransformOperation { +pub fn list_domain_record_ip_changes_docs(op: TransformOperation<'_>) -> TransformOperation<'_> { op.description("List all recent domain record ip changes") } diff --git a/crates/dyndns/src/web/static_server.rs b/crates/dyndns/src/web/static_server.rs index ffe0060..53b61c3 100644 --- a/crates/dyndns/src/web/static_server.rs +++ b/crates/dyndns/src/web/static_server.rs @@ -43,7 +43,7 @@ pub fn print_where_files_are_served_from() { ServeStaticFilesFrom::Filesystem => info!("Serving web assets from filesystem"), ServeStaticFilesFrom::Embedded => info!("Serving web assets embedded in binary"), ServeStaticFilesFrom::FSOrEmbedded => { - info!("Serving web assets from filesystem with fallback to assets embedded in binary") + info!("Serving web assets from filesystem with fallback to assets embedded in binary"); } } }