From a8307fa0c6783b11382a4166a2c6d1cb5425ef02 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Wed, 3 Dec 2025 12:44:44 -0500 Subject: [PATCH 01/28] modernize deps --- CHANGELOG.md | 11 + Cargo.lock | 2669 +++++++++++++++++---------- deny.toml | 40 +- falconeri-worker/Cargo.toml | 14 +- falconeri-worker/src/main.rs | 12 +- falconeri/Cargo.toml | 17 +- falconeri/src/cmd/datum/mod.rs | 7 +- falconeri/src/cmd/db.rs | 8 +- falconeri/src/cmd/deploy.rs | 35 +- falconeri/src/cmd/job/mod.rs | 19 +- falconeri/src/main.rs | 38 +- falconeri_common/Cargo.toml | 39 +- falconeri_common/src/connect_via.rs | 52 +- falconeri_common/src/kubernetes.rs | 12 +- falconeri_common/src/models/mod.rs | 7 +- falconeri_common/src/rest_api.rs | 1 - falconerid/Cargo.toml | 16 +- falconerid/src/main.rs | 4 - falconerid/src/util.rs | 12 +- 19 files changed, 1866 insertions(+), 1147 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed20fa..d45f311 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.0-beta.13] - 2025-12-03 + +### Changed + +- Updated all dependencies to latest versions. +- Replaced unmaintained `structopt` with `clap` v4. +- Replaced unmaintained `backoff` crate with simple built-in retry logic. +- Removed OpenSSL Rust dependencies entirely. We now use `rustls` for all TLS. (Database connections still use the system's `libpq`, which may link against OpenSSL.) +- Updated Rocket from 0.5.0-rc.3 to 0.5.1 (stable release). +- Updated axum from 0.6 to 0.8. + ## [1.0.0-beta.12] - 2022-12-14 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index ef708f4..ec5593f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,37 +1,31 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -42,28 +36,69 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" dependencies = [ "backtrace", ] [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -72,24 +107,24 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -99,45 +134,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] -name = "atty" -version = "0.2.14" +name = "atomic" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "bytemuck", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.6.18" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ - "async-trait", "axum-core", "axum-macros", - "bitflags 1.3.2", "bytes", + "form_urlencoded", "futures-util", - "http", - "http-body", - "hyper", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-util", "itoa", "matchit", "memchr", "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -151,17 +190,18 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ - "async-trait", "bytes", - "futures-util", - "http", - "http-body", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", "mime", - "rustversion", + "pin-project-lite", + "sync_wrapper", "tower-layer", "tower-service", "tracing", @@ -169,53 +209,35 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.3.7" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb524613be645939e280b7279f7b017f98cf7f5ef084ec374df373530e73277" +checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.22", -] - -[[package]] -name = "backoff" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" -dependencies = [ - "getrandom", - "instant", - "rand", + "syn", ] [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-link", ] [[package]] name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.2" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "binascii" @@ -225,15 +247,9 @@ checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -246,21 +262,27 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cast" @@ -270,63 +292,102 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.79" +version = "1.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", - "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-link", ] [[package]] name = "clap" -version = "2.34.0" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "cookie" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ "percent-encoding", - "time 0.3.22", + "time", "version_check", ] [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -334,26 +395,25 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crossbeam" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "cfg-if", "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", @@ -363,62 +423,52 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -426,30 +476,140 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "devise" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6eacefd3f541c66fc61433d65e54e0e46e0a029a819a7dbbc7a7b489e8a85f8" +checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d" dependencies = [ "devise_codegen", "devise_core", @@ -457,9 +617,9 @@ dependencies = [ [[package]] name = "devise_codegen" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8cf4b8dd484ede80fd5c547592c46c3745a617c8af278e2b72bea86b2dfed6" +checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867" dependencies = [ "devise_core", "quote", @@ -467,27 +627,28 @@ dependencies = [ [[package]] name = "devise_core" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" +checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7" dependencies = [ - "bitflags 2.3.3", + "bitflags", "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "diesel" -version = "2.1.0" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7a532c1f99a0f596f6960a60d1e119e91582b24b39e2d83a190e61262c3ef0c" +checksum = "0c415189028b232660655e4893e8bc25ca7aee8e96888db66d9edb400535456a" dependencies = [ - "bitflags 2.3.3", + "bitflags", "byteorder", "chrono", "diesel_derives", + "downcast-rs", "itoa", "pq-sys", "r2d2", @@ -497,21 +658,22 @@ dependencies = [ [[package]] name = "diesel_derives" -version = "2.1.0" +version = "2.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74398b79d81e52e130d991afeed9c86034bb1b7735f46d2f5bf7deb261d80303" +checksum = "8587cbca3c929fb198e7950d761d31ca72b80aa6e07c1b7bec5879d187720436" dependencies = [ "diesel_table_macro_syntax", + "dsl_auto_type", "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "diesel_migrations" -version = "2.1.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6036b3f0120c5961381b570ee20a02432d7e2d27ea60de9578799cf9156914ac" +checksum = "745fd255645f0f1135f9ec55c7b00e0882192af9683ab4731e4bba3da82b8f9c" dependencies = [ "diesel", "migrations_internals", @@ -520,11 +682,11 @@ dependencies = [ [[package]] name = "diesel_table_macro_syntax" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" +checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c" dependencies = [ - "syn 2.0.22", + "syn", ] [[package]] @@ -558,11 +720,42 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "downcast-rs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" + +[[package]] +name = "dsl_auto_type" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e" +dependencies = [ + "darling 0.21.3", + "either", + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "either" -version = "1.8.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" @@ -572,93 +765,88 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] -name = "env_logger" -version = "0.10.0" +name = "env_filter" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ - "humantime", - "is-terminal", "log", "regex", - "termcolor", ] [[package]] -name = "equivalent" -version = "1.0.0" +name = "env_logger" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] [[package]] -name = "errno" -version = "0.3.1" +name = "equivalent" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "cc", "libc", + "windows-sys 0.61.2", ] [[package]] name = "falconeri" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" dependencies = [ - "base64 0.21.2", + "base64", + "clap", "crossbeam", "falconeri_common", "handlebars", "log", - "openssl-probe", - "openssl-sys", "prettytable-rs", "serde", "serde_derive", "serde_json", - "structopt", "uuid", ] [[package]] name = "falconeri-worker" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" dependencies = [ "crossbeam", "env_logger", "falconeri_common", "glob", "log", - "openssl-probe", - "openssl-sys", + "tracing", "uuid", ] [[package]] name = "falconeri_common" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" dependencies = [ "anyhow", - "backoff", - "base64 0.21.2", + "base64", "cast", "chrono", "diesel", @@ -667,7 +855,7 @@ dependencies = [ "humantime-serde", "lazy_static", "r2d2", - "rand", + "rand 0.9.2", "regex", "reqwest", "semver", @@ -681,45 +869,45 @@ dependencies = [ [[package]] name = "falconerid" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" dependencies = [ "axum", "falconeri_common", "headers", - "openssl-probe", - "openssl-sys", "rocket", - "rocket_codegen", - "rocket_http", "serde", "serde_derive", "serde_json", "serde_yaml", + "tracing", ] [[package]] name = "fastrand" -version = "1.9.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "figment" -version = "0.10.10" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4547e226f4c9ab860571e070a9034192b3175580ecea38da34fcdb53a018c9a5" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ - "atomic", + "atomic 0.6.1", "pear", "serde", - "toml", + "toml 0.8.23", "uncased", "version_check", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "fnv" version = "1.0.7" @@ -728,18 +916,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "futures" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -751,9 +939,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -761,33 +949,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -825,40 +1013,56 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "r-efi", + "wasip2", + "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.27.3" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "h2" -version = "0.3.20" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 1.9.3", + "http 0.2.12", + "indexmap", "slab", "tokio", "tokio-util", @@ -867,41 +1071,36 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.3.7" +version = "6.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c3372087601b532857d332f5957cbae686da52bb7810bf038c3e3c3cc2fa0d" +checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098" dependencies = [ + "derive_builder", "log", + "num-order", "pest", "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 2.0.17", ] [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "headers" -version = "0.3.8" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", + "base64", "bytes", "headers-core", - "http", + "http 1.4.0", "httpdate", "mime", "sha1", @@ -909,82 +1108,97 @@ dependencies = [ [[package]] name = "headers-core" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http", + "http 1.4.0", ] [[package]] name = "heck" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "heck" -version = "0.4.1" +name = "hermit-abi" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "http" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "libc", + "bytes", + "fnv", + "itoa", ] [[package]] -name = "hermit-abi" -version = "0.3.1" +name = "http" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] [[package]] -name = "http" -version = "0.2.9" +name = "http-body" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "fnv", - "itoa", + "http 0.2.12", + "pin-project-lite", ] [[package]] name = "http-body" -version = "0.4.5" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.4.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "http", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "humantime-serde" @@ -998,53 +1212,104 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" -version = "0.24.0" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", - "hyper", + "http 1.4.0", + "hyper 1.8.1", + "hyper-util", "rustls", + "rustls-native-certs", + "rustls-pki-types", "tokio", "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.1", + "tokio", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1056,35 +1321,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" -version = "0.4.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "indexmap" -version = "1.9.3" +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.0.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown", + "serde", + "serde_core", ] [[package]] @@ -1094,96 +1448,126 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" [[package]] -name = "instant" -version = "0.1.12" +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" dependencies = [ - "cfg-if", + "memchr", + "serde", ] [[package]] -name = "io-lifetimes" -version = "1.0.11" +name = "is-terminal" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] -name = "ipnet" -version = "2.8.0" +name = "is_terminal_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] -name = "is-terminal" -version = "0.4.8" +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" dependencies = [ - "hermit-abi 0.3.1", - "rustix 0.38.1", - "windows-sys 0.48.0", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", ] [[package]] -name = "itoa" -version = "1.0.6" +name = "jiff-static" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] -name = "linux-raw-sys" -version = "0.3.8" +name = "libredox" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", +] [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.19" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "loom" @@ -1200,51 +1584,48 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ "regex-automata", ] [[package]] name = "matchit" -version = "0.7.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.9.0" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "migrations_internals" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f23f71580015254b020e856feac3df5878c2c7a8812297edd6c0a485ac9dada" +checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d" dependencies = [ "serde", - "toml", + "toml 0.9.8", ] [[package]] name = "migrations_macros" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce3325ac70e67bbab5bd837a31cae01f1a6db64e0e744a33cb03a543469ef08" +checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703" dependencies = [ "migrations_internals", "proc-macro2", @@ -1259,39 +1640,38 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.8" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] name = "multer" -version = "2.1.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 1.4.0", "httparse", - "log", "memchr", "mime", - "spin 0.9.8", + "spin", "tokio", "tokio-util", "version_check", @@ -1299,77 +1679,85 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", ] [[package]] name = "object" -version = "0.31.1" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "openssl-probe" -version = "0.1.5" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "openssl-sys" -version = "0.9.90" +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] -name = "overload" -version = "0.1.1" +name = "openssl-probe" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1377,22 +1765,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets", + "windows-link", ] [[package]] name = "pear" -version = "0.2.4" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec95680a7087503575284e5063e14b694b7a9c0b065e5dceec661e0497127e8" +checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" dependencies = [ "inlinable_string", "pear_codegen", @@ -1401,37 +1789,37 @@ dependencies = [ [[package]] name = "pear_codegen" -version = "0.2.4" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9661a3a53f93f09f2ea882018e4d7c88f6ff2956d809a276060476fd8c879d3c" +checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.7.0" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" +checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" dependencies = [ - "thiserror", + "memchr", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.0" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" +checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" dependencies = [ "pest", "pest_generator", @@ -1439,53 +1827,32 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.0" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" +checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "pest_meta" -version = "2.7.0" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" +checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" dependencies = [ - "once_cell", "pest", "sha2", ] -[[package]] -name = "pin-project" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e138fdd8263907a2b0e1b4e80b7e58c721126479b6e6eedfb1b402acea7b9bd" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1fef411b303e3e12d534fb6e7852de82da56edd937d895125821fb7c09436c7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.22", -] - [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1495,94 +1862,166 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "ppv-lite86" -version = "0.2.17" +name = "portable-atomic" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] -name = "pq-sys" -version = "0.4.8" +name = "portable-atomic-util" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0052426df997c0cbd30789eb44ca097e3541717a7b8fa36b1c464ee7edebd" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ - "vcpkg", + "portable-atomic", ] [[package]] -name = "prettytable-rs" -version = "0.10.0" +name = "potential_utf" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ - "csv", - "encode_unicode", - "is-terminal", - "lazy_static", - "term", - "unicode-width", + "zerovec", ] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", + "zerocopy", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "pq-sys" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width", ] [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "proc-macro2-diagnostics" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", "version_check", "yansi", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.6.1", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.1", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" -version = "1.0.29" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "r2d2" version = "0.8.10" @@ -1601,8 +2040,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -1612,7 +2061,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1621,167 +2080,163 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "rand_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "bitflags 1.3.2", + "getrandom 0.3.4", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", - "redox_syscall 0.2.16", - "thiserror", + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", ] [[package]] name = "ref-cast" -version = "1.0.16" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.16" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ - "regex-syntax 0.6.29", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.7.2" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ - "base64 0.21.2", + "base64", "bytes", - "encoding_rs", + "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", "hyper-rustls", - "ipnet", + "hyper-util", "js-sys", "log", - "mime", - "once_cell", "percent-encoding", "pin-project-lite", + "quinn", "rustls", "rustls-native-certs", - "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "tokio", "tokio-rustls", + "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", ] [[package]] name = "ring" -version = "0.16.20" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", + "cfg-if", + "getrandom 0.2.16", "libc", - "once_cell", - "spin 0.5.2", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "rocket" -version = "0.5.0-rc.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58734f7401ae5cfd129685b48f61182331745b357b96f2367f01aebaf1cc9cc9" +checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f" dependencies = [ "async-stream", "async-trait", - "atomic", + "atomic 0.5.3", "binascii", "bytes", "either", "figment", "futures", - "indexmap 1.9.3", - "is-terminal", + "indexmap", "log", "memchr", "multer", "num_cpus", "parking_lot", "pin-project-lite", - "rand", + "rand 0.8.5", "ref-cast", "rocket_codegen", "rocket_http", @@ -1789,7 +2244,7 @@ dependencies = [ "serde_json", "state", "tempfile", - "time 0.3.22", + "time", "tokio", "tokio-stream", "tokio-util", @@ -1801,32 +2256,33 @@ dependencies = [ [[package]] name = "rocket_codegen" -version = "0.5.0-rc.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7093353f14228c744982e409259fb54878ba9563d08214f2d880d59ff2fc508b" +checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" dependencies = [ "devise", "glob", - "indexmap 1.9.3", + "indexmap", "proc-macro2", "quote", "rocket_http", - "syn 2.0.22", + "syn", "unicode-xid", + "version_check", ] [[package]] name = "rocket_http" -version = "0.5.0-rc.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936012c99162a03a67f37f9836d5f938f662e26f2717809761a9ac46432090f4" +checksum = "e274915a20ee3065f611c044bd63c40757396b6dbc057d6046aec27f14f882b9" dependencies = [ "cookie", "either", "futures", - "http", - "hyper", - "indexmap 1.9.3", + "http 0.2.12", + "hyper 0.14.32", + "indexmap", "log", "memchr", "pear", @@ -1837,7 +2293,7 @@ dependencies = [ "smallvec", "stable-pattern", "state", - "time 0.3.22", + "time", "tokio", "uncased", "uuid", @@ -1845,99 +2301,95 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] -name = "rustix" -version = "0.37.21" +name = "rustc-hash" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" -version = "0.38.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.3.3", + "bitflags", "errno", "libc", - "linux-raw-sys 0.4.3", - "windows-sys 0.48.0", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.21.2" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ - "log", + "once_cell", "ring", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.6.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pki-types", "schannel", "security-framework", ] [[package]] -name = "rustls-pemfile" -version = "1.0.3" +name = "rustls-pki-types" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" dependencies = [ - "base64 0.21.2", + "web-time", + "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.100.1" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.42.0", + "windows-sys 0.61.2", ] [[package]] @@ -1957,27 +2409,17 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "sct" -version = "0.7.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.9.1" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -1986,9 +2428,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -1996,59 +2438,82 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", + "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_path_to_error" -version = "0.1.11" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7f05c1d5476066defcdfacce1f52fc3cae3af1d3089727100c02ae92e5abbe0" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ + "itoa", "serde", + "serde_core", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2063,11 +2528,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.22" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "452e67b9c20c37fa79df53201dc03839651086ed9bbe92b3ca585ca9fdaa7d85" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.0.0", + "indexmap", "itoa", "ryu", "serde", @@ -2076,9 +2541,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -2087,9 +2552,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -2098,52 +2563,59 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] [[package]] name = "slab" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.4.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] -name = "spin" -version = "0.5.2" +name = "socket2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] [[package]] name = "spin" @@ -2160,85 +2632,75 @@ dependencies = [ "memchr", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "state" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" dependencies = [ "loom", ] [[package]] name = "strsim" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "structopt" -version = "0.3.26" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] -name = "structopt-derive" -version = "0.4.18" +name = "syn" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ - "heck 0.3.3", - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "unicode-ident", ] [[package]] -name = "syn" -version = "1.0.109" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "futures-core", ] [[package]] -name = "syn" -version = "2.0.22" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "syn", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "tempfile" -version = "3.6.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ - "autocfg", - "cfg-if", "fastrand", - "redox_syscall 0.3.5", - "rustix 0.37.21", - "windows-sys 0.48.0", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", ] [[package]] @@ -2253,71 +2715,64 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.2.0" +name = "thiserror" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "winapi-util", + "thiserror-impl 1.0.69", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "thiserror" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "unicode-width", + "thiserror-impl 2.0.17", ] [[package]] -name = "thiserror" -version = "1.0.40" +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", ] [[package]] name = "time" -version = "0.3.22" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ + "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -2325,24 +2780,35 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ + "num-conv", "time-core", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -2355,39 +2821,36 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "autocfg", - "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -2395,9 +2858,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -2406,62 +2869,99 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml" -version = "0.7.5" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_edit", ] +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "serde_core", + "serde_spanned 1.0.3", + "toml_datetime 0.7.3", + "toml_parser", + "winnow", +] + [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.0.0", + "indexmap", "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tower" -version = "0.4.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -2469,24 +2969,41 @@ dependencies = [ ] [[package]] -name = "tower-layer" -version = "0.3.2" +name = "tower-http" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" +checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -2495,20 +3012,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" dependencies = [ "once_cell", "valuable", @@ -2516,25 +3033,25 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -2545,118 +3062,112 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.16.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ubyte" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c81f0dae7d286ad0d9366d7679a77934cfc3cf3a8d67e82669794412b2368fe6" +checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" dependencies = [ "serde", ] [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uncased" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ "serde", "version_check", ] -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unsafe-libyaml" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.0" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" -version = "1.4.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ - "getrandom", - "serde", + "getrandom 0.3.4", + "js-sys", + "serde_core", + "wasm-bindgen", ] [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" @@ -2664,17 +3175,11 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" @@ -2687,58 +3192,50 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "cfg-if", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" +name = "wasm-bindgen" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ - "bumpalo", - "log", + "cfg-if", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.22", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2746,28 +3243,41 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.22", - "wasm-bindgen-backend", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -2789,15 +3299,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2810,152 +3311,410 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", ] [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.6", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows-targets", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.4.7" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] [[package]] -name = "winreg" -version = "0.10.1" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" dependencies = [ - "winapi", + "is-terminal", ] [[package]] -name = "yansi" -version = "0.5.1" +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/deny.toml b/deny.toml index 8118083..b42cf2b 100644 --- a/deny.toml +++ b/deny.toml @@ -3,32 +3,12 @@ # These policies can be enforced using `cargo deny check`. [advisories] -ignore = [ - # Ignore a nasty `localtime_r` and `setenv` race condition which can - # segfault if we try to read the localtime while someone is setting an env - # var. - # - # This can probably be fixed once - # https://github.com/chronotope/chrono/issues/602 has been addressed. - #"RUSTSEC-2020-0159", - # Also `localtime_r`. - "RUSTSEC-2020-0071", -] [licenses] -# Don't allow code with an unclear license. -unlicensed = "deny" - -# Don't allow "copylefted" licenses unless they're listed below. -copyleft = "deny" - # Allow common non-restrictive licenses. ISC is used for various DNS and crypto -# things, and it's a minimally restrictive open source license. -allow = ["MIT", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "CC0-1.0", "ISC", "OpenSSL", "Zlib", "Unicode-DFS-2016"] - -# Many organizations ban AGPL-licensed code -# https://opensource.google/docs/using/agpl-policy/ -deny = ["AGPL-3.0"] +# things, and it's a minimally restrictive open source license. Everything not +# in this list (including AGPL, unlicensed, and copyleft) is denied by default. +allow = ["MIT", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "CC0-1.0", "ISC", "OpenSSL", "Zlib", "Unicode-3.0", "Unicode-DFS-2016"] [[licenses.clarify]] # Ring has a messy license. @@ -44,19 +24,21 @@ multiple-versions = "warn" deny = [ # OpenSSL has caused endless deployment and build problems, and we want - # nothing to do with it, in any version. Unforunately, `diesel` depends on - # `libpq`, which depends on OpenSSL at the C level. So we ban `openssl` - # (used from Rust), but we keep `openssl-sys` so we can do some linker - # tricks with `extern crate`. + # nothing to do with it. We use rustls for TLS. Note that `diesel` depends + # on `libpq`, which depends on OpenSSL at the C level for database + # connections, but that's handled by the system library. + # + # Note: openssl-probe is allowed - it's a tiny crate that just finds system + # CA cert paths, used by rustls-native-certs. Despite the name, it doesn't + # link to or depend on OpenSSL. { name = "openssl" }, + { name = "openssl-sys" }, ] skip = [ ] skip-tree = [ - # Rocket's pre-release is stale. - { name = "rocket", version = "0.5.0-rc.1" }, # Build-only dependency uses some stale crates. { name = "pest_meta" }, # We're never running on top of a real WASI platform, so just ignore it. diff --git a/falconeri-worker/Cargo.toml b/falconeri-worker/Cargo.toml index d764f8d..853c4a7 100644 --- a/falconeri-worker/Cargo.toml +++ b/falconeri-worker/Cargo.toml @@ -1,18 +1,16 @@ [package] name = "falconeri-worker" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" authors = ["Eric Kidd "] edition = "2018" license = "Apache-2.0 OR MIT" [dependencies] -crossbeam = "0.8.1" -env_logger = "0.10.0" +crossbeam = "0.8.4" +env_logger = "0.11.8" falconeri_common = { path = "../falconeri_common" } glob = "0.3" -log = "0.4.3" -# Needed for ekidd/rust-musl-builder. -openssl-sys = "*" -openssl-probe = "0.1.2" -uuid = { version = "1.3.3", features = ["serde", "v4"] } +log = "0.4.29" +tracing = "0.1.43" +uuid = { version = "1.19.0", features = ["serde", "v4"] } diff --git a/falconeri-worker/src/main.rs b/falconeri-worker/src/main.rs index c057484..2886c52 100644 --- a/falconeri-worker/src/main.rs +++ b/falconeri-worker/src/main.rs @@ -1,6 +1,3 @@ -// Needed for static linking to work right on Linux. -extern crate openssl_sys; - use crossbeam::{self, thread::Scope}; use falconeri_common::{ prelude::*, @@ -25,7 +22,6 @@ const USAGE: &str = "Usage: falconeri-worker "; #[tracing::instrument(level = "trace")] fn main() -> Result<()> { initialize_tracing(); - openssl_probe::init_ssl_cert_env_vars(); // Parse our arguments (manually, so we don't need to drag in a ton of // libraries). @@ -178,8 +174,8 @@ fn process_datum( /// /// This function will panic if `child` does not have a `stdout` or `stderr`. #[tracing::instrument(skip(to_record), level = "trace")] -fn tee_child<'a>( - scope: &'a Scope, +fn tee_child( + scope: &Scope, child: &mut process::Child, to_record: Arc>, ) -> Result<()> { @@ -239,9 +235,7 @@ fn tee_output( Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} // An actual error occurred. Err(e) => { - return Err(e) - .context("error reading from child process") - .map_err(Into::into); + return Err(e).context("error reading from child process"); } } } diff --git a/falconeri/Cargo.toml b/falconeri/Cargo.toml index 8d3370e..d962166 100644 --- a/falconeri/Cargo.toml +++ b/falconeri/Cargo.toml @@ -1,23 +1,20 @@ [package] authors = ["Eric Kidd "] name = "falconeri" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" edition = "2018" license = "Apache-2.0 OR MIT" [dependencies] -base64 = "0.21.2" -crossbeam = "0.8.1" +base64 = "0.22.1" +crossbeam = "0.8.4" falconeri_common = { path = "../falconeri_common" } -handlebars = "4.1.4" -log = "0.4.3" -# Needed for ekidd/rust-musl-builder. -openssl-sys = "*" -openssl-probe = "0.1.2" +handlebars = "6.3.2" +log = "0.4.29" prettytable-rs = "0.10.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -structopt = "0.3.25" -uuid = { version = "1.3.3", features = ["serde", "v4"] } +clap = { version = "4", features = ["derive"] } +uuid = { version = "1.19.0", features = ["serde", "v4"] } diff --git a/falconeri/src/cmd/datum/mod.rs b/falconeri/src/cmd/datum/mod.rs index 7db2935..cba3f94 100644 --- a/falconeri/src/cmd/datum/mod.rs +++ b/falconeri/src/cmd/datum/mod.rs @@ -1,18 +1,17 @@ //! The `datum` subcommand. +use clap::Parser; use falconeri_common::prelude::*; -use structopt::StructOpt; mod describe; /// `datum` options. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Opt { /// Describe a specific job. - #[structopt(name = "describe")] + #[command(name = "describe")] Describe { /// The UUID of the datum to describe. - #[structopt(parse(try_from_str))] id: Uuid, }, } diff --git a/falconeri/src/cmd/db.rs b/falconeri/src/cmd/db.rs index 354a3d6..103e2e2 100644 --- a/falconeri/src/cmd/db.rs +++ b/falconeri/src/cmd/db.rs @@ -1,17 +1,17 @@ //! `db` subcommand for interaction with the database. +use clap::Parser; use falconeri_common::{db, prelude::*}; use std::process; -use structopt::StructOpt; /// Commands for interacting with the database. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Opt { /// Access the database console. - #[structopt(name = "console")] + #[command(name = "console")] Console, /// Print our a URL for connecting to the database. - #[structopt(name = "url")] + #[command(name = "url")] Url, } diff --git a/falconeri/src/cmd/deploy.rs b/falconeri/src/cmd/deploy.rs index 7bb4226..4848a04 100644 --- a/falconeri/src/cmd/deploy.rs +++ b/falconeri/src/cmd/deploy.rs @@ -1,14 +1,14 @@ //! The `deploy` subcommand. use base64::{prelude::BASE64_STANDARD, Engine}; +use clap::Parser; use std::iter; -use structopt::StructOpt; use falconeri_common::{ kubernetes, manifest::render_manifest, prelude::*, - rand::{distributions::Alphanumeric, rngs::StdRng, Rng, SeedableRng}, + rand::{distr::Alphanumeric, Rng}, }; /// The manifest defining secrets for `falconeri`. @@ -59,62 +59,61 @@ struct DeployManifestParams { } /// Commands for interacting with the database. -#[derive(Debug, StructOpt)] -#[structopt(name = "deploy", about = "Commands for interacting with the database.")] +#[derive(Debug, Parser)] +#[command(name = "deploy", about = "Commands for interacting with the database.")] pub struct Opt { /// Just print out the manifest without deploying it. - #[structopt(long = "dry-run")] + #[arg(long = "dry-run")] dry_run: bool, /// Don't include a secret in the manifest. - #[structopt(long = "skip-secret")] + #[arg(long = "skip-secret")] skip_secret: bool, /// Deploy a development server (for minikube). - #[structopt(long = "development")] + #[arg(long = "development")] development: bool, /// The version of PostgreSQL to deploy. It's generally OK to specify just /// the major version, like "14". - #[structopt(long = "postgres-version", default_value = "14")] + #[arg(long = "postgres-version", default_value = "14")] postgres_version: String, /// The amount of disk to allocate for PostgreSQL. - #[structopt(long = "postgres-storage")] + #[arg(long = "postgres-storage")] postgres_storage: Option, /// The amount of RAM to request for PostgreSQL. - #[structopt(long = "postgres-memory")] + #[arg(long = "postgres-memory")] postgres_memory: Option, /// The number of CPUs to request for PostgreSQL. - #[structopt(long = "postgres-cpu")] + #[arg(long = "postgres-cpu")] postgres_cpu: Option, /// The number of copies of `falconerid` to run. - #[structopt(long = "falconerid-replicas")] + #[arg(long = "falconerid-replicas")] falconerid_replicas: Option, /// The amount of RAM to request for `falconerid`. - #[structopt(long = "falconerid-memory")] + #[arg(long = "falconerid-memory")] falconerid_memory: Option, /// The number of CPUs to request for `falconerid`. - #[structopt(long = "falconerid-cpu")] + #[arg(long = "falconerid-cpu")] falconerid_cpu: Option, /// Set the log level to be used for `falconerid`. This uses the same format /// as `RUST_LOG`. Example: `falconeri_common=debug,falconerid=debug,warn`. - #[structopt(long = "falconerid-log-level")] + #[arg(long = "falconerid-log-level")] falconerid_log_level: Option, } /// Deploy `falconeri` to the current Kubernetes cluster. pub fn run(opt: &Opt) -> Result<()> { // Generate a password using the system's "secure" random number generator. - let mut rng = StdRng::from_entropy(); - let postgres_password = iter::repeat(()) - .map(|()| rng.sample(Alphanumeric)) + let mut rng = falconeri_common::rand::rng(); + let postgres_password = iter::repeat_with(|| rng.sample(Alphanumeric)) .take(32) .collect::>(); diff --git a/falconeri/src/cmd/job/mod.rs b/falconeri/src/cmd/job/mod.rs index 9d6607e..a67f465 100644 --- a/falconeri/src/cmd/job/mod.rs +++ b/falconeri/src/cmd/job/mod.rs @@ -1,8 +1,8 @@ //! The `job` subcommand. +use clap::Parser; use falconeri_common::{pipeline::PipelineSpec, prelude::*}; use serde_json; -use structopt::StructOpt; mod describe; mod list; @@ -14,41 +14,40 @@ mod run; mod wait; /// The `job` subcommand. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Opt { /// Describe a specific job. - #[structopt(name = "describe")] + #[command(name = "describe")] Describe { /// The Kubernetes name of the job to describe. job_name: String, }, /// List all jobs. - #[structopt(name = "list")] + #[command(name = "list")] List, /// Retry failed datums. - #[structopt(name = "retry")] + #[command(name = "retry")] Retry { /// The name of the job for which to retry failed datums. job_name: String, }, /// Run the specified pipeline as a one-off job. - #[structopt(name = "run")] + #[command(name = "run")] Run { /// Path to a JSON pipeline spec. - #[structopt(parse(from_os_str))] pipeline_json: PathBuf, }, // Disabled because `BsonSchema` doesn't handle recursive types. // // /// Output a JSON schema for a falconeri job. - // #[structopt(name = "schema")] + // #[command(name = "schema")] // Schema, /// Wait for the specified job to finish, either successfully or with an /// error. - #[structopt(name = "wait")] + #[command(name = "wait")] Wait { /// The name of the job to wait for. job_name: String, @@ -59,7 +58,7 @@ pub enum Opt { pub fn run(opt: &Opt) -> Result<()> { match opt { Opt::Describe { job_name } => describe::run(job_name), - Opt::List {} => list::run(), + Opt::List => list::run(), Opt::Retry { job_name } => retry::run(job_name), Opt::Run { pipeline_json } => { let f = diff --git a/falconeri/src/main.rs b/falconeri/src/main.rs index 23296df..80e73b9 100644 --- a/falconeri/src/main.rs +++ b/falconeri/src/main.rs @@ -1,59 +1,56 @@ -// Needed for static linking to work right on Linux. -extern crate openssl_sys; - use std::{io::stderr, process}; +use clap::Parser; use falconeri_common::prelude::*; -use structopt::StructOpt; mod cmd; mod description; -/// Command-line options, parsed using `structopt`. -#[derive(Debug, StructOpt)] -#[structopt(about = "A tool for running batch jobs on Kubernetes.")] +/// Command-line options. +#[derive(Debug, Parser)] +#[command(about = "A tool for running batch jobs on Kubernetes.")] enum Opt { /// Datum-related commands. - #[structopt(name = "datum")] + #[command(name = "datum")] Datum { - #[structopt(subcommand)] + #[command(subcommand)] cmd: cmd::datum::Opt, }, /// Commands for accessing the database. - #[structopt(name = "db")] + #[command(name = "db")] Db { - #[structopt(subcommand)] + #[command(subcommand)] cmd: cmd::db::Opt, }, /// Deploy falconeri onto the current Docker cluster. - #[structopt(name = "deploy")] + #[command(name = "deploy")] Deploy { - #[structopt(flatten)] + #[command(flatten)] cmd: cmd::deploy::Opt, }, /// Job-related commands. - #[structopt(name = "job")] + #[command(name = "job")] Job { - #[structopt(subcommand)] + #[command(subcommand)] cmd: cmd::job::Opt, }, /// Manaually migrate falconeri's database schema to the latest version. - #[structopt(name = "migrate")] + #[command(name = "migrate")] Migrate, /// Create a proxy connection to the default Kubernetes cluster. - #[structopt(name = "proxy")] + #[command(name = "proxy")] Proxy, /// Undeploy `falconeri`, removing it from the cluster. - #[structopt(name = "undeploy")] + #[command(name = "undeploy")] Undeploy { /// Also delete the database volume and the secrets. - #[structopt(long = "all")] + #[arg(long = "all")] all: bool, }, } @@ -70,8 +67,7 @@ fn main() { /// The actual main code of the application. fn run() -> Result<()> { - openssl_probe::init_ssl_cert_env_vars(); - let opt = Opt::from_args(); + let opt = Opt::parse(); debug!("Args: {:?}", opt); match opt { diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index 7f05428..a6c36f2 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -1,30 +1,29 @@ [package] name = "falconeri_common" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" authors = ["Eric Kidd "] edition = "2018" license = "Apache-2.0 OR MIT" [dependencies] -anyhow = { version = "1.0.45", features = ["backtrace"] } -backoff = "0.4.0" -base64 = "0.21.2" +anyhow = { version = "1.0.100", features = ["backtrace"] } +base64 = "0.22.1" cast = { version = "0.3.0", features = ["std"] } -chrono = { version = "0.4.4", features = ["serde"] } -diesel = { version = "2.0.4", features = ["chrono", "postgres", "r2d2", "serde_json", "uuid"] } -diesel_migrations = "2.0.0" -handlebars = "4.1.4" -humantime-serde = "1.0.1" -lazy_static = "1.0.2" -r2d2 = "0.8.4" -rand = "0.8.4" -regex = "1.0.2" -reqwest = { version = "0.11.6", default-features = false, features = ["blocking", "json", "rustls-tls-native-roots"] } -semver = "1.0.4" -serde = "1.0.70" +chrono = { version = "0.4.42", features = ["serde"] } +diesel = { version = "2.3.4", features = ["chrono", "postgres", "r2d2", "serde_json", "uuid"] } +diesel_migrations = "2.3.1" +handlebars = "6.3.2" +humantime-serde = "1.1.1" +lazy_static = "1.5.0" +r2d2 = "0.8.10" +rand = "0.9.2" +regex = "1.12.2" +reqwest = { version = "0.12.24", default-features = false, features = ["blocking", "json", "rustls-tls-native-roots"] } +semver = "1.0.27" +serde = "1.0.228" serde_json = "1.0" -tracing = "0.1.29" -tracing-subscriber = { version = "0.3.2", features = ["env-filter"] } -url = "2.2.2" -uuid = { version = "1.3.3", features = ["serde", "v4"] } +tracing = "0.1.43" +tracing-subscriber = { version = "0.3.22", features = ["env-filter"] } +url = "2.5.7" +uuid = { version = "1.19.0", features = ["serde", "v4"] } diff --git a/falconeri_common/src/connect_via.rs b/falconeri_common/src/connect_via.rs index 563415b..554ddb4 100644 --- a/falconeri_common/src/connect_via.rs +++ b/falconeri_common/src/connect_via.rs @@ -1,7 +1,7 @@ //! How should we connect to PostgreSQL and `falconerid`? -use backoff::{self, retry, ExponentialBackoff}; -use std::result; +use std::thread; +use std::time::Duration; use crate::prelude::*; @@ -35,39 +35,35 @@ impl ConnectVia { /// Run the function `f`. If `self.should_retry_by_default()` is true, retry /// failures using exponential backoff. Return either the result or the final - /// final failure. + /// failure. #[tracing::instrument(skip(f), level = "trace")] pub fn retry_if_appropriate(self, mut f: F) -> Result where F: FnMut() -> Result, { - // Wrap `f` up into an operation that results am appropriate - // `backoff::Error` on failure. - let operation = || -> result::Result> { - f().map_err(|err| { - if self.should_retry_by_default() { + if !self.should_retry_by_default() { + return f(); + } + + const MAX_RETRIES: u32 = 10; + const INITIAL_INTERVAL: Duration = Duration::from_millis(500); + const MAX_INTERVAL: Duration = Duration::from_secs(60); + + let mut interval = INITIAL_INTERVAL; + let mut last_err = None; + + for _ in 0..MAX_RETRIES { + match f() { + Ok(value) => return Ok(value), + Err(err) => { error!("retrying after error: {}", err); - backoff::Error::Transient { - err, - retry_after: None, - } - } else { - backoff::Error::Permanent(err) + last_err = Some(err); + thread::sleep(interval); + interval = (interval * 2).min(MAX_INTERVAL); } - }) - }; - - // Specify what kind of backoff to use. - let backoff = ExponentialBackoff::default(); + } + } - // Run our operation, retrying if necessary. - let value = retry(backoff, operation) - // Unwrap the backoff error into something we can handle. This should - // have been built in. - .map_err(|e| match e { - backoff::Error::Transient { err, .. } => err, - backoff::Error::Permanent(err) => err, - })?; - Ok(value) + Err(last_err.unwrap()) } } diff --git a/falconeri_common/src/kubernetes.rs b/falconeri_common/src/kubernetes.rs index b09afa0..9ce8f29 100644 --- a/falconeri_common/src/kubernetes.rs +++ b/falconeri_common/src/kubernetes.rs @@ -1,7 +1,7 @@ //! Tools for talking to Kubernetes. -use rand::distributions::Alphanumeric; -use rand::{thread_rng, Rng}; +use rand::distr::Alphanumeric; +use rand::{rng, Rng}; use serde::de::{Deserialize, DeserializeOwned}; use serde_json; use std::collections::HashSet; @@ -242,12 +242,8 @@ pub fn delete(resource_id: &str) -> Result<()> { /// Kubernetes happy, this must be a legal DNS name component (but we have a /// database constraint to enforce that). pub fn resource_tag() -> String { - let mut rng = thread_rng(); - let bytes = iter::repeat(()) - // Note that this random distribution is biased, because we generate - // both upper and lowercase letters and then convert to lowercase - // later. This isn't a big deal for now. - .map(|()| rng.sample(Alphanumeric)) + let mut rng = rng(); + let bytes = iter::repeat_with(|| rng.sample(Alphanumeric)) // This needs to be large enough to avoid getting bit by // https://en.wikipedia.org/wiki/Birthday_problem. .take(10) diff --git a/falconeri_common/src/models/mod.rs b/falconeri_common/src/models/mod.rs index d4f4555..07d5ec6 100644 --- a/falconeri_common/src/models/mod.rs +++ b/falconeri_common/src/models/mod.rs @@ -92,7 +92,12 @@ impl ::diesel::serialize::ToSql for Status { impl ::diesel::deserialize::FromSql for Status { fn from_sql(bytes: ::RawValue<'_>) -> deserialize::Result { - match String::from_sql(bytes)?.as_str() { + match >::from_sql(bytes)? + .as_str() + { "ready" => Ok(Status::Ready), "running" => Ok(Status::Running), "done" => Ok(Status::Done), diff --git a/falconeri_common/src/rest_api.rs b/falconeri_common/src/rest_api.rs index a11baa2..ca8ead8 100644 --- a/falconeri_common/src/rest_api.rs +++ b/falconeri_common/src/rest_api.rs @@ -2,7 +2,6 @@ use reqwest::blocking as reqwest; use serde::de::DeserializeOwned; -use std::usize; use url::Url; use crate::db; diff --git a/falconerid/Cargo.toml b/falconerid/Cargo.toml index 5f628e8..3da9fa7 100644 --- a/falconerid/Cargo.toml +++ b/falconerid/Cargo.toml @@ -1,25 +1,19 @@ [package] name = "falconerid" -version = "1.0.0-beta.12" +version = "1.0.0-beta.13" authors = ["Eric Kidd "] edition = "2018" license = "Apache-2.0 OR MIT" [dependencies] -axum = { version = "0.6.18", features = ["macros", "tracing"] } +axum = { version = "0.8.7", features = ["macros", "tracing"] } falconeri_common = { path = "../falconeri_common" } -headers = "0.3.5" -# Needed for ekidd/rust-musl-builder. -openssl-sys = "*" -openssl-probe = "0.1.2" -# Newer versions after 0.5.0-rc.1 require uuid 1.0.0, which requires diesel 2.0. -rocket = { version = "=0.5.0-rc.3", features = ["json", "uuid"] } -# We also need to lock down rocket's supporting modules. -rocket_codegen = "=0.5.0-rc.3" -rocket_http = "=0.5.0-rc.3" +headers = "0.4.1" +rocket = { version = "0.5.1", features = ["json", "uuid"] } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" serde_yaml = "0.9" +tracing = "0.1.43" diff --git a/falconerid/src/main.rs b/falconerid/src/main.rs index 9ef7e45..36717b4 100644 --- a/falconerid/src/main.rs +++ b/falconerid/src/main.rs @@ -1,6 +1,3 @@ -// Needed for static linking to work right on Linux. -extern crate openssl_sys; - use falconeri_common::{ db, falconeri_common_version, pipeline::PipelineSpec, @@ -209,7 +206,6 @@ fn patch_output_files( #[launch] fn rocket() -> _ { initialize_tracing(); - openssl_probe::init_ssl_cert_env_vars(); if let Err(err) = initialize_server() { eprintln!( diff --git a/falconerid/src/util.rs b/falconerid/src/util.rs index 5133453..f8e706e 100644 --- a/falconerid/src/util.rs +++ b/falconerid/src/util.rs @@ -64,14 +64,14 @@ impl<'r> FromRequest<'r> for DbConn { // Try to get the connection pool attached to our server. let pool = match request.guard::<&State>().await { Outcome::Success(pool) => pool, - Outcome::Failure(failure) => return Outcome::Failure(failure), + Outcome::Error(err) => return Outcome::Error(err), Outcome::Forward(forward) => return Outcome::Forward(forward), }; // Get a connection. match pool.0.get() { Ok(conn) => Outcome::Success(DbConn(conn)), - Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())), + Err(_) => Outcome::Error((Status::ServiceUnavailable, ())), } } } @@ -134,15 +134,15 @@ impl<'r> FromRequest<'r> for User { Ok(None) => { // TODO: Should send `WWW-Authenticate: Basic // realm="falconeri"`. - return Outcome::Failure((Status::Unauthorized, ())); + return Outcome::Error((Status::Unauthorized, ())); } - Err(_) => return Outcome::Failure((Status::BadRequest, ())), + Err(_) => return Outcome::Error((Status::BadRequest, ())), }; // Get the admin password for our server. let password = match request.guard::<&State>().await { Outcome::Success(password) => password, - Outcome::Failure(failure) => return Outcome::Failure(failure), + Outcome::Error(err) => return Outcome::Error(err), Outcome::Forward(forward) => return Outcome::Forward(forward), }; @@ -150,7 +150,7 @@ impl<'r> FromRequest<'r> for User { if auth.0.username() == "falconeri" && auth.0.password() == password.0 { Outcome::Success(User) } else { - Outcome::Failure((Status::Unauthorized, ())) + Outcome::Error((Status::Unauthorized, ())) } } } From b60400810d09b8257d7146a68b8fdbdfd541fd8f Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 15:45:33 -0500 Subject: [PATCH 02/28] run a full test in minikube MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✓ Profile falconeri-gcs-test already exists $ minikube status -p falconeri-gcs-test -o json ✓ falconeri-gcs-test is already running Setting kubectl context to test profile... $ kubectl config use-context falconeri-gcs-test Switched to context "falconeri-gcs-test". ✓ minikube setup complete ⚠️ Using dedicated minikube profile 'falconeri-gcs-test' === Cleaning up resources from previous runs === $ kubectl config current-context ✓ Using correct context: falconeri-gcs-test Killing kubectl port-forward processes... $ pgrep -f kubectl port-forward Killing kubectl port-forward process 61293 $ kill 61293 Deleting old gcs-test jobs... $ kubectl get jobs -o name No old gcs-test jobs found Deleting old falconerid deployment... $ kubectl delete deployment falconerid --wait=false Deleted falconerid deployment Deleting old replica sets... $ kubectl delete replicaset -l app=falconerid --wait=false Deleting old secrets... $ kubectl delete secret gcs --wait=false $ kubectl delete secret gcs-credentials --wait=false Waiting for resources to be deleted... ✓ Cleanup complete === Uploading test data to gs://faraday-falconeri-test/falconeri-test-f00e2e116581/input/sample.txt === $ gsutil cp /Users/seamus/code/rust/falconeri/examples/gcs-test/sample.txt gs://faraday-falconeri-test/falconeri-test-f00e2e116581/input/sample.txt Copying file:///Users/seamus/code/rust/falconeri/examples/gcs-test/sample.txt [Content-Type=text/plain]... / [1 files][ 242.0 B/ 242.0 B] Operation completed over 1 objects/242.0 B. === Building falconeri Docker image === $ minikube image build -t falconeri-local:test -f Dockerfile . -p falconeri-gcs-test #0 building with "default" instance using docker driver #1 [internal] load build definition from Dockerfile #1 transferring dockerfile: 1.85kB done #1 DONE 0.0s #2 [internal] load metadata for docker.io/library/ubuntu:25.10 #2 DONE 0.3s #3 [internal] load .dockerignore #3 transferring context: 76B done #3 DONE 0.0s #4 [ 1/13] FROM docker.io/library/ubuntu:25.10@sha256:4a9232cc47bf99defcc8860ef6222c99773330367fcecbf21ba2edb0b810a31e #4 DONE 0.0s #5 [internal] load build context #5 transferring context: 304.85kB done #5 DONE 0.0s #6 [ 3/13] ADD https://storage.googleapis.com/kubernetes-release/release/v1.13.4/bin/linux/amd64/kubectl /usr/local/bin/kubectl #6 DONE 0.1s #7 [ 7/13] COPY falconeri ./falconeri #7 CACHED #8 [ 4/13] RUN chmod +x /usr/local/bin/kubectl #8 CACHED #9 [ 3/13] ADD https://storage.googleapis.com/kubernetes-release/release/v1.13.4/bin/linux/amd64/kubectl /usr/local/bin/kubectl #9 CACHED #10 [ 8/13] COPY falconerid ./falconerid #10 CACHED #11 [ 6/13] COPY Cargo.toml Cargo.lock ./ #11 CACHED #12 [ 9/13] COPY falconeri-worker ./falconeri-worker #12 CACHED #13 [ 5/13] WORKDIR /build #13 CACHED #14 [12/13] WORKDIR /app #14 CACHED #15 [11/13] RUN if [ "debug" = "release" ]; then cargo build --release --bin falconerid --bin falconeri-worker && cp target/release/falconerid target/release/falconeri-worker /usr/local/bin/; else cargo build --bin falconerid --bin falconeri-worker && cp target/debug/falconerid target/debug/falconeri-worker /usr/local/bin/; fi #15 CACHED #16 [ 2/13] RUN apt-get update && apt-get install -y curl build-essential libssl-dev pkg-config libpq-dev bash openssh-client git gnupg ca-certificates unzip && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip && ./aws/install && rm -rf awscliv2.zip aws && rm -rf /var/lib/apt/lists/* #16 CACHED #17 [10/13] COPY falconeri_common ./falconeri_common #17 CACHED #18 [13/13] ADD falconerid/Rocket.toml . #18 CACHED #19 exporting to image #19 exporting layers done #19 writing image sha256:61dc0e66ab00d9f84159bda9e9fcb04c925e671a201af109fe574142eb375af8 done #19 naming to docker.io/library/falconeri-local:test done #19 DONE 0.0s WARNING: current commit information was not captured by the build: git was not found in the system: exec: "git": executable file not found in $PATH ✓ Built falconeri-local:test in minikube === Creating Kubernetes secret === $ kubectl config current-context ✓ Using correct context: falconeri-gcs-test $ kubectl create secret generic gcs-credentials --from-literal=xxx secret/gcs-credentials created === Deploying falconeri infrastructure === $ kubectl config current-context ✓ Using correct context: falconeri-gcs-test $ cargo run -p falconeri -- deploy Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.61s Running `target/debug/falconeri deploy` persistentvolumeclaim/falconeri-postgres unchanged deployment.apps/falconeri-postgres unchanged service/falconeri-postgres unchanged deployment.apps/falconerid created service/falconerid unchanged serviceaccount/falconerid unchanged role.rbac.authorization.k8s.io/falconerid unchanged rolebinding.rbac.authorization.k8s.io/falconerid unchanged Updating deployment to use falconeri-local:test with imagePullPolicy: Never and 1 replica... $ kubectl patch deployment/falconerid --type json -p [{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "falconeri-local:test"}, {"op": "replace", "path": "/spec/template/spec/containers/0/imagePullPolicy", "value": "Never"}, {"op": "replace", "path": "/spec/replicas", "value": 1}] deployment.apps/falconerid patched Waiting for rollout to start... Cleaning up old replica sets... $ kubectl get replicaset -l app=falconerid -o name $ kubectl get replicaset.apps/falconerid-56c8976f5 -o jsonpath='{.spec.replicas}' Keeping active replica set: replicaset.apps/falconerid-56c8976f5 (replicas=1) $ kubectl get replicaset.apps/falconerid-56f674f58f -o jsonpath='{.spec.replicas}' Deleting old replica set: replicaset.apps/falconerid-56f674f58f $ kubectl delete replicaset.apps/falconerid-56f674f58f replicaset.apps "falconerid-56f674f58f" deleted from default namespace Waiting for falconeri deployments to be ready... $ kubectl wait --for=condition=available deployment/falconerid --timeout=300s deployment.apps/falconerid condition met $ kubectl wait --for=condition=available deployment/falconeri-postgres --timeout=300s deployment.apps/falconeri-postgres condition met ✓ Falconeri infrastructure is ready === Building test Docker image (with Rust compilation) === $ cp /Users/seamus/code/rust/falconeri/examples/word-frequencies/word-frequencies.sh /Users/seamus/code/rust/falconeri/word-frequencies.sh $ minikube image build -f examples/gcs-test/Dockerfile -t gcs-test . -p falconeri-gcs-test #0 building with "default" instance using docker driver #1 [internal] load build definition from Dockerfile #1 transferring dockerfile: 765B done #1 DONE 0.0s #2 [internal] load metadata for docker.io/library/rust:latest #2 DONE 0.2s #3 [internal] load metadata for docker.io/library/ubuntu:25.10 #3 DONE 0.2s #4 [internal] load .dockerignore #4 transferring context: 76B done #4 DONE 0.0s #5 [builder 1/9] FROM docker.io/library/rust:latest@sha256:65734d21f103d104fe0d9e508a424f7f60abd10e489d36de8bd36ae6c80e746d #5 DONE 0.0s #6 [stage-1 1/4] FROM docker.io/library/ubuntu:25.10@sha256:4a9232cc47bf99defcc8860ef6222c99773330367fcecbf21ba2edb0b810a31e #6 DONE 0.0s #7 [internal] load build context #7 transferring context: 305.24kB done #7 DONE 0.0s #8 [builder 7/9] COPY falconeri ./falconeri #8 CACHED #9 [stage-1 3/4] COPY --from=builder /build/target/debug/falconeri-worker /usr/local/bin/ #9 CACHED #10 [builder 5/9] COPY falconeri-worker ./falconeri-worker #10 CACHED #11 [builder 6/9] COPY falconeri_common ./falconeri_common #11 CACHED #12 [builder 3/9] WORKDIR /build #12 CACHED #13 [builder 4/9] COPY Cargo.toml Cargo.lock ./ #13 CACHED #14 [builder 9/9] RUN cargo build -p falconeri-worker #14 CACHED #15 [builder 2/9] RUN apt-get update && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/* #15 CACHED #16 [builder 8/9] COPY falconerid ./falconerid #16 CACHED #17 [stage-1 2/4] RUN apt-get update && apt-get install -y ca-certificates libpq5 && apt-get clean && rm -rf /var/lib/apt/lists/* #17 CACHED #18 [stage-1 4/4] ADD word-frequencies.sh /usr/local/bin/ #18 CACHED #19 exporting to image #19 exporting layers done #19 writing image sha256:893bdc35473c487aae59d3507a82898337a97705f253230491dabf6bb729440c done #19 naming to docker.io/library/gcs-test done #19 DONE 0.0s WARNING: current commit information was not captured by the build: git was not found in the system: exec: "git": executable file not found in $PATH === Verifying Docker images === Verifying falconeri-local:test: Checking /usr/local/bin/falconerid in falconeri-local:test... $ minikube -p falconeri-gcs-test ssh -- docker run --rm falconeri-local:test file /usr/local/bin/falconerid ❌ Could not check /usr/local/bin/falconerid Checking /usr/local/bin/falconeri-worker in falconeri-local:test... $ minikube -p falconeri-gcs-test ssh -- docker run --rm falconeri-local:test file /usr/local/bin/falconeri-worker ❌ Could not check /usr/local/bin/falconeri-worker Checking /usr/local/bin/kubectl in falconeri-local:test... $ minikube -p falconeri-gcs-test ssh -- docker run --rm falconeri-local:test file /usr/local/bin/kubectl ❌ Could not check /usr/local/bin/kubectl Verifying gcs-test: Checking /usr/local/bin/falconeri-worker in gcs-test... $ minikube -p falconeri-gcs-test ssh -- docker run --rm gcs-test file /usr/local/bin/falconeri-worker ❌ Could not check /usr/local/bin/falconeri-worker Checking /usr/local/bin/word-frequencies.sh in gcs-test... $ minikube -p falconeri-gcs-test ssh -- docker run --rm gcs-test file /usr/local/bin/word-frequencies.sh ❌ Could not check /usr/local/bin/word-frequencies.sh ⚠️ Some image verifications failed, but continuing... (This may be expected if architecture differs) === Generated pipeline spec at /Users/seamus/code/rust/falconeri/examples/gcs-test/gcs-test.json === === Starting falconeri proxy === $ cargo run -p falconeri -- proxy Waiting for proxy to be ready... Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.44s Running `target/debug/falconeri proxy` Forwarding from 127.0.0.1:8089 -> 8089 Forwarding from [::1]:8089 -> 8089 Forwarding from 127.0.0.1:5432 -> 5432 Forwarding from [::1]:5432 -> 5432 Handling connection for 8089 ✓ Proxy is ready === Running falconeri job === $ kubectl config current-context ✓ Using correct context: falconeri-gcs-test $ cargo run -p falconeri -- job run /Users/seamus/code/rust/falconeri/examples/gcs-test/gcs-test.json Handling connection for 8089 gcs-test-ph1viw9umy Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.20s Running `target/debug/falconeri job run /Users/seamus/code/rust/falconeri/examples/gcs-test/gcs-test.json` === Waiting for job gcs-test-ph1viw9umy to complete === $ kubectl config current-context ✓ Using correct context: falconeri-gcs-test $ cargo run -p falconeri -- job describe gcs-test-ph1viw9umy Handling connection for 5432 Job still running... (0s elapsed) $ cargo run -p falconeri -- job describe gcs-test-ph1viw9umy Handling connection for 5432 Job gcs-test-ph1viw9umy completed successfully! === Verifying output === $ gsutil ls gs://faraday-falconeri-test/falconeri-test-f00e2e116581/output/sample.txt Output file exists at gs://faraday-falconeri-test/falconeri-test-f00e2e116581/output/sample.txt $ gsutil cp gs://faraday-falconeri-test/falconeri-test-f00e2e116581/output/sample.txt /var/folders/y5/qt_wf5l52jd12gzd8dxfqpt40000gp/T/tmp7xqe3bh3 Copying gs://faraday-falconeri-test/falconeri-test-f00e2e116581/output/sample.txt... Downloading to temp gzip filename /var/folders/y5/qt_wf5l52jd12gzd8dxfqpt40000gp/T/tmp7xqe3bh3_.gztmp / [1 files][ 187.0 B/ 187.0 B] Operation completed over 1 objects/187.0 B. Output contents: 5 the 3 a 2 to 2 that 2 not 2 is 2 be 1 worm 1 words 1 with 1 thousand 1 than 1 step 1 speak 1 single 1 quick 1 question 1 over 1 or 1 of 1 miles 1 louder 1 lazy 1 jumps 1 journey 1 gold 1 glitters 1 fox 1 early 1 dog 1 catches 1 brown 1 bird 1 begins 1 all 1 actions Success! Output contains 36 lines of word frequencies === Cleaning up === Stopping proxy... Killing kubectl port-forward processes... $ pgrep -f kubectl port-forward Killing kubectl port-forward process 62054 $ kill 62054 Killing kubectl port-forward process 62057 $ kill 62057 Deleting GCS test files... $ gsutil -m rm -r gs://faraday-falconeri-test/falconeri-test-f00e2e116581/ If you experience problems with multiprocessing on MacOS, they might be related to https://bugs.python.org/issue33725. You can disable multiprocessing by editing your .boto config or by adding the following flag to your command: `-o "GSUtil:parallel_process_count=1"`. Note that multithreading is still available even if you disable multiprocessing. Removing gs://faraday-falconeri-test/falconeri-test-f00e2e116581/output/sample.txt#1767559295122682... Removing gs://faraday-falconeri-test/falconeri-test-f00e2e116581/input/sample.txt#1767559277510927... / [2/2 objects] 100% Done Operation completed over 2 objects. If you experience problems with multiprocessing on MacOS, they might be related to https://bugs.python.org/issue33725. You can disable multiprocessing by editing your .boto config or by adding the following flag to your command: `-o "GSUtil:parallel_process_count=1"`. Note that multithreading is still available even if you disable multiprocessing. Deleting k8s secrets... $ kubectl config current-context ✓ Using correct context: falconeri-gcs-test $ kubectl delete secret gcs Error from server (NotFound): secrets "gcs" not found $ kubectl delete secret gcs-credentials secret "gcs-credentials" deleted from default namespace ================================================== ✓ GCS integration test PASSED --- .gitignore | 1 + CHANGELOG.md | 6 + Cargo.lock | 1080 +++++++++++++++-- Dockerfile | 94 +- deny.toml | 9 +- examples/gcs-test/BUILD_VERIFICATION.md | 53 + examples/gcs-test/Dockerfile | 29 + examples/gcs-test/README.md | 52 + examples/gcs-test/justfile | 25 + examples/gcs-test/sample.txt | 7 + examples/gcs-test/test_gcs.py | 813 +++++++++++++ examples/word-frequencies/word-frequencies.sh | 2 +- falconeri/src/cmd/deploy_manifest.yml.hbs | 5 + falconeri_common/Cargo.toml | 10 +- falconeri_common/src/db.rs | 2 +- falconeri_common/src/storage/gs.rs | 283 ++++- guide/src/images.md | 14 +- guide/src/installation.md | 10 +- 18 files changed, 2271 insertions(+), 224 deletions(-) create mode 100644 examples/gcs-test/BUILD_VERIFICATION.md create mode 100644 examples/gcs-test/Dockerfile create mode 100644 examples/gcs-test/README.md create mode 100644 examples/gcs-test/justfile create mode 100644 examples/gcs-test/sample.txt create mode 100755 examples/gcs-test/test_gcs.py diff --git a/.gitignore b/.gitignore index 8f511bd..ff35bcd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ **/*.rs.bk /bin/ /examples/word-frequencies/falconeri-worker +*.pyc \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d45f311..d497f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.0-beta.13] - 2025-12-03 +### Added + +- Native Google Cloud Storage (GCS) support using the official `google-cloud-rust` SDK. +- Support for `gs://` URIs with automatic compression/decompression. +- Authentication via `GCLOUD_SERVICE_ACCOUNT_KEY` environment variable or standard Application Default Credentials. + ### Changed - Updated all dependencies to latest versions. diff --git a/Cargo.lock b/Cargo.lock index ec5593f..c94deb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,11 +154,33 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" dependencies = [ "axum-core", "axum-macros", @@ -190,9 +212,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", @@ -260,11 +282,36 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bon" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebeb9aaf9329dff6ceb65c689ca3db33dbf15f324909c60e4e5eef5701ce31b1" +dependencies = [ + "bon-macros", + "rustversion", +] + +[[package]] +name = "bon-macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e9d642a7e3a318e37c2c9427b5a6a48aa1ad55dcd986f3034ab2239045a645" +dependencies = [ + "darling 0.21.3", + "ident_case", + "prettyplease", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytemuck" @@ -283,6 +330,9 @@ name = "bytes" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +dependencies = [ + "serde", +] [[package]] name = "cast" @@ -292,14 +342,22 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.48" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.4" @@ -328,9 +386,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -338,9 +396,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -366,12 +424,31 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "cookie" version = "0.18.1" @@ -408,6 +485,24 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32c" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -572,6 +667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", + "serde_core", ] [[package]] @@ -640,9 +736,9 @@ dependencies = [ [[package]] name = "diesel" -version = "2.3.4" +version = "2.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c415189028b232660655e4893e8bc25ca7aee8e96888db66d9edb400535456a" +checksum = "e130c806dccc85428c564f2dc5a96e05b6615a27c9a28776bd7761a9af4bb552" dependencies = [ "bitflags", "byteorder", @@ -658,9 +754,9 @@ dependencies = [ [[package]] name = "diesel_derives" -version = "2.3.5" +version = "2.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8587cbca3c929fb198e7950d761d31ca72b80aa6e07c1b7bec5879d187720436" +checksum = "c30b2969f923fa1f73744b92bb7df60b858df8832742d9a3aceb79236c0be1d2" dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", @@ -751,6 +847,18 @@ dependencies = [ "syn", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "either" version = "1.15.0" @@ -847,20 +955,28 @@ version = "1.0.0-beta.13" dependencies = [ "anyhow", "base64", + "bytes", "cast", "chrono", "diesel", "diesel_migrations", + "flate2", + "futures", + "glob", + "google-cloud-auth", + "google-cloud-storage", "handlebars", "humantime-serde", "lazy_static", "r2d2", "rand 0.9.2", "regex", - "reqwest", + "reqwest 0.13.1", "semver", "serde", "serde_json", + "tokio", + "tokio-util", "tracing", "tracing-subscriber", "url", @@ -904,9 +1020,19 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" + +[[package]] +name = "flate2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] [[package]] name = "fnv" @@ -923,6 +1049,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.31" @@ -931,6 +1063,7 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -953,12 +1086,34 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -980,6 +1135,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -1050,6 +1206,214 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "google-cloud-auth" +version = "1.3.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "async-trait", + "base64", + "bon", + "bytes", + "google-cloud-gax", + "http 1.4.0", + "reqwest 0.12.28", + "rustc_version", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "thiserror 2.0.17", + "time", + "tokio", +] + +[[package]] +name = "google-cloud-gax" +version = "1.5.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "base64", + "bytes", + "futures", + "google-cloud-rpc", + "google-cloud-wkt", + "http 1.4.0", + "pin-project", + "rand 0.9.2", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", +] + +[[package]] +name = "google-cloud-gax-internal" +version = "0.7.7" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "bytes", + "futures", + "google-cloud-auth", + "google-cloud-gax", + "google-cloud-rpc", + "google-cloud-wkt", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "opentelemetry-semantic-conventions", + "percent-encoding", + "pin-project", + "prost", + "prost-types", + "reqwest 0.12.28", + "rustc_version", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tonic", + "tonic-prost", + "tower", + "tracing", +] + +[[package]] +name = "google-cloud-iam-v1" +version = "1.2.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "async-trait", + "bytes", + "google-cloud-gax", + "google-cloud-gax-internal", + "google-cloud-type", + "google-cloud-wkt", + "lazy_static", + "reqwest 0.12.28", + "serde", + "serde_json", + "serde_with", + "tracing", +] + +[[package]] +name = "google-cloud-longrunning" +version = "1.3.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "async-trait", + "bytes", + "google-cloud-gax", + "google-cloud-gax-internal", + "google-cloud-rpc", + "google-cloud-wkt", + "lazy_static", + "reqwest 0.12.28", + "serde", + "serde_json", + "serde_with", + "tracing", +] + +[[package]] +name = "google-cloud-lro" +version = "1.2.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "google-cloud-gax", + "google-cloud-longrunning", + "google-cloud-rpc", + "google-cloud-wkt", + "serde", + "tokio", +] + +[[package]] +name = "google-cloud-rpc" +version = "1.2.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "bytes", + "google-cloud-wkt", + "serde", + "serde_json", + "serde_with", +] + +[[package]] +name = "google-cloud-storage" +version = "1.6.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "async-trait", + "base64", + "bytes", + "chrono", + "crc32c", + "futures", + "google-cloud-auth", + "google-cloud-gax", + "google-cloud-gax-internal", + "google-cloud-iam-v1", + "google-cloud-longrunning", + "google-cloud-lro", + "google-cloud-rpc", + "google-cloud-type", + "google-cloud-wkt", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", + "lazy_static", + "md5", + "mime", + "percent-encoding", + "pin-project", + "prost", + "prost-types", + "reqwest 0.12.28", + "serde", + "serde_json", + "serde_with", + "sha2", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "google-cloud-type" +version = "1.2.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "bytes", + "google-cloud-wkt", + "serde", + "serde_json", + "serde_with", +] + +[[package]] +name = "google-cloud-wkt" +version = "1.2.0" +source = "git+https://github.com/googleapis/google-cloud-rust.git#275f0b9c7b1c7af8d83c18734ec8974b12717ecb" +dependencies = [ + "base64", + "bytes", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.17", + "time", + "url", +] + [[package]] name = "h2" version = "0.3.27" @@ -1062,7 +1426,26 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.12.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.4.0", + "indexmap 2.12.1", "slab", "tokio", "tokio-util", @@ -1071,9 +1454,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "6.3.2" +version = "6.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098" +checksum = "9b3f9296c208515b87bd915a2f5d1163d4b3f863ba83337d7713cf478055948e" dependencies = [ "derive_builder", "log", @@ -1085,6 +1468,12 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.16.1" @@ -1127,6 +1516,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "http" version = "0.2.12" @@ -1220,7 +1615,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -1244,6 +1639,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", + "h2 0.4.12", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -1266,11 +1662,24 @@ dependencies = [ "hyper 1.8.1", "hyper-util", "rustls", - "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper 1.8.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", ] [[package]] @@ -1369,9 +1778,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", @@ -1383,9 +1792,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" @@ -1429,6 +1838,17 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.12.1" @@ -1436,7 +1856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", "serde", "serde_core", ] @@ -1455,9 +1875,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -1480,17 +1900,26 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +checksum = "a87d9b8105c23642f50cbbae03d1f75d8422c5cb98ce7ee9271f7ff7505be6b8" dependencies = [ "jiff-static", "log", @@ -1501,15 +1930,47 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +checksum = "b787bebb543f8969132630c51fd0afab173a86c6abae56ff3b9e5e3e3f9f6e58" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.83" @@ -1528,15 +1989,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags", "libc", @@ -1605,6 +2066,12 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "md5" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" + [[package]] name = "memchr" version = "2.7.6" @@ -1618,7 +2085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d" dependencies = [ "serde", - "toml 0.9.8", + "toml 0.9.10+spec-1.1.0", ] [[package]] @@ -1638,6 +2105,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1645,13 +2122,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "wasi", @@ -1749,9 +2227,15 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "e62e29dfe041afb8ed2a6c9737ab57db4907285d999ef8ad3a59092a36bdc846" [[package]] name = "parking_lot" @@ -1807,9 +2291,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" +checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" dependencies = [ "memchr", "ucd-trie", @@ -1817,9 +2301,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" +checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" dependencies = [ "pest", "pest_generator", @@ -1827,9 +2311,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" +checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" dependencies = [ "pest", "pest_meta", @@ -1840,14 +2324,34 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" +checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" dependencies = [ "pest", "sha2", ] +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -1868,9 +2372,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "portable-atomic-util" @@ -1916,6 +2420,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "prettytable-rs" version = "0.10.0" @@ -1932,9 +2446,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ "unicode-ident", ] @@ -1952,6 +2466,38 @@ dependencies = [ "yansi", ] +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +dependencies = [ + "prost", +] + [[package]] name = "quinn" version = "0.11.9" @@ -1978,6 +2524,7 @@ version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -2163,13 +2710,12 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" -version = "0.12.24" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", - "futures-channel", "futures-core", "futures-util", "http 1.4.0", @@ -2180,11 +2726,11 @@ dependencies = [ "hyper-util", "js-sys", "log", + "mime_guess", "percent-encoding", "pin-project-lite", "quinn", "rustls", - "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -2192,6 +2738,48 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "reqwest" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "sync_wrapper", + "tokio", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -2229,7 +2817,7 @@ dependencies = [ "either", "figment", "futures", - "indexmap", + "indexmap 2.12.1", "log", "memchr", "multer", @@ -2262,7 +2850,7 @@ checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" dependencies = [ "devise", "glob", - "indexmap", + "indexmap 2.12.1", "proc-macro2", "quote", "rocket_http", @@ -2282,7 +2870,7 @@ dependencies = [ "futures", "http 0.2.12", "hyper 0.14.32", - "indexmap", + "indexmap 2.12.1", "log", "memchr", "pear", @@ -2311,11 +2899,20 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags", "errno", @@ -2330,6 +2927,8 @@ version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "aws-lc-rs", + "log", "once_cell", "ring", "rustls-pki-types", @@ -2340,9 +2939,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -2352,20 +2951,48 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -2379,9 +3006,18 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" + +[[package]] +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "schannel" @@ -2401,6 +3037,30 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -2474,15 +3134,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -2507,9 +3167,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ "serde_core", ] @@ -2526,13 +3186,44 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.12.1", + "schemars 0.9.0", + "schemars 1.2.0", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_yaml" version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap", + "indexmap 2.12.1", "itoa", "ryu", "serde", @@ -2578,13 +3269,20 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + [[package]] name = "slab" version = "0.4.11" @@ -2661,9 +3359,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.111" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -2692,9 +3390,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.23.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", "getrandom 0.3.4", @@ -2821,9 +3519,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -2858,9 +3556,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -2869,12 +3567,13 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -2894,13 +3593,13 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.8" +version = "0.9.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" dependencies = [ "serde_core", - "serde_spanned 1.0.3", - "toml_datetime 0.7.3", + "serde_spanned 1.0.4", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", ] @@ -2916,9 +3615,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ "serde_core", ] @@ -2929,7 +3628,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap", + "indexmap 2.12.1", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -2939,9 +3638,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] @@ -2952,6 +3651,44 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "tonic" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +dependencies = [ + "base64", + "bytes", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "rustls-native-certs", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +dependencies = [ + "bytes", + "prost", + "tonic", +] + [[package]] name = "tower" version = "0.5.2" @@ -2960,9 +3697,12 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", + "indexmap 2.12.1", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -2970,9 +3710,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "bitflags", "bytes", @@ -3000,9 +3740,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -3023,9 +3763,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -3097,6 +3837,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.22" @@ -3181,6 +3927,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -3263,6 +4019,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.83" @@ -3283,6 +4052,24 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3299,6 +4086,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3373,6 +4169,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -3400,6 +4205,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -3448,6 +4268,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3466,6 +4292,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3484,6 +4316,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3514,6 +4352,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3532,6 +4376,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3550,6 +4400,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3568,6 +4424,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3718,3 +4580,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e0d8dffbae3d840f64bda38e28391faef673a7b5a6017840f2a106c8145868" diff --git a/Dockerfile b/Dockerfile index c4273e8..8ec841e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,49 +1,61 @@ -# Use Alpine as a base image, because it's small. We need `edge` to get -# `aws-cli`. -FROM alpine:3.14 - -# Install `gsutil`. Taken from -# https://github.com/GoogleCloudPlatform/cloud-sdk-docker/blob/master/alpine/Dockerfile. -ARG CLOUD_SDK_VERSION=364.0.0 -ENV CLOUD_SDK_VERSION=$CLOUD_SDK_VERSION -ENV PATH /google-cloud-sdk/bin:$PATH -RUN apk --no-cache --update add \ - curl \ - python3 \ - py-crcmod \ - bash \ - libc6-compat \ - openssh-client \ - git \ - gnupg \ - && curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz && \ - tar xzf google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz && \ - rm google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz && \ - ln -s /lib /lib64 && \ - gcloud config set core/disable_usage_reporting true && \ - gcloud config set component_manager/disable_update_check true && \ - gcloud config set metrics/environment github_docker_image && \ - gcloud --version -VOLUME ["/root/.config"] - -# Install `awscli`. -RUN echo http://dl-cdn.alpinelinux.org/alpine/edge/testing/ >> /etc/apk/repositories && \ - apk --no-cache --update add aws-cli - -# Install `kubectl`. +# Single stage build for testing +# Note: No platform specified - uses native architecture of build environment (minikube VM) +FROM ubuntu:25.10 + +# Install Rust, build dependencies, and runtime utilities +RUN apt-get update && apt-get install -y \ + curl \ + build-essential \ + libssl-dev \ + pkg-config \ + libpq-dev \ + bash \ + openssh-client \ + git \ + gnupg \ + ca-certificates \ + unzip \ + && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip awscliv2.zip \ + && ./aws/install \ + && rm -rf awscliv2.zip aws \ + && rm -rf /var/lib/apt/lists/* + +# Add Rust to PATH +ENV PATH="/root/.cargo/bin:${PATH}" + +# Install kubectl ARG KUBERNETES_VERSION=1.13.4 +ARG TARGETARCH=amd64 ENV KUBERNETES_VERSION=$KUBERNETES_VERSION -ADD https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl /usr/local/bin/kubectl +ADD https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/${TARGETARCH}/kubectl /usr/local/bin/kubectl RUN chmod +x /usr/local/bin/kubectl -# Run our webserver out of /app. -WORKDIR /app +# Set working directory +WORKDIR /build -# Configure our Rocket webserver. -ADD falconerid/Rocket.toml . +# Copy workspace files +COPY Cargo.toml Cargo.lock ./ +COPY falconeri ./falconeri +COPY falconerid ./falconerid +COPY falconeri-worker ./falconeri-worker +COPY falconeri_common ./falconeri_common -# Build target. +# Build target ARG MODE=debug -# Copy static executables into container. -ADD bin/${MODE}/falconerid bin/${MODE}/falconeri-worker /usr/local/bin/ +# Build the binaries +RUN if [ "$MODE" = "release" ]; then \ + cargo build --release --bin falconerid --bin falconeri-worker && \ + cp target/release/falconerid target/release/falconeri-worker /usr/local/bin/; \ + else \ + cargo build --bin falconerid --bin falconeri-worker && \ + cp target/debug/falconerid target/debug/falconeri-worker /usr/local/bin/; \ + fi + +# Run our webserver out of /app +WORKDIR /app + +# Configure our Rocket webserver +ADD falconerid/Rocket.toml . diff --git a/deny.toml b/deny.toml index b42cf2b..f062899 100644 --- a/deny.toml +++ b/deny.toml @@ -2,13 +2,20 @@ # # These policies can be enforced using `cargo deny check`. +[sources] +# Allow git dependencies from the official Google Cloud Rust SDK +allow-git = [ + "https://github.com/googleapis/google-cloud-rust", +] + [advisories] [licenses] # Allow common non-restrictive licenses. ISC is used for various DNS and crypto # things, and it's a minimally restrictive open source license. Everything not # in this list (including AGPL, unlicensed, and copyleft) is denied by default. -allow = ["MIT", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "CC0-1.0", "ISC", "OpenSSL", "Zlib", "Unicode-3.0", "Unicode-DFS-2016"] +# CDLA-Permissive-2.0 is used by webpki-roots, a permissive license for root certificates. +allow = ["MIT", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "CC0-1.0", "ISC", "OpenSSL", "Zlib", "Unicode-3.0", "Unicode-DFS-2016", "CDLA-Permissive-2.0"] [[licenses.clarify]] # Ring has a messy license. diff --git a/examples/gcs-test/BUILD_VERIFICATION.md b/examples/gcs-test/BUILD_VERIFICATION.md new file mode 100644 index 0000000..2ad7d86 --- /dev/null +++ b/examples/gcs-test/BUILD_VERIFICATION.md @@ -0,0 +1,53 @@ +# Build Verification for GCS Test + +## Build Strategy + +All cluster components (falconerid and falconeri-worker) are built **inside minikube** to ensure architecture compatibility with the Kubernetes cluster. Nothing is built on the host machine except the CLI tools that need to run locally. + +### What is Built in Minikube + +1. **falconeri-local:test** image + - Contains: falconerid, falconeri-worker, kubectl + - Built with: `minikube image build -t falconeri-local:test` + - Dockerfile: `/Dockerfile` + +2. **gcs-test** image + - Contains: falconeri-worker, word-frequencies.sh + - Built with: `minikube image build -t gcs-test` + - Dockerfile: `examples/gcs-test/Dockerfile` + +### What Runs Locally + +Only CLI tools that coordinate the test: +- `cargo run -p falconeri -- deploy` - Deploy infrastructure +- `cargo run -p falconeri -- proxy` - Run local proxy for API access +- `cargo run -p falconeri -- job run` - Submit job to cluster +- `cargo run -p falconeri -- job describe` - Query job status + +## Architecture Compatibility + +The Dockerfiles **do not specify a platform**, allowing Docker to build for the native architecture of the build environment (the minikube VM). This ensures: +- No cross-compilation issues +- Binaries match the cluster architecture +- No dependency on host machine architecture + +## Verification + +The test script now includes automatic verification that checks each built image contains the expected files in the correct format: + +### falconeri-local:test +- `/usr/local/bin/falconerid` → ELF executable +- `/usr/local/bin/falconeri-worker` → ELF executable +- `/usr/local/bin/kubectl` → ELF executable + +### gcs-test +- `/usr/local/bin/falconeri-worker` → ELF executable +- `/usr/local/bin/word-frequencies.sh` → shell script + +The verification runs after building images and before running the job, using: +```bash +minikube -p falconeri-gcs-test ssh -- docker run --rm file +``` + +This ensures binaries are correctly formatted and executable within the minikube cluster environment. + diff --git a/examples/gcs-test/Dockerfile b/examples/gcs-test/Dockerfile new file mode 100644 index 0000000..8b8b479 --- /dev/null +++ b/examples/gcs-test/Dockerfile @@ -0,0 +1,29 @@ +# Note: No platform specified - uses native architecture of build environment (minikube VM) +FROM rust:latest AS builder + +RUN apt-get update && \ + apt-get install -y libpq-dev && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +COPY Cargo.toml Cargo.lock ./ +COPY falconeri-worker ./falconeri-worker +COPY falconeri_common ./falconeri_common +COPY falconeri ./falconeri +COPY falconerid ./falconerid + +RUN cargo build -p falconeri-worker + +FROM ubuntu:25.10 + +RUN apt-get update && \ + apt-get install -y \ + ca-certificates \ + libpq5 \ + && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /build/target/debug/falconeri-worker /usr/local/bin/ +ADD word-frequencies.sh /usr/local/bin/ + diff --git a/examples/gcs-test/README.md b/examples/gcs-test/README.md new file mode 100644 index 0000000..9583b7f --- /dev/null +++ b/examples/gcs-test/README.md @@ -0,0 +1,52 @@ +# GCS Integration Test + +End-to-end test for Falconeri with Google Cloud Storage. + +## Prerequisites + +- A GCS bucket with read/write permissions +- A Google Cloud service account JSON key file +- `minikube`, `gsutil`, `kubectl`, `cargo`, `docker` in your PATH + +## Setup + +Set required environment variables: + +```bash +export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json +export GCS_BUCKET=your-bucket-name # or gs://your-bucket-name +``` + +The test script will automatically: +- Start minikube if not already running (and delete it when done) +- Configure kubectl context +- Set up Docker environment variables + +## Running the test + +```bash +just run +# or +python3 test_gcs.py +``` + +## What the test does + +1. **Setup**: Uploads `sample.txt` to `gs://$GCS_BUCKET/falconeri-test/input/` +2. **Build**: Builds falconeri-worker and the test Docker image +3. **Run**: Starts falconeri proxy and runs a job that processes the input file +4. **Verify**: Checks that output file was created with word frequencies +5. **Cleanup**: Deletes test files from GCS and removes k8s secret + +The test reuses the `word-frequencies.sh` script from the sibling example directory, which counts word frequencies in text files. + +## Expected output + +On success, you should see: + +``` +✓ GCS integration test PASSED +``` + +The test will create a word frequency count file at `gs://$GCS_BUCKET/falconeri-test/output/sample.txt`. + diff --git a/examples/gcs-test/justfile b/examples/gcs-test/justfile new file mode 100644 index 0000000..33e7d63 --- /dev/null +++ b/examples/gcs-test/justfile @@ -0,0 +1,25 @@ +# GCS integration test justfile +# +# Required environment variables: +# - GOOGLE_APPLICATION_CREDENTIALS: Path to service account JSON file +# - GCS_BUCKET: Name of existing GCS bucket (without gs:// prefix) + +# Run the GCS integration test +run: + python3 test_gcs.py + +# Quick check that environment variables are set +check-env: + #!/usr/bin/env bash + set -euo pipefail + if [ -z "${GOOGLE_APPLICATION_CREDENTIALS:-}" ]; then + echo "Error: GOOGLE_APPLICATION_CREDENTIALS not set" + exit 1 + fi + if [ -z "${GCS_BUCKET:-}" ]; then + echo "Error: GCS_BUCKET not set" + exit 1 + fi + echo "✓ GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS}" + echo "✓ GCS_BUCKET=${GCS_BUCKET}" + diff --git a/examples/gcs-test/sample.txt b/examples/gcs-test/sample.txt new file mode 100644 index 0000000..d6b49b2 --- /dev/null +++ b/examples/gcs-test/sample.txt @@ -0,0 +1,7 @@ +The quick brown fox jumps over the lazy dog. +A journey of a thousand miles begins with a single step. +To be or not to be, that is the question. +All that glitters is not gold. +The early bird catches the worm. +Actions speak louder than words. + diff --git a/examples/gcs-test/test_gcs.py b/examples/gcs-test/test_gcs.py new file mode 100755 index 0000000..3c882e0 --- /dev/null +++ b/examples/gcs-test/test_gcs.py @@ -0,0 +1,813 @@ +#!/usr/bin/env python3 +""" +End-to-end test for Falconeri with Google Cloud Storage. + +Required environment variables: +- GOOGLE_APPLICATION_CREDENTIALS: Path to service account JSON file +- GCS_BUCKET: Name of existing GCS bucket (without gs:// prefix) + +Usage: + python3 test_gcs.py # Reuse existing minikube profile + python3 test_gcs.py --clean # Delete and recreate minikube profile + +Build Strategy: +- All cluster binaries (falconerid, falconeri-worker) are built inside minikube + using 'minikube image build' to ensure architecture compatibility +- Only the CLI tools (falconeri proxy, job commands) run locally +- No cargo build commands are run on the host machine for cluster components +""" + +import argparse +import json +import os +import secrets +import subprocess +import sys +import time +import tempfile +import urllib.request +import urllib.error +from pathlib import Path + +SCRIPT_DIR = Path(__file__).parent +PROJECT_ROOT = SCRIPT_DIR.parent.parent +MINIKUBE_PROFILE = "falconeri-gcs-test" + + +def run(cmd, check=True, **kwargs): + """Run a command and print it.""" + print(f"$ {' '.join(cmd) if isinstance(cmd, list) else cmd}") + return subprocess.run(cmd, check=check, **kwargs) + + +def setup_minikube(): + """Create a dedicated minikube profile for this test.""" + print(f"\n=== Setting up minikube profile: {MINIKUBE_PROFILE} ===") + + # Check if this profile already exists + result = run( + ["minikube", "profile", "list", "-o", "json"], + capture_output=True, + text=True, + check=False, + ) + + profile_exists = False + if result.returncode == 0: + try: + profiles = json.loads(result.stdout) + if "valid" in profiles: + for profile in profiles["valid"]: + if profile.get("Name") == MINIKUBE_PROFILE: + profile_exists = True + print(f"✓ Profile {MINIKUBE_PROFILE} already exists") + break + except (json.JSONDecodeError, KeyError): + pass + + if not profile_exists: + print(f"Creating minikube profile {MINIKUBE_PROFILE}...") + run(["minikube", "start", "-p", MINIKUBE_PROFILE]) + print(f"✓ minikube profile {MINIKUBE_PROFILE} started") + else: + # Check if it's running + status_result = run( + ["minikube", "status", "-p", MINIKUBE_PROFILE, "-o", "json"], + capture_output=True, + text=True, + check=False, + ) + + is_running = False + if status_result.returncode == 0: + try: + status = json.loads(status_result.stdout) + is_running = status.get("Host") == "Running" + except (json.JSONDecodeError, KeyError): + pass + + if not is_running: + print(f"Starting {MINIKUBE_PROFILE}...") + run(["minikube", "start", "-p", MINIKUBE_PROFILE]) + else: + print(f"✓ {MINIKUBE_PROFILE} is already running") + + # Switch kubectl context to our profile + print("Setting kubectl context to test profile...") + run(["kubectl", "config", "use-context", MINIKUBE_PROFILE]) + + print("✓ minikube setup complete") + + +def validate_minikube(): + """Ensure we're not accidentally running against production k8s.""" + print("\n=== Validating kubectl context ===") + + # Check current kubectl context + result = run( + ["kubectl", "config", "current-context"], + capture_output=True, + text=True, + check=False, + ) + + if result.returncode != 0: + print("No kubectl context set - will be configured during minikube setup") + return + + context = result.stdout.strip() + + # Warn if context looks like production (doesn't contain minikube or our test profile) + if "minikube" not in context.lower() and MINIKUBE_PROFILE not in context: + print(f"⚠️ WARNING: Current kubectl context is '{context}'") + print( + f"This test will create a new minikube profile '{MINIKUBE_PROFILE}' and switch to it." + ) + response = input("Continue? (y/N): ") + if response.lower() != "y": + sys.exit(1) + else: + print(f"Current context: {context}") + + +def ensure_correct_context(): + """Ensure kubectl is using the correct test context.""" + result = run( + ["kubectl", "config", "current-context"], + capture_output=True, + text=True, + check=False, + ) + + if result.returncode != 0: + print(f"⚠️ No kubectl context set! Setting to {MINIKUBE_PROFILE}") + run(["kubectl", "config", "use-context", MINIKUBE_PROFILE]) + return + + current_context = result.stdout.strip() + if current_context != MINIKUBE_PROFILE: + print(f"⚠️ Context is '{current_context}', switching to '{MINIKUBE_PROFILE}'") + run(["kubectl", "config", "use-context", MINIKUBE_PROFILE]) + else: + print(f"✓ Using correct context: {MINIKUBE_PROFILE}") + + +def validate_env(): + """Validate required environment variables.""" + creds = os.getenv("GOOGLE_APPLICATION_CREDENTIALS") + bucket = os.getenv("GCS_BUCKET") + + if not creds: + print("Error: GOOGLE_APPLICATION_CREDENTIALS environment variable not set") + sys.exit(1) + + if not bucket: + print("Error: GCS_BUCKET environment variable not set") + sys.exit(1) + + if not Path(creds).exists(): + print(f"Error: Service account file not found: {creds}") + sys.exit(1) + + # Strip gs:// prefix if provided + bucket = bucket.removeprefix("gs://") + + return creds, bucket + + +def upload_test_data(bucket, gcs_prefix): + """Upload sample.txt to GCS.""" + sample_file = SCRIPT_DIR / "sample.txt" + gcs_uri = f"gs://{bucket}/{gcs_prefix}/input/sample.txt" + + print(f"\n=== Uploading test data to {gcs_uri} ===") + run(["gsutil", "cp", str(sample_file), gcs_uri]) + + +def kill_kubectl_port_forwards(): + """Kill any kubectl port-forward processes.""" + print("Killing kubectl port-forward processes...") + result = run( + ["pgrep", "-f", "kubectl port-forward"], + capture_output=True, + text=True, + check=False, + ) + + if result.stdout.strip(): + pids = result.stdout.strip().split("\n") + for pid in pids: + if pid: + print(f" Killing kubectl port-forward process {pid}") + run(["kill", pid], check=False) + time.sleep(1) + else: + print(" No kubectl port-forward processes found") + + +def cleanup_previous_run(): + """Clean up resources from any previous test run.""" + print("\n=== Cleaning up resources from previous runs ===") + ensure_correct_context() + + kill_kubectl_port_forwards() + + # Delete all gcs-test jobs (pods will be cleaned up automatically) + print("Deleting old gcs-test jobs...") + result = run( + ["kubectl", "get", "jobs", "-o", "name"], + capture_output=True, + text=True, + check=False, + ) + if result.stdout: + job_names = [ + line.strip() + for line in result.stdout.strip().split("\n") + if line and "gcs-test" in line + ] + if job_names: + run(["kubectl", "delete"] + job_names + ["--wait=false"], check=False) + print(f" Deleted {len(job_names)} old gcs-test jobs") + else: + print(" No old gcs-test jobs found") + else: + print(" No old gcs-test jobs found") + + # Delete falconerid deployment + print("Deleting old falconerid deployment...") + result = run( + ["kubectl", "delete", "deployment", "falconerid", "--wait=false"], + check=False, + capture_output=True, + ) + if result.returncode == 0: + print(" Deleted falconerid deployment") + else: + print(" No falconerid deployment found") + + # Delete old replica sets + print("Deleting old replica sets...") + run( + ["kubectl", "delete", "replicaset", "-l", "app=falconerid", "--wait=false"], + check=False, + capture_output=True, + ) + + # Delete old secrets (they'll be recreated) + print("Deleting old secrets...") + run( + ["kubectl", "delete", "secret", "gcs", "--wait=false"], + check=False, + capture_output=True, + ) + run( + ["kubectl", "delete", "secret", "gcs-credentials", "--wait=false"], + check=False, + capture_output=True, + ) + + # Wait a moment for deletions to start + print("Waiting for resources to be deleted...") + time.sleep(3) + + print("✓ Cleanup complete") + + +def build_falconeri_image(): + """Build the falconeri Docker image directly in minikube.""" + print("\n=== Building falconeri Docker image ===") + + # Use a local image name to avoid conflicts with Docker Hub + image_name = "falconeri-local:test" + + # Build Docker image directly in minikube (Dockerfile will build binaries inside Docker) + run( + [ + "minikube", + "image", + "build", + "-t", + image_name, + "-f", + "Dockerfile", + ".", + "-p", + MINIKUBE_PROFILE, + ], + cwd=PROJECT_ROOT, + ) + + print(f"✓ Built {image_name} in minikube") + + return image_name + + +def deploy_falconeri(image_name): + """Deploy falconeri infrastructure to the cluster.""" + print("\n=== Deploying falconeri infrastructure ===") + ensure_correct_context() + + run( + ["cargo", "run", "-p", "falconeri", "--", "deploy"], + cwd=PROJECT_ROOT, + ) + + # Patch the deployment to use our custom local image, set imagePullPolicy, and scale to 1 replica + print( + f"Updating deployment to use {image_name} with imagePullPolicy: Never and 1 replica..." + ) + run( + [ + "kubectl", + "patch", + "deployment/falconerid", + "--type", + "json", + "-p", + f'[{{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "{image_name}"}}, {{"op": "replace", "path": "/spec/template/spec/containers/0/imagePullPolicy", "value": "Never"}}, {{"op": "replace", "path": "/spec/replicas", "value": 1}}]', + ] + ) + + # Wait a moment for the rollout to start + print("Waiting for rollout to start...") + time.sleep(2) + + # Delete old replica sets to force clean rollout + print("Cleaning up old replica sets...") + result = run( + ["kubectl", "get", "replicaset", "-l", "app=falconerid", "-o", "name"], + capture_output=True, + text=True, + check=False, + ) + if result.stdout: + for rs in result.stdout.strip().split("\n"): + if rs: + # Get the deployment revision to keep only the latest + result = run( + ["kubectl", "get", rs, "-o", "jsonpath='{.spec.replicas}'"], + capture_output=True, + text=True, + check=False, + ) + # Delete replica sets with 0 desired replicas + replicas = result.stdout.strip().strip("'") + if replicas == "0": + print(f" Deleting old replica set: {rs}") + run(["kubectl", "delete", rs], check=False) + else: + print(f" Keeping active replica set: {rs} (replicas={replicas})") + + print("Waiting for falconeri deployments to be ready...") + run( + [ + "kubectl", + "wait", + "--for=condition=available", + "deployment/falconerid", + "--timeout=300s", + ] + ) + run( + [ + "kubectl", + "wait", + "--for=condition=available", + "deployment/falconeri-postgres", + "--timeout=300s", + ] + ) + print("✓ Falconeri infrastructure is ready") + + +def create_k8s_secret(creds_path): + """Create Kubernetes secret from service account JSON.""" + print("\n=== Creating Kubernetes secret ===") + ensure_correct_context() + + # Read the service account JSON + with open(creds_path) as f: + service_account_json = f.read() + + # Create secret with GCLOUD_SERVICE_ACCOUNT_KEY + # Use gcs-credentials to match what falconerid deployment expects + run( + [ + "kubectl", + "create", + "secret", + "generic", + "gcs-credentials", + f"--from-literal=GCLOUD_SERVICE_ACCOUNT_KEY={service_account_json}", + ] + ) + + +def build_worker(): + """No-op: worker is now built inside Docker.""" + pass + + +def build_docker_image(bucket): + """Build the test Docker image directly in minikube.""" + print("\n=== Building test Docker image (with Rust compilation) ===") + + # Copy word-frequencies.sh to project root temporarily for Docker context + script_src = SCRIPT_DIR.parent / "word-frequencies" / "word-frequencies.sh" + script_dst = PROJECT_ROOT / "word-frequencies.sh" + run(["cp", str(script_src), str(script_dst)]) + + # Build Docker image from project root using Dockerfile in gcs-test directory + # Use relative path from PROJECT_ROOT to the Dockerfile + dockerfile_rel_path = "examples/gcs-test/Dockerfile" + run( + [ + "minikube", + "image", + "build", + "-f", + dockerfile_rel_path, + "-t", + "gcs-test", + ".", + "-p", + MINIKUBE_PROFILE, + ], + cwd=PROJECT_ROOT, + ) + + # Clean up copied file + script_dst.unlink() + + +def verify_images(): + """Verify that images contain expected binaries in correct format.""" + print("\n=== Verifying Docker images ===") + + def check_file_in_image(image_name, file_path, expected_type): + """Check that a file exists in the image and is of the expected type.""" + print(f"Checking {file_path} in {image_name}...") + + result = run( + [ + "minikube", + "-p", + MINIKUBE_PROFILE, + "ssh", + "--", + f"docker run --rm {image_name} file {file_path}", + ], + capture_output=True, + text=True, + check=False, + ) + + if result.returncode != 0: + print(f" ❌ Could not check {file_path}") + return False + + output = result.stdout.strip() + if expected_type.lower() in output.lower(): + print(f" ✓ {file_path} is a {expected_type}") + return True + else: + print(f" ❌ Expected {expected_type}, got: {output}") + return False + + # Check falconeri-local:test image + print("\nVerifying falconeri-local:test:") + falconeri_checks = [ + check_file_in_image("falconeri-local:test", "/usr/local/bin/falconerid", "ELF"), + check_file_in_image( + "falconeri-local:test", "/usr/local/bin/falconeri-worker", "ELF" + ), + check_file_in_image("falconeri-local:test", "/usr/local/bin/kubectl", "ELF"), + ] + + # Check gcs-test image + print("\nVerifying gcs-test:") + gcs_test_checks = [ + check_file_in_image("gcs-test", "/usr/local/bin/falconeri-worker", "ELF"), + check_file_in_image( + "gcs-test", "/usr/local/bin/word-frequencies.sh", "shell script" + ), + ] + + if all(falconeri_checks + gcs_test_checks): + print("\n✓ All image verifications passed") + else: + print("\n⚠️ Some image verifications failed, but continuing...") + print(" (This may be expected if architecture differs)") + + +def generate_pipeline_spec(bucket, gcs_prefix): + """Generate the pipeline spec JSON.""" + spec = { + "pipeline": {"name": "gcs_test"}, + "transform": { + "image": "gcs-test", + "image_pull_policy": "Never", + "cmd": ["word-frequencies.sh"], + "env": {"RUST_LOG": "falconeri_common=debug,falconeri_worker=debug,info"}, + "secrets": [ + { + "name": "gcs-credentials", + "key": "GCLOUD_SERVICE_ACCOUNT_KEY", + "env_var": "GCLOUD_SERVICE_ACCOUNT_KEY", + } + ], + }, + "parallelism_spec": {"constant": 2}, + "resource_requests": {"memory": "128Mi", "cpu": 0.1}, + "datum_tries": 3, + "input": { + "atom": { + "repo": "input", + "URI": f"gs://{bucket}/{gcs_prefix}/input/", + "glob": "/*", + } + }, + "egress": {"URI": f"gs://{bucket}/{gcs_prefix}/output/"}, + } + + spec_path = SCRIPT_DIR / "gcs-test.json" + with open(spec_path, "w") as f: + json.dump(spec, f, indent=2) + + print(f"\n=== Generated pipeline spec at {spec_path} ===") + return spec_path + + +def start_proxy(): + """Start falconeri proxy in background.""" + print("\n=== Starting falconeri proxy ===") + print("$ cargo run -p falconeri -- proxy") + proxy_proc = subprocess.Popen( + ["cargo", "run", "-p", "falconeri", "--", "proxy"], + cwd=PROJECT_ROOT, + ) + + # Wait for proxy to be ready by polling the version endpoint + print("Waiting for proxy to be ready...") + + for i in range(60): + time.sleep(1) + try: + urllib.request.urlopen("http://localhost:8089/version", timeout=1) + print("✓ Proxy is ready") + return proxy_proc + except Exception: + if proxy_proc.poll() is not None: + raise Exception(f"Proxy exited with code {proxy_proc.returncode}") + continue + + raise Exception("Proxy did not become ready within 60 seconds") + + +def run_job(spec_path): + """Run the falconeri job and return job ID.""" + print("\n=== Running falconeri job ===") + ensure_correct_context() + + result = run( + ["cargo", "run", "-p", "falconeri", "--", "job", "run", str(spec_path)], + cwd=PROJECT_ROOT, + capture_output=True, + text=True, + check=False, + ) + + # Print stdout and stderr + if result.stdout: + print(result.stdout) + if result.stderr: + print(result.stderr, file=sys.stderr) + + # Check if command failed + if result.returncode != 0: + raise subprocess.CalledProcessError( + result.returncode, result.args, result.stdout, result.stderr + ) + + # Look for job name in output (it's just the job name on a single line) + for line in result.stdout.split("\n"): + line = line.strip() + # Job names are alphanumeric with dashes, matching pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ + if ( + line + and not line.startswith("Handling") + and not line.startswith("Finished") + and not line.startswith("Running") + ): + # This should be the job name + if line and all(c.isalnum() or c == "-" for c in line): + return line + + print("Warning: Could not extract job ID from output") + return None + + +def wait_for_job(job_id, timeout=300): + """Wait for job to complete, polling status.""" + if not job_id: + print("No job ID provided, skipping wait") + return False + + print(f"\n=== Waiting for job {job_id} to complete ===") + ensure_correct_context() + start_time = time.time() + + while time.time() - start_time < timeout: + result = run( + ["cargo", "run", "-p", "falconeri", "--", "job", "describe", job_id], + cwd=PROJECT_ROOT, + capture_output=True, + text=True, + check=False, + ) + + # Check for completion indicators + if "Status: done" in result.stdout: + print(f"Job {job_id} completed successfully!") + return True + elif "error" in result.stdout.lower(): + print(f"Job {job_id} failed!") + if result.stdout: + print(result.stdout) + if result.stderr: + print(result.stderr, file=sys.stderr) + return False + + print(f"Job still running... ({int(time.time() - start_time)}s elapsed)") + time.sleep(10) + + print(f"Job did not complete within {timeout}s") + return False + + +def verify_output(bucket, gcs_prefix): + """Verify that output file was created and contains expected data.""" + print("\n=== Verifying output ===") + + output_uri = f"gs://{bucket}/{gcs_prefix}/output/sample.txt" + + # Check if file exists + result = run( + ["gsutil", "ls", output_uri], check=False, capture_output=True, text=True + ) + + if result.returncode != 0: + print(f"Error: Output file not found at {output_uri}") + if result.stderr: + print(result.stderr, file=sys.stderr) + return False + + print(f"Output file exists at {output_uri}") + + # Download and check contents + with tempfile.NamedTemporaryFile(mode="w+", delete=False) as tmp: + tmp_path = tmp.name + + # Download to temp file + run(["gsutil", "cp", output_uri, tmp_path]) + + # Read contents + with open(tmp_path) as f: + contents = f.read() + + # Clean up temp file + os.unlink(tmp_path) + + print("\nOutput contents:") + print(contents[:500]) # Print first 500 chars + + # Basic validation - should contain word frequency counts + if not contents.strip(): + print("Error: Output file is empty") + return False + + # Should have lines with counts and words + lines = contents.strip().split("\n") + if len(lines) < 5: + print("Error: Output has too few lines") + return False + + print(f"\nSuccess! Output contains {len(lines)} lines of word frequencies") + return True + + +def cleanup(bucket, gcs_prefix, proxy_proc): + """Clean up test resources.""" + print("\n=== Cleaning up ===") + + # Stop proxy + if proxy_proc: + print("Stopping proxy...") + proxy_proc.terminate() + try: + proxy_proc.wait(timeout=5) + except subprocess.TimeoutExpired: + proxy_proc.kill() + + # Kill any kubectl port-forward processes (in case proxy didn't clean them up) + kill_kubectl_port_forwards() + + # Delete GCS test files + print("Deleting GCS test files...") + run(["gsutil", "-m", "rm", "-r", f"gs://{bucket}/{gcs_prefix}/"], check=False) + + # Delete k8s secrets + print("Deleting k8s secrets...") + ensure_correct_context() + run(["kubectl", "delete", "secret", "gcs"], check=False) + run(["kubectl", "delete", "secret", "gcs-credentials"], check=False) + + # Delete generated spec + spec_path = SCRIPT_DIR / "gcs-test.json" + if spec_path.exists(): + spec_path.unlink() + + +def main(): + """Main test orchestration.""" + parser = argparse.ArgumentParser( + description="End-to-end test for Falconeri with Google Cloud Storage" + ) + parser.add_argument( + "--clean", + action="store_true", + help="Delete the minikube profile before starting for a clean slate", + ) + args = parser.parse_args() + + print("=== Falconeri GCS Integration Test ===\n") + + # Validate environment first + creds_path, bucket = validate_env() + print(f"Using GCS bucket: {bucket}") + print(f"Using credentials: {creds_path}") + + # Generate random GCS prefix for this test run + gcs_prefix = f"falconeri-test-{secrets.token_hex(6)}" + print(f"Using GCS prefix: {gcs_prefix}") + + # SAFETY: Validate current kubectl context + validate_minikube() + + # Delete minikube profile if --clean flag is set + if args.clean: + print(f"\n🧹 Deleting minikube profile {MINIKUBE_PROFILE} for clean slate...") + run(["minikube", "delete", "-p", MINIKUBE_PROFILE], check=False) + + # Setup dedicated minikube profile + setup_minikube() + print(f"\n⚠️ Using dedicated minikube profile '{MINIKUBE_PROFILE}'") + + # Clean up any resources from previous runs + cleanup_previous_run() + + proxy_proc = None + success = False + + try: + # Setup phase + upload_test_data(bucket, gcs_prefix) + falconeri_image = build_falconeri_image() + create_k8s_secret(creds_path) # Create secret BEFORE deploying + deploy_falconeri(falconeri_image) + + # Build phase + build_worker() + build_docker_image(bucket) + + # Verify images contain correct binaries + verify_images() + + # Run phase + spec_path = generate_pipeline_spec(bucket, gcs_prefix) + proxy_proc = start_proxy() + job_id = run_job(spec_path) + + # Wait for completion + job_success = wait_for_job(job_id) + + # Verify phase + if job_success: + success = verify_output(bucket, gcs_prefix) + finally: + # Always cleanup + cleanup(bucket, gcs_prefix, proxy_proc) + + # Report results + print("\n" + "=" * 50) + if success: + print("✓ GCS integration test PASSED") + sys.exit(0) + else: + print("✗ GCS integration test FAILED") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/examples/word-frequencies/word-frequencies.sh b/examples/word-frequencies/word-frequencies.sh index da95af0..87cb49a 100755 --- a/examples/word-frequencies/word-frequencies.sh +++ b/examples/word-frequencies/word-frequencies.sh @@ -3,7 +3,7 @@ # Standard paranoia. set -euo pipefail -for F in /pfs/texts/*.txt; do +for F in /pfs/input/*.txt; do outfile="/pfs/out/$(basename "$F")" cat "$F" | tr '[:upper:]' '[:lower:]' | diff --git a/falconeri/src/cmd/deploy_manifest.yml.hbs b/falconeri/src/cmd/deploy_manifest.yml.hbs index af4b1bc..e20d472 100644 --- a/falconeri/src/cmd/deploy_manifest.yml.hbs +++ b/falconeri/src/cmd/deploy_manifest.yml.hbs @@ -113,6 +113,11 @@ spec: value: "/app/Rocket.toml" - name: RUST_LOG value: "{{config.falconerid_log_level}}" + - name: GCLOUD_SERVICE_ACCOUNT_KEY + valueFrom: + secretKeyRef: + name: gcs-credentials + key: GCLOUD_SERVICE_ACCOUNT_KEY resources: requests: cpu: "{{config.falconerid_cpu}}" diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index a6c36f2..39b1867 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -19,7 +19,7 @@ lazy_static = "1.5.0" r2d2 = "0.8.10" rand = "0.9.2" regex = "1.12.2" -reqwest = { version = "0.12.24", default-features = false, features = ["blocking", "json", "rustls-tls-native-roots"] } +reqwest = { version = "0.13.1", default-features = false, features = ["blocking", "json", "rustls"] } semver = "1.0.27" serde = "1.0.228" serde_json = "1.0" @@ -27,3 +27,11 @@ tracing = "0.1.43" tracing-subscriber = { version = "0.3.22", features = ["env-filter"] } url = "2.5.7" uuid = { version = "1.19.0", features = ["serde", "v4"] } +google-cloud-storage = { git = "https://github.com/googleapis/google-cloud-rust.git", package = "google-cloud-storage" } +google-cloud-auth = { git = "https://github.com/googleapis/google-cloud-rust.git", package = "google-cloud-auth" } +tokio = { version = "1.48", features = ["rt-multi-thread", "macros", "fs"] } +tokio-util = { version = "0.7", features = ["io", "compat"] } +futures = "0.3" +bytes = "1.11" +flate2 = "1.1" +glob = "0.3" diff --git a/falconeri_common/src/db.rs b/falconeri_common/src/db.rs index 3178927..23b5fff 100644 --- a/falconeri_common/src/db.rs +++ b/falconeri_common/src/db.rs @@ -113,7 +113,7 @@ pub fn run_pending_migrations(conn: &mut PgConnection) -> Result<()> { conn.transaction(|conn| -> Result<()> { // Take an advisory lock before running the migration. It's safe to // generate this SQL by hand because MIGRATION_LOCK_ID is an integer. - let lock_sql = sql_query("SELECT pg_advisory_xact_lock(?)"); + let lock_sql = sql_query("SELECT pg_advisory_xact_lock($1)"); lock_sql .bind::(MIGRATION_LOCK_ID) .execute(conn) diff --git a/falconeri_common/src/storage/gs.rs b/falconeri_common/src/storage/gs.rs index 0d67918..f0d6ad3 100644 --- a/falconeri_common/src/storage/gs.rs +++ b/falconeri_common/src/storage/gs.rs @@ -1,47 +1,124 @@ //! Support for Google Cloud Storage. -use std::{collections::HashSet, fs, io::BufRead, process}; +use std::future::Future; +use std::io::Write; +use std::path::Path; + +use google_cloud_auth::credentials::service_account; +use google_cloud_storage::client::{Storage, StorageControl}; use super::CloudStorage; use crate::prelude::*; use crate::secret::Secret; -/// Backend for talking to Google Cloud Storage, currently based on `gsutil`. +/// Run an async function, either using the current Tokio runtime if available, +/// or creating a new one if not. +fn run_async(future: F) -> Result +where + F: Future>, +{ + match tokio::runtime::Handle::try_current() { + Ok(handle) => tokio::task::block_in_place(|| handle.block_on(future)), + Err(_) => { + let rt = tokio::runtime::Runtime::new() + .context("failed to create Tokio runtime")?; + rt.block_on(future) + } + } +} + +/// Backend for talking to Google Cloud Storage using the native GCS SDK. #[derive(Debug)] -pub struct GoogleCloudStorage {} +pub struct GoogleCloudStorage { + client: Storage, + control: StorageControl, +} impl GoogleCloudStorage { /// Create a new `GoogleCloudStorage` backend. #[allow(clippy::new_ret_no_self)] #[tracing::instrument(level = "trace")] pub fn new(_secrets: &[Secret]) -> Result { - // We don't yet know how to authenticate using secrets. - Ok(GoogleCloudStorage {}) + let (client, control) = run_async(async { + let mut storage_builder = Storage::builder(); + let mut control_builder = StorageControl::builder(); + + // Support GCLOUD_SERVICE_ACCOUNT_KEY (falconeri's current env var) + if let Ok(key_json) = std::env::var("GCLOUD_SERVICE_ACCOUNT_KEY") { + let json: serde_json::Value = serde_json::from_str(&key_json) + .context("failed to parse GCLOUD_SERVICE_ACCOUNT_KEY as JSON")?; + let credentials = service_account::Builder::new(json) + .build() + .context("failed to build service account credentials")?; + storage_builder = + storage_builder.with_credentials(credentials.clone()); + control_builder = control_builder.with_credentials(credentials); + } + // Otherwise falls back to standard ADC (GOOGLE_APPLICATION_CREDENTIALS or metadata service) + + let client = storage_builder.build().await?; + let control = control_builder.build().await?; + Ok::<_, anyhow::Error>((client, control)) + })?; + + Ok(GoogleCloudStorage { client, control }) } } +/// Parse a `gs://bucket/object` URI into bucket and object components. +fn parse_gs_uri(uri: &str) -> Result<(String, String)> { + let url = url::Url::parse(uri)?; + if url.scheme() != "gs" { + return Err(format_err!("expected gs:// URL, got {}", uri)); + } + let bucket = url + .host_str() + .ok_or_else(|| format_err!("no bucket in {}", uri))? + .to_string(); + let object = url.path().trim_start_matches('/').to_string(); + Ok((bucket, object)) +} + impl CloudStorage for GoogleCloudStorage { #[tracing::instrument(level = "trace")] fn list(&self, uri: &str) -> Result> { trace!("listing {}", uri); - // Shell out to gsutil to list the files we want to process. - let output = process::Command::new("gsutil") - .arg("ls") - .arg(uri) - .stderr(process::Stdio::inherit()) - .output() - .context("error running gsutil")?; - if !output.status.success() { - return Err(format_err!("could not list {:?}: {}", uri, output.status)); - } - // `gsutil ls` is "eventually consistent", and seems to occasionally retun - // duplicate entries. - let mut paths = HashSet::new(); - for line in output.stdout.lines() { - let line = line?; - paths.insert(line.trim_end().to_owned()); - } - Ok(paths.into_iter().collect()) + + let (bucket, prefix) = parse_gs_uri(uri)?; + + run_async(async { + let mut results = Vec::new(); + let mut page_token: Option = None; + + loop { + let mut request = self + .control + .list_objects() + .set_parent(format!("projects/_/buckets/{}", bucket)) + .set_prefix(prefix.clone()); + + if let Some(token) = page_token { + request = request.set_page_token(token); + } + + let response = request.send().await?; + + for object in response.objects { + results.push(format!("gs://{}/{}", bucket, object.name)); + } + + page_token = if response.next_page_token.is_empty() { + None + } else { + Some(response.next_page_token) + }; + if page_token.is_none() { + break; + } + } + + Ok(results) + }) } #[tracing::instrument(level = "trace")] @@ -54,53 +131,139 @@ impl CloudStorage for GoogleCloudStorage { .expect("path should be UTF-8") .ends_with('/')); trace!("syncing {} to {}", uri, local_path.display()); - fs::create_dir_all(local_path) - .context("cannot create local download directory")?; - let status = process::Command::new("gsutil") - .args(["-m", "rsync"]) - .arg(uri) - .arg(local_path) - .status() - .context("could not run gsutil rsync")?; - if !status.success() { - return Err(format_err!("could not download {:?}: {}", uri, status)); + + // List all files with this prefix and download each + let files = self.list(uri)?; + for file_uri in files { + let (bucket, object) = parse_gs_uri(&file_uri)?; + + // Construct local path + let relative = object.trim_start_matches(&parse_gs_uri(uri)?.1); + let file_local_path = local_path.join(relative); + + // Download the file + self.download_file(&bucket, &object, &file_local_path)?; } + Ok(()) } else { - // We have a file. We can't use `gsutil rsync` for this case. + // We have a single file trace!("downloading {} to {}", uri, local_path.display()); - if let Some(parent) = local_path.parent() { - fs::create_dir_all(parent) - .context("cannot create local download directory")?; - } - let status = process::Command::new("gsutil") - .args(["-m", "cp", "-r"]) - .arg(uri) - .arg(local_path) - .status() - .context("could not run gsutil cp")?; - if !status.success() { - return Err(format_err!("could not download {:?}: {}", uri, status)); - } + let (bucket, object) = parse_gs_uri(uri)?; + self.download_file(&bucket, &object, local_path) } - Ok(()) } #[tracing::instrument(level = "trace")] fn sync_up(&self, local_path: &Path, uri: &str) -> Result<()> { trace!("uploading {} to {}", local_path.display(), uri); - let status = process::Command::new("gsutil") - .args(["-m", "rsync", "-r"]) - .arg(local_path) - .arg(uri) - .status() - .context("could not run gsutil")?; - if !status.success() { - return Err(format_err!( - "could not upload {}: {}", - local_path.display(), - status, - )); + + let (bucket, prefix) = parse_gs_uri(uri)?; + + // Walk the directory and upload each file + let entries = glob::glob(&format!("{}**/*", local_path.display())) + .context("failed to read directory pattern")?; + + for entry in entries { + let entry = entry?; + if !entry.is_file() { + continue; + } + + // Calculate relative path and object name + let relative = entry + .strip_prefix(local_path) + .context("failed to strip prefix")?; + let object_name = if prefix.is_empty() { + relative.to_str().unwrap().to_string() + } else { + format!( + "{}/{}", + prefix.trim_end_matches('/'), + relative.to_str().unwrap() + ) + }; + + // Upload the file with gzip compression + self.upload_file_compressed(&bucket, &object_name, &entry)?; } + Ok(()) } } + +impl GoogleCloudStorage { + /// Download a single file from GCS to local disk. + fn download_file( + &self, + bucket: &str, + object: &str, + local_path: &Path, + ) -> Result<()> { + run_async(async { + // Create parent directory if needed + if let Some(parent) = local_path.parent() { + tokio::fs::create_dir_all(parent) + .await + .context("cannot create local download directory")?; + } + + // Format bucket name with projects/_/buckets/ prefix + let bucket_path = format!("projects/_/buckets/{}", bucket); + + // Download with automatic decompression enabled + let mut reader = self + .client + .read_object(&bucket_path, object) + .with_automatic_decompression(true) + .send() + .await?; + + // Write to file + let mut file = tokio::fs::File::create(local_path).await?; + while let Some(chunk) = reader.next().await { + let chunk = chunk?; + tokio::io::AsyncWriteExt::write_all(&mut file, &chunk).await?; + } + + Ok(()) + }) + } + + /// Upload a single file to GCS with gzip compression. + fn upload_file_compressed( + &self, + bucket: &str, + object: &str, + local_path: &Path, + ) -> Result<()> { + use flate2::Compression; + + run_async(async { + // Read entire file into memory + let data = std::fs::read(local_path) + .with_context(|| format!("failed to read {}", local_path.display()))?; + + // Compress with gzip + let mut encoder = + flate2::write::GzEncoder::new(Vec::new(), Compression::default()); + encoder.write_all(&data)?; + let compressed_data = encoder.finish()?; + + // Format bucket name with projects/_/buckets/ prefix + let bucket_path = format!("projects/_/buckets/{}", bucket); + + // Upload with Content-Encoding: gzip + self.client + .write_object( + &bucket_path, + object, + bytes::Bytes::from(compressed_data), + ) + .set_content_encoding("gzip") + .send_buffered() + .await?; + + Ok(()) + }) + } +} diff --git a/guide/src/images.md b/guide/src/images.md index 68d013d..31cc07f 100644 --- a/guide/src/images.md +++ b/guide/src/images.md @@ -20,19 +20,9 @@ If your pipeline JSON contains the following input section: ## Required executables -Your Docker image must contain both `gsutil` (assuming you're using Google Cloud Storage) and `falconeri-worker` somewhere in your `$PATH`. You can install `gsutil` on an Ubuntu image as follows: - -```Dockerfile -RUN export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \ - echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | \ - tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ - curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \ - apt-key add - && \ - apt-get update && apt-get install -y google-cloud-sdk && \ - apt-get clean && rm -rf /var/lib/apt/lists/* -``` +Your Docker image must contain `falconeri-worker` somewhere in your `$PATH`. You can install `falconeri-worker` by downloading the latest [release][] and copying `falconeri-worker` to `/usr/local/bin`, or another directory in your `$PATH`. This is a statically-linked Linux binary, so it should work on any reasonably modern Linux distro. -You can install `falconeri-worker` by downloading the latest [release][] and copying `falconeri-worker` to `/usr/local/bin`, or another directory in your `$PATH`. This is a statically-linked Linux binary, so it should work on any reasonably modern Linux distro. +Note: `falconeri-worker` now uses the native Google Cloud Storage SDK for Rust, so there is no need to install `gsutil` or the Google Cloud SDK. Authentication is handled via the `GCLOUD_SERVICE_ACCOUNT_KEY` environment variable or Application Default Credentials. TODO: Add example of installing `falconeri-worker`. diff --git a/guide/src/installation.md b/guide/src/installation.md index d7b4235..cfb9209 100644 --- a/guide/src/installation.md +++ b/guide/src/installation.md @@ -11,11 +11,19 @@ We've had good luck with the following: If you're running Kubernetes on Google's cloud, you will need: -- `gsutil` for accessing Google Cloud Storage. - `gcloud` for working with your cluster. For other clouds, you will need to check your vendor's documentation. +### Google Cloud Storage authentication + +Falconeri uses the native Google Cloud Storage SDK for Rust and supports two authentication methods: + +1. **`GCLOUD_SERVICE_ACCOUNT_KEY`** environment variable containing service account JSON credentials (recommended for containerized deployments). +2. **Application Default Credentials (ADC)** via the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or GKE/GCE metadata service. + +No separate `gsutil` installation is required. + For all setups, you will also need: - `kubectl`, compatible with your version of Kubernetes. From b93f9fb092479a7e89815ad74502f6b5dd0082b2 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 15:57:02 -0500 Subject: [PATCH 03/28] modernize ci --- .github/workflows/ci.yml | 174 +++++++++++++++++----------------- .github/workflows/release.yml | 142 +++++++++++++++++++++++++++ 2 files changed, 228 insertions(+), 88 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c0c75b..343e21b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,111 +1,109 @@ name: CI -# Controls when the action will run. Triggers the workflow on push or pull -# request events but only for the main branch. on: push: - # Run on the main branch. branches: - main - - ci - tags: - - "v*" pull_request: - # Only run on pull requests against main. - branches: [main] + +permissions: + contents: read jobs: - # We run this job first, to create any GitHub release that we might need. - # Creating a release can only be done once, so we need to split it out from - # other jobs. - create_release: - name: Create release (if needed) + test: + name: Test runs-on: ubuntu-latest - outputs: - release_version: ${{ steps.extract_release_version.outputs.release_version }} - upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - name: Extract release version - id: extract_release_version - run: | - release_version="$(echo '${{ github.ref }}' | sed 's,^.*/\([^/]*\)$,\1,; s,^v,,' )" - echo Release version: $release_version - echo "::set-output name=release_version::$release_version" - - name: Extract release body from CHANGELOG.md - id: extract_release_body - if: ${{ startsWith(github.ref, 'refs/tags/v') }} - # Use `clparse` to parse `CHANGELOG.md` and extract release notes. - run: | - curl -sLO https://github.com/marcaddeo/clparse/releases/download/0.8.0/clparse-0.8.0-x86_64-unknown-linux-musl.tar.gz - tar xzf clparse*.tar.gz - sudo cp clparse /usr/local/bin - rm -rf clparse* - clparse -f json CHANGELOG.md | \ - jq ".releases[] | select(.version == \"${{ steps.extract_release_version.outputs.release_version }}\") | { title: \"\", description: \"\", releases: [.] }" | \ - clparse - | \ - tail -n +3 > RELEASE_BODY.md - - name: "Make release" - id: create_release - if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache dependencies + uses: Swatinem/rust-cache@v2 + + - name: Run tests + run: cargo test --verbose + + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache dependencies + uses: Swatinem/rust-cache@v2 + + - name: Run cargo check + run: cargo check --verbose + + fmt: + name: Format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable with: - tag_name: ${{ github.ref }} - release_name: "${{ steps.extract_release_version.outputs.release_version }}" - body_path: RELEASE_BODY.md + components: rustfmt - # We use a matrix to run our build on every supported platform. - release: - name: "Build" + - name: Check formatting + run: cargo fmt --all -- --check - needs: - - create_release + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - name: Cache dependencies + uses: Swatinem/rust-cache@v2 + + - name: Run clippy + run: cargo clippy --verbose -- -D warnings + + build: + name: Build ${{ matrix.target }} + runs-on: ${{ matrix.os }} strategy: matrix: - # target: Official name of system to compile for. - # os: GitHub CI OS image to use on runner. include: - - target: x86_64-unknown-linux-musl - os: ubuntu-latest - - runs-on: ${{ matrix.os }} + - os: ubuntu-latest + target: x86_64-unknown-linux-musl + - os: macos-latest + target: x86_64-apple-darwin + - os: macos-latest + target: aarch64-apple-darwin + - os: windows-latest + target: x86_64-pc-windows-msvc steps: - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable with: - profile: minimal - # We track latest stable Rust instead of hardcoding it because it - # virtually never breaks old code. - toolchain: stable - components: rustfmt, clippy - target: ${{ matrix.target }} - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - name: Check source formatting and warnings - run: | - cargo fmt -- --check - cargo clippy -- -D warnings - - name: Test - run: | - cargo test - - name: Build release - id: build_release + targets: ${{ matrix.target }} + + - name: Install dependencies (Linux) + if: matrix.target == 'x86_64-unknown-linux-musl' run: | - ./build-release falconeri ${{ needs.create_release.outputs.release_version }}_${{ matrix.target }} - release_file=falconeri_${{ needs.create_release.outputs.release_version }}_${{ matrix.target }}.zip - echo "::set-output name=release_file::$release_file" - - name: Upload Release Asset - if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + sudo apt-get update + sudo apt-get install -y musl-tools + + - name: Cache dependencies + uses: Swatinem/rust-cache@v2 with: - upload_url: ${{ needs.create_release.outputs.upload_url }} - asset_path: ./${{ steps.build_release.outputs.release_file }} - asset_name: ${{ steps.build_release.outputs.release_file }} - asset_content_type: application/zip \ No newline at end of file + key: ${{ matrix.target }} + + - name: Build + run: cargo build --release --target ${{ matrix.target }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..065b330 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,142 @@ +name: Release + +on: + push: + tags: + - "v*" + +permissions: + contents: write + +jobs: + validate: + name: Validate version + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Extract version from tag + id: tag_version + run: | + TAG="${GITHUB_REF#refs/tags/v}" + echo "version=$TAG" >> $GITHUB_OUTPUT + echo "Tag version: $TAG" + + - name: Extract version from Cargo.toml + id: cargo_version + run: | + CARGO_VERSION=$(grep '^version = ' falconeri/Cargo.toml | head -1 | cut -d'"' -f2) + echo "version=$CARGO_VERSION" >> $GITHUB_OUTPUT + echo "Cargo.toml version: $CARGO_VERSION" + + - name: Validate versions match + run: | + if [ "${{ steps.tag_version.outputs.version }}" != "${{ steps.cargo_version.outputs.version }}" ]; then + echo "Error: Tag version (${{ steps.tag_version.outputs.version }}) does not match Cargo.toml version (${{ steps.cargo_version.outputs.version }})" + exit 1 + fi + echo "Version validation passed: ${{ steps.tag_version.outputs.version }}" + + test: + name: Run tests before release + needs: validate + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Run tests + run: cargo test --verbose + + - name: Run clippy + run: | + rustup component add clippy + cargo clippy --verbose -- -D warnings + + build: + name: Build ${{ matrix.target }} + needs: test + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-musl + archive_name: falconeri-${{ github.ref_name }}-linux-x86_64.zip + - os: macos-latest + target: x86_64-apple-darwin + archive_name: falconeri-${{ github.ref_name }}-macos-x86_64.zip + - os: macos-latest + target: aarch64-apple-darwin + archive_name: falconeri-${{ github.ref_name }}-macos-aarch64.zip + - os: windows-latest + target: x86_64-pc-windows-msvc + archive_name: falconeri-${{ github.ref_name }}-windows-x86_64.zip + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install dependencies (Linux) + if: matrix.target == 'x86_64-unknown-linux-musl' + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + + - name: Build + run: cargo build --release --target ${{ matrix.target }} + + - name: Create archive (Unix) + if: runner.os != 'Windows' + run: | + cd target/${{ matrix.target }}/release + zip ../../../${{ matrix.archive_name }} falconeri falconerid falconeri-worker + + - name: Create archive (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + cd target/${{ matrix.target }}/release + Compress-Archive -Path falconeri.exe,falconerid.exe,falconeri-worker.exe -DestinationPath ../../../${{ matrix.archive_name }} + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.target }} + path: ${{ matrix.archive_name }} + + release: + name: Create GitHub Release + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release files + run: | + mkdir release-files + find artifacts -name "*.zip" -exec cp {} release-files/ \; + ls -lh release-files/ + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + files: release-files/* + draft: false + prerelease: false + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + From 1fa22560effb32a0ef21cbff3332d75af3d40b34 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 16:07:14 -0500 Subject: [PATCH 04/28] buikld --- .github/workflows/ci.yml | 29 ++++++++++++++++++++--------- Dockerfile.build | 12 +++++------- justfile | 14 +++++++------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 343e21b..1250721 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,31 +79,42 @@ jobs: include: - os: ubuntu-latest target: x86_64-unknown-linux-musl + use_container: true - os: macos-latest target: x86_64-apple-darwin + use_container: false - os: macos-latest target: aarch64-apple-darwin + use_container: false - os: windows-latest target: x86_64-pc-windows-msvc + use_container: false steps: - uses: actions/checkout@v4 - - name: Install Rust + - name: Build (Linux musl with Docker) + if: matrix.use_container + run: | + docker build -f Dockerfile.build -t build-falconeri . + docker run --name build-falconeri-container -e CARGO_ARGS=--release build-falconeri + mkdir -p bin/release + docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri bin/release/ + docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconerid bin/release/ + docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri-worker bin/release/ + + - name: Install Rust (non-Linux) + if: ${{ !matrix.use_container }} uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - - name: Install dependencies (Linux) - if: matrix.target == 'x86_64-unknown-linux-musl' - run: | - sudo apt-get update - sudo apt-get install -y musl-tools - - - name: Cache dependencies + - name: Cache dependencies (non-Linux) + if: ${{ !matrix.use_container }} uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.target }} - - name: Build + - name: Build (non-Linux) + if: ${{ !matrix.use_container }} run: cargo build --release --target ${{ matrix.target }} diff --git a/Dockerfile.build b/Dockerfile.build index aff093e..88d08ca 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,15 +1,13 @@ -FROM ekidd/rust-musl-builder:stable +FROM clux/muslrust:stable -# We need to add the source code to the image because `rust-musl-builder` -# assumes a UID of 1000, but TravisCI has switched to 2000. -ADD . ./ -RUN sudo chown -R rust:rust . +# Copy source code +COPY --chown=rust:rust . . # Extra arguments to pass to cargo. ENV CARGO_ARGS= # Build all binaries. -CMD if [ -d target ]; then sudo chown -R rust:rust /home/rust/.cargo/git /home/rust/.cargo/registry /home/rust/src/target; fi && \ +CMD if [ -d target ]; then chown -R rust:rust /volume/.cargo/git /volume/.cargo/registry /volume/target; fi && \ cargo deny check && \ - cargo build --all ${CARGO_ARGS} && \ + cargo build --all ${CARGO_ARGS} --target x86_64-unknown-linux-musl && \ cd guide && mdbook build diff --git a/justfile b/justfile index cf92a8c..0e01a47 100644 --- a/justfile +++ b/justfile @@ -47,9 +47,9 @@ _build_falconeri_container: _build_falconeri_image docker rm build-falconeri-container || true if [ "{{MODE}}" == debug ]; then docker run \ - -v falconeri-cargo-git:/home/rust/.cargo/git \ - -v falconeri-cargo-git:/home/rust/.cargo/registry \ - -v falconeri-target:/home/rust/src/target \ + -v falconeri-cargo-git:/volume/.cargo/git \ + -v falconeri-cargo-git:/volume/.cargo/registry \ + -v falconeri-target:/volume/target \ --name build-falconeri-container \ build-falconeri else @@ -62,14 +62,14 @@ _build_falconeri_container: _build_falconeri_image # Create a `bin/{{MODE}}/` directory with our various binaries. static-bin: _build_falconeri_container mkdir -p 'bin/{{MODE}}' - docker cp 'build-falconeri-container:/home/rust/src/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' - docker cp 'build-falconeri-container:/home/rust/src/target/x86_64-unknown-linux-musl/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' - docker cp 'build-falconeri-container:/home/rust/src/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' + docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' + docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' + docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' # Create a `gh-pages` directory with our "GitHub pages" documentation. gh-pages: _build_falconeri_container rm -rf gh-pages - docker cp build-falconeri-container:/home/rust/src/guide/book gh-pages + docker cp build-falconeri-container:/volume/guide/book gh-pages # Our `falconeri` Docker image. image: static-bin From e7bf5dc4a6b91dea8549ec5f3dc6062e92d99e29 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 16:09:06 -0500 Subject: [PATCH 05/28] more --- .github/workflows/ci.yml | 8 ++++++++ Dockerfile.build | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1250721..01e5f80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,6 +71,14 @@ jobs: - name: Run clippy run: cargo clippy --verbose -- -D warnings + deny: + name: Deny + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: EmbarkStudios/cargo-deny-action@v2 + build: name: Build ${{ matrix.target }} runs-on: ${{ matrix.os }} diff --git a/Dockerfile.build b/Dockerfile.build index 88d08ca..30a99b3 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -8,6 +8,5 @@ ENV CARGO_ARGS= # Build all binaries. CMD if [ -d target ]; then chown -R rust:rust /volume/.cargo/git /volume/.cargo/registry /volume/target; fi && \ - cargo deny check && \ cargo build --all ${CARGO_ARGS} --target x86_64-unknown-linux-musl && \ cd guide && mdbook build From f4685707171725544639425c178bae0af8301422 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 16:18:07 -0500 Subject: [PATCH 06/28] more fixes --- Dockerfile.build | 3 +++ falconeri_common/src/models/output_file.rs | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Dockerfile.build b/Dockerfile.build index 30a99b3..70f47c9 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,5 +1,8 @@ FROM clux/muslrust:stable +# Install PostgreSQL development libraries (needed for diesel with postgres feature) +RUN sudo apt-get update && sudo apt-get install -y libpq-dev && sudo rm -rf /var/lib/apt/lists/* + # Copy source code COPY --chown=rust:rust . . diff --git a/falconeri_common/src/models/output_file.rs b/falconeri_common/src/models/output_file.rs index 7f05dd5..72f28c9 100644 --- a/falconeri_common/src/models/output_file.rs +++ b/falconeri_common/src/models/output_file.rs @@ -123,10 +123,25 @@ impl NewOutputFile { output_files: &[Self], conn: &mut PgConnection, ) -> Result> { - let output_files = diesel::insert_into(output_files::table) + let input_count = output_files.len(); + let inserted_files = diesel::insert_into(output_files::table) .values(output_files) + .on_conflict((output_files::job_id, output_files::uri)) + .do_nothing() .get_results::(conn) - .context("error inserting datums")?; - Ok(output_files) + .context("error inserting output files")?; + + let inserted_count = inserted_files.len(); + if inserted_count < input_count { + let conflict_count = input_count - inserted_count; + tracing::warn!( + conflict_count, + input_count, + inserted_count, + "detected duplicate output files, skipped inserting due to conflicts" + ); + } + + Ok(inserted_files) } } From 216a5254afba8bba3d1fdb0a3fb17da147825e37 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 16:19:10 -0500 Subject: [PATCH 07/28] more --- Dockerfile.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.build b/Dockerfile.build index 70f47c9..c00d75a 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,7 +1,7 @@ FROM clux/muslrust:stable # Install PostgreSQL development libraries (needed for diesel with postgres feature) -RUN sudo apt-get update && sudo apt-get install -y libpq-dev && sudo rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/* # Copy source code COPY --chown=rust:rust . . From 8016a24b0dbb7fe6334ba6fb452d2767374e8c14 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 16:27:09 -0500 Subject: [PATCH 08/28] let's see --- .github/workflows/release.yml | 11 +++++++++++ Dockerfile.build | 12 +++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 065b330..68f8495 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,17 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate tag is on modernize branch + run: | + git fetch origin modernize + if ! git branch -r --contains ${{ github.ref }} | grep -q 'origin/modernize'; then + echo "Error: Tag ${{ github.ref }} is not on the modernize branch" + exit 1 + fi + echo "Tag is on modernize branch ✓" - name: Extract version from tag id: tag_version diff --git a/Dockerfile.build b/Dockerfile.build index c00d75a..f5eecbc 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,7 +1,17 @@ FROM clux/muslrust:stable # Install PostgreSQL development libraries (needed for diesel with postgres feature) -RUN apt-get update && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/* +# We need both the regular dev package and the static libraries for musl linking +RUN apt-get update && \ + apt-get install -y \ + libpq-dev \ + postgresql-server-dev-all \ + libkrb5-dev \ + && rm -rf /var/lib/apt/lists/* + +# Set environment variables to help pkg-config find the static libraries +ENV PKG_CONFIG_ALLOW_CROSS=1 +ENV PQ_LIB_STATIC=1 # Copy source code COPY --chown=rust:rust . . From f5f6e885484ed5882653a0a32605e177f86bf2bc Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 16:36:24 -0500 Subject: [PATCH 09/28] let's try --- Cargo.lock | 24 ++++++++++++++++++++++++ Dockerfile.build | 13 ++++++------- falconeri_common/Cargo.toml | 1 + 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c94deb6..4516805 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -968,6 +968,7 @@ dependencies = [ "handlebars", "humantime-serde", "lazy_static", + "pq-sys", "r2d2", "rand 0.9.2", "regex", @@ -2231,6 +2232,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "opentelemetry-semantic-conventions" version = "0.31.0" @@ -2409,6 +2422,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "pq-src" +version = "0.3.10+libpq-18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ef39ce621f4993d6084fdcd4cbf1e01c84bdba53109cfad095d2cf441b85b9" +dependencies = [ + "cc", + "openssl-sys", +] + [[package]] name = "pq-sys" version = "0.7.5" @@ -2417,6 +2440,7 @@ checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" dependencies = [ "libc", "pkg-config", + "pq-src", "vcpkg", ] diff --git a/Dockerfile.build b/Dockerfile.build index f5eecbc..fd5d02f 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,17 +1,16 @@ FROM clux/muslrust:stable -# Install PostgreSQL development libraries (needed for diesel with postgres feature) -# We need both the regular dev package and the static libraries for musl linking +# Install build tools needed for bundled libpq compilation +# The pq-sys crate with "bundled" feature will compile PostgreSQL from source +# which requires make, perl, and other build tools RUN apt-get update && \ apt-get install -y \ - libpq-dev \ - postgresql-server-dev-all \ - libkrb5-dev \ + make \ + perl \ && rm -rf /var/lib/apt/lists/* -# Set environment variables to help pkg-config find the static libraries +# Set environment variables for static linking ENV PKG_CONFIG_ALLOW_CROSS=1 -ENV PQ_LIB_STATIC=1 # Copy source code COPY --chown=rust:rust . . diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index 39b1867..aadb528 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -13,6 +13,7 @@ cast = { version = "0.3.0", features = ["std"] } chrono = { version = "0.4.42", features = ["serde"] } diesel = { version = "2.3.4", features = ["chrono", "postgres", "r2d2", "serde_json", "uuid"] } diesel_migrations = "2.3.1" +pq-sys = { version = "0.7", features = ["bundled"] } handlebars = "6.3.2" humantime-serde = "1.1.1" lazy_static = "1.5.0" From ed4da0d992b3e4a69bea84c0b796a4854fc4e9f1 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 17:22:14 -0500 Subject: [PATCH 10/28] dynamically link postgres --- CHANGELOG.md | 9 +++++++-- Dockerfile.build | 22 ++++++++++------------ falconeri_common/src/models/output_file.rs | 20 +++++++++++++++----- justfile | 10 +++++----- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d497f59..d84e686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.0.0-beta.13] - 2025-12-03 +## [Unreleased] + +### Fixed + +- Fixed race condition causing "duplicate key value violates unique constraint" errors when retrying failed datums. Output file inserts now use `ON CONFLICT DO UPDATE` to properly handle concurrent retries, ensuring workers can always update file statuses and making the entire retry flow idempotent. ### Added @@ -15,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Switched from static musl builds to dynamically-linked binaries. The build process now uses standard Rust with glibc instead of musl, requiring `libpq` to be available at runtime. This simplifies the build process and avoids static linking complications with PostgreSQL. - Updated all dependencies to latest versions. - Replaced unmaintained `structopt` with `clap` v4. - Replaced unmaintained `backoff` crate with simple built-in retry logic. @@ -112,7 +117,7 @@ We plan to stabilize a `falconeri` 1.0 with approximately this feature set. It h ### Added - Wrote some basic developer documentation to supplement the `justfile`s. -- Allow specifying `--falconerid-log-level` for `falconeri deploy`. This uses standard `RUST_LOG` syntax, as described in the CLI help. +- Allow specifying `--falconerid-log-level` for `falconeri deploy`. This uses standard `RUST_LOG` syntax, as described in the CLI help. ### Fixed diff --git a/Dockerfile.build b/Dockerfile.build index fd5d02f..4d14a59 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,24 +1,22 @@ -FROM clux/muslrust:stable +FROM rust:1.85 -# Install build tools needed for bundled libpq compilation -# The pq-sys crate with "bundled" feature will compile PostgreSQL from source -# which requires make, perl, and other build tools +# Install PostgreSQL development libraries (for dynamic linking) RUN apt-get update && \ apt-get install -y \ - make \ - perl \ + libpq-dev \ && rm -rf /var/lib/apt/lists/* -# Set environment variables for static linking -ENV PKG_CONFIG_ALLOW_CROSS=1 +# Install mdbook for building the guide +RUN cargo install mdbook + +WORKDIR /volume # Copy source code -COPY --chown=rust:rust . . +COPY . . # Extra arguments to pass to cargo. ENV CARGO_ARGS= -# Build all binaries. -CMD if [ -d target ]; then chown -R rust:rust /volume/.cargo/git /volume/.cargo/registry /volume/target; fi && \ - cargo build --all ${CARGO_ARGS} --target x86_64-unknown-linux-musl && \ +# Build all binaries (dynamically linked for x86_64-unknown-linux-gnu) +CMD cargo build --all ${CARGO_ARGS} && \ cd guide && mdbook build diff --git a/falconeri_common/src/models/output_file.rs b/falconeri_common/src/models/output_file.rs index 72f28c9..801915b 100644 --- a/falconeri_common/src/models/output_file.rs +++ b/falconeri_common/src/models/output_file.rs @@ -123,25 +123,35 @@ impl NewOutputFile { output_files: &[Self], conn: &mut PgConnection, ) -> Result> { + use diesel::upsert::excluded; + let input_count = output_files.len(); - let inserted_files = diesel::insert_into(output_files::table) + let result_files = diesel::insert_into(output_files::table) .values(output_files) .on_conflict((output_files::job_id, output_files::uri)) - .do_nothing() + .do_update() + .set(( + output_files::updated_at.eq(Utc::now().naive_utc()), + output_files::datum_id.eq(excluded(output_files::datum_id)), + )) .get_results::(conn) .context("error inserting output files")?; - let inserted_count = inserted_files.len(); + let inserted_count = result_files + .iter() + .filter(|f| f.created_at == f.updated_at) + .count(); + if inserted_count < input_count { let conflict_count = input_count - inserted_count; tracing::warn!( conflict_count, input_count, inserted_count, - "detected duplicate output files, skipped inserting due to conflicts" + "detected duplicate output files, updated existing records" ); } - Ok(inserted_files) + Ok(result_files) } } diff --git a/justfile b/justfile index 0e01a47..f33fa3d 100644 --- a/justfile +++ b/justfile @@ -60,11 +60,11 @@ _build_falconeri_container: _build_falconeri_image fi # Create a `bin/{{MODE}}/` directory with our various binaries. -static-bin: _build_falconeri_container +bin: _build_falconeri_container mkdir -p 'bin/{{MODE}}' - docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' - docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' - docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' + docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' + docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' + docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' # Create a `gh-pages` directory with our "GitHub pages" documentation. gh-pages: _build_falconeri_container @@ -72,7 +72,7 @@ gh-pages: _build_falconeri_container docker cp build-falconeri-container:/volume/guide/book gh-pages # Our `falconeri` Docker image. -image: static-bin +image: bin docker build --build-arg MODE={{MODE}} -t faraday/falconeri:{{VERSION}} . # This will publish our image to Docker Hub. Obviously, this requires an From b8931187249ceb92abb99591df16e97ad2169b50 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 17:28:46 -0500 Subject: [PATCH 11/28] simplify --- .github/workflows/ci.yml | 37 ++++++++++------------------- .github/workflows/release.yml | 44 +++++++++++++++++------------------ Dockerfile.build | 22 ------------------ build-release | 34 --------------------------- install-static | 23 ------------------ justfile | 43 ++++++++++------------------------ 6 files changed, 45 insertions(+), 158 deletions(-) delete mode 100644 Dockerfile.build delete mode 100755 build-release delete mode 100755 install-static diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01e5f80..78a4ce3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run tests - run: cargo test --verbose + run: cargo test --all-features check: name: Check @@ -38,7 +38,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run cargo check - run: cargo check --verbose + run: cargo check --all-features fmt: name: Format @@ -69,7 +69,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run clippy - run: cargo clippy --verbose -- -D warnings + run: cargo clippy --all-features -- -D warnings deny: name: Deny @@ -77,7 +77,11 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: EmbarkStudios/cargo-deny-action@v2 + - name: Install cargo-deny + run: cargo install --locked cargo-deny + + - name: Run cargo deny + run: cargo deny check advisories licenses sources build: name: Build ${{ matrix.target }} @@ -86,43 +90,26 @@ jobs: matrix: include: - os: ubuntu-latest - target: x86_64-unknown-linux-musl - use_container: true + target: x86_64-unknown-linux-gnu - os: macos-latest target: x86_64-apple-darwin - use_container: false - os: macos-latest target: aarch64-apple-darwin - use_container: false - os: windows-latest target: x86_64-pc-windows-msvc - use_container: false steps: - uses: actions/checkout@v4 - - name: Build (Linux musl with Docker) - if: matrix.use_container - run: | - docker build -f Dockerfile.build -t build-falconeri . - docker run --name build-falconeri-container -e CARGO_ARGS=--release build-falconeri - mkdir -p bin/release - docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri bin/release/ - docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconerid bin/release/ - docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri-worker bin/release/ - - - name: Install Rust (non-Linux) - if: ${{ !matrix.use_container }} + - name: Install Rust uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - - name: Cache dependencies (non-Linux) - if: ${{ !matrix.use_container }} + - name: Cache dependencies uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.target }} - - name: Build (non-Linux) - if: ${{ !matrix.use_container }} + - name: Build run: cargo build --release --target ${{ matrix.target }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68f8495..7ec4eec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,17 +14,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Validate tag is on modernize branch - run: | - git fetch origin modernize - if ! git branch -r --contains ${{ github.ref }} | grep -q 'origin/modernize'; then - echo "Error: Tag ${{ github.ref }} is not on the modernize branch" - exit 1 - fi - echo "Tag is on modernize branch ✓" - name: Extract version from tag id: tag_version @@ -59,12 +48,12 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Run tests - run: cargo test --verbose + run: cargo test --all-features - name: Run clippy run: | rustup component add clippy - cargo clippy --verbose -- -D warnings + cargo clippy --all-features -- -D warnings build: name: Build ${{ matrix.target }} @@ -74,7 +63,7 @@ jobs: matrix: include: - os: ubuntu-latest - target: x86_64-unknown-linux-musl + target: x86_64-unknown-linux-gnu archive_name: falconeri-${{ github.ref_name }}-linux-x86_64.zip - os: macos-latest target: x86_64-apple-darwin @@ -94,12 +83,6 @@ jobs: with: targets: ${{ matrix.target }} - - name: Install dependencies (Linux) - if: matrix.target == 'x86_64-unknown-linux-musl' - run: | - sudo apt-get update - sudo apt-get install -y musl-tools - - name: Build run: cargo build --release --target ${{ matrix.target }} @@ -140,14 +123,29 @@ jobs: find artifacts -name "*.zip" -exec cp {} release-files/ \; ls -lh release-files/ + - name: Extract changelog for this version + id: changelog + run: | + VERSION="${GITHUB_REF#refs/tags/v}" + echo "Extracting changelog for version $VERSION" + + # Extract the section between this version and the next one + CHANGELOG=$(awk "/## $VERSION/,/## [0-9]/" CHANGELOG.md | sed '1d;$d') + + # If empty, use a default message + if [ -z "$CHANGELOG" ]; then + CHANGELOG="Release $VERSION" + fi + + # Save to file for multi-line handling + echo "$CHANGELOG" > changelog.txt + - name: Create Release uses: softprops/action-gh-release@v2 with: files: release-files/* + body_path: changelog.txt draft: false prerelease: false - generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - diff --git a/Dockerfile.build b/Dockerfile.build deleted file mode 100644 index 4d14a59..0000000 --- a/Dockerfile.build +++ /dev/null @@ -1,22 +0,0 @@ -FROM rust:1.85 - -# Install PostgreSQL development libraries (for dynamic linking) -RUN apt-get update && \ - apt-get install -y \ - libpq-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install mdbook for building the guide -RUN cargo install mdbook - -WORKDIR /volume - -# Copy source code -COPY . . - -# Extra arguments to pass to cargo. -ENV CARGO_ARGS= - -# Build all binaries (dynamically linked for x86_64-unknown-linux-gnu) -CMD cargo build --all ${CARGO_ARGS} && \ - cd guide && mdbook build diff --git a/build-release b/build-release deleted file mode 100755 index f3ce978..0000000 --- a/build-release +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# -# Usage: ./build-release ${TRAVIS_TAG}-${TRAVIS_OS_NAME} -# -# The original/latest version of this script is available at -# https://github.com/emk/rust-musl-builder/blob/master/examples/build-release -# -# Called by `.travis.yml` to build release binaries. We use -# ekidd/rust-musl-builder to make the Linux binaries so that we can run -# them unchanged on any distro, including tiny distros like Alpine (which -# is heavily used for Docker containers). Other platforms get regular -# binaries, which will generally be dynamically linked against libc. - -set -euo pipefail - -case `uname -s` in - Linux) - echo "Building static binaries using ekidd/rust-musl-builder" - docker build -f Dockerfile.build -t build-"$1" . - docker run -e CARGO_ARGS=--release --name build-"$1"-run build-"$1" - mkdir bin - docker cp build-"$1"-run:/home/rust/src/target/x86_64-unknown-linux-musl/release/falconeri bin/falconeri - docker cp build-"$1"-run:/home/rust/src/target/x86_64-unknown-linux-musl/release/falconeri-worker bin/falconeri-worker - docker cp build-"$1"-run:/home/rust/src/guide/book gh-pages - docker rm build-"$1"-run - docker rmi build-"$1" - zip -j "$1"_"$2".zip bin/falconeri bin/falconeri-worker - ;; - *) - echo "Building standard release binaries" - cargo build -p falconeri --release - zip -j "$1"_"$2".zip target/release/"$1" - ;; -esac diff --git a/install-static b/install-static deleted file mode 100755 index 9ee68ed..0000000 --- a/install-static +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# -# Usage: ./install-static -# -# Build a static version of the `falconeri` tools and install it. Only works on -# x86_64 systems. This assumes the current user has UID 1000. (We can remove -# that restriction later by adding the source to the container and mounting -# a volume on ./target, then using `docker cp` to copy out the binaries.) - -# Standard paranoia. -set -euo pipefail - -# Build our binaries. -docker run --rm -it \ - -v falconeri-cargo-git:/home/rust/.cargo/git \ - -v falconeri-cargo-registry:/home/rust/.cargo/registry \ - -v "$(pwd)":/home/rust/src \ - ekidd/rust-musl-builder \ - bash -c 'sudo chown -R rust:rust /home/rust/.cargo/git /home/rust/.cargo/registry && cargo build --all --release' - -# Install our binaries. -target_dir=./target/x86_64-unknown-linux-musl/release -sudo cp "$target_dir/falconeri" "$target_dir/falconeri-worker" /usr/local/bin diff --git a/justfile b/justfile index f33fa3d..448a7b2 100644 --- a/justfile +++ b/justfile @@ -9,8 +9,7 @@ # 1. Run `just set-version 0.x.y-alpha.z`, where `0.x.y` will be the next # release. # 2. Run `just publish-image`. -# 3. Grab `bin/debug/falconeri-worker` and rebuild your worker image. -# 4. Run `cargo run -p falconeri -- deploy` to update `falconerid`. +# 3. Run `cargo run -p falconeri -- deploy` to update `falconerid`. # This should be either "debug" or "release". You can pass `mode=release` on # the command line to perform a release build. @@ -34,42 +33,25 @@ set-version NEW_VERSION: # If this fails, run `cargo install cargo-edit`. cargo set-version --workspace {{NEW_VERSION}} -# The docker image `build-falconeri`, which we use to compile things. -_build_falconeri_image: - docker build -f Dockerfile.build -t build-falconeri . - -# The container `build-falconeri-run`, which contains our binaries and docs. -# -# This uses a bash script so it can get access to more features. -_build_falconeri_container: _build_falconeri_image +# Build all binaries and create a `bin/{{MODE}}/` directory. +bin: #!/usr/bin/env bash set -euo pipefail - docker rm build-falconeri-container || true - if [ "{{MODE}}" == debug ]; then - docker run \ - -v falconeri-cargo-git:/volume/.cargo/git \ - -v falconeri-cargo-git:/volume/.cargo/registry \ - -v falconeri-target:/volume/target \ - --name build-falconeri-container \ - build-falconeri + if [ "{{MODE}}" == "release" ]; then + cargo build --all --release else - docker run \ - -e CARGO_ARGS=--release \ - --name build-falconeri-container \ - build-falconeri + cargo build --all fi - -# Create a `bin/{{MODE}}/` directory with our various binaries. -bin: _build_falconeri_container mkdir -p 'bin/{{MODE}}' - docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' - docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' - docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' + cp 'target/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' + cp 'target/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' + cp 'target/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' # Create a `gh-pages` directory with our "GitHub pages" documentation. -gh-pages: _build_falconeri_container +gh-pages: + cd guide && mdbook build rm -rf gh-pages - docker cp build-falconeri-container:/volume/guide/book gh-pages + cp -r guide/book gh-pages # Our `falconeri` Docker image. image: bin @@ -104,7 +86,6 @@ check-clean: # # just set-version x.y.z-alpha.n # just publish-image -# # Copy falconeri-worker from bin/debug # # Call this as: # From 3fbc36a99899a9e8d2d939c6a96dd6d0895744cc Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 17:34:16 -0500 Subject: [PATCH 12/28] unbundle --- Cargo.lock | 23 ----------------------- falconeri_common/Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4516805..4314d34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2232,18 +2232,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "opentelemetry-semantic-conventions" version = "0.31.0" @@ -2422,16 +2410,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "pq-src" -version = "0.3.10+libpq-18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ef39ce621f4993d6084fdcd4cbf1e01c84bdba53109cfad095d2cf441b85b9" -dependencies = [ - "cc", - "openssl-sys", -] - [[package]] name = "pq-sys" version = "0.7.5" @@ -2440,7 +2418,6 @@ checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" dependencies = [ "libc", "pkg-config", - "pq-src", "vcpkg", ] diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index aadb528..15909c4 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -13,7 +13,7 @@ cast = { version = "0.3.0", features = ["std"] } chrono = { version = "0.4.42", features = ["serde"] } diesel = { version = "2.3.4", features = ["chrono", "postgres", "r2d2", "serde_json", "uuid"] } diesel_migrations = "2.3.1" -pq-sys = { version = "0.7", features = ["bundled"] } +pq-sys = "0.7" handlebars = "6.3.2" humantime-serde = "1.1.1" lazy_static = "1.5.0" From 49a6218c13068fe79fb447d8d274e1b8cf8f2056 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 17:43:28 -0500 Subject: [PATCH 13/28] no more auto compress. fix postgres on mac and windows --- .github/workflows/ci.yml | 8 ++++++++ CHANGELOG.md | 2 +- Cargo.lock | 27 --------------------------- falconeri_common/Cargo.toml | 1 - falconeri_common/src/storage/gs.rs | 28 ++++++---------------------- 5 files changed, 15 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78a4ce3..e09e978 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,6 +101,14 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install PostgreSQL (macOS) + if: runner.os == 'macOS' + run: brew install postgresql@14 + + - name: Install PostgreSQL (Windows) + if: runner.os == 'Windows' + run: choco install postgresql14 --params '/Password:postgres' --no-progress + - name: Install Rust uses: dtolnay/rust-toolchain@stable with: diff --git a/CHANGELOG.md b/CHANGELOG.md index d84e686..d44f8dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Native Google Cloud Storage (GCS) support using the official `google-cloud-rust` SDK. -- Support for `gs://` URIs with automatic compression/decompression. +- Support for `gs://` URIs. Automatic decompression for files that were uploaded with Content-Encoding: gzip. - Authentication via `GCLOUD_SERVICE_ACCOUNT_KEY` environment variable or standard Application Default Credentials. ### Changed diff --git a/Cargo.lock b/Cargo.lock index 4314d34..4d5ba7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,15 +494,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossbeam" version = "0.8.4" @@ -960,7 +951,6 @@ dependencies = [ "chrono", "diesel", "diesel_migrations", - "flate2", "futures", "glob", "google-cloud-auth", @@ -1025,16 +1015,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" -[[package]] -name = "flate2" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "fnv" version = "1.0.7" @@ -2123,7 +2103,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", - "simd-adler32", ] [[package]] @@ -3278,12 +3257,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - [[package]] name = "slab" version = "0.4.11" diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index 15909c4..38b373c 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -34,5 +34,4 @@ tokio = { version = "1.48", features = ["rt-multi-thread", "macros", "fs"] } tokio-util = { version = "0.7", features = ["io", "compat"] } futures = "0.3" bytes = "1.11" -flate2 = "1.1" glob = "0.3" diff --git a/falconeri_common/src/storage/gs.rs b/falconeri_common/src/storage/gs.rs index f0d6ad3..e3412b8 100644 --- a/falconeri_common/src/storage/gs.rs +++ b/falconeri_common/src/storage/gs.rs @@ -1,7 +1,6 @@ //! Support for Google Cloud Storage. use std::future::Future; -use std::io::Write; use std::path::Path; use google_cloud_auth::credentials::service_account; @@ -183,8 +182,7 @@ impl CloudStorage for GoogleCloudStorage { ) }; - // Upload the file with gzip compression - self.upload_file_compressed(&bucket, &object_name, &entry)?; + self.upload_file(&bucket, &object_name, &entry)?; } Ok(()) @@ -210,7 +208,8 @@ impl GoogleCloudStorage { // Format bucket name with projects/_/buckets/ prefix let bucket_path = format!("projects/_/buckets/{}", bucket); - // Download with automatic decompression enabled + // Download with automatic decompression enabled - this only affects files + // with Content-Encoding: gzip, not files that are natively .gz format let mut reader = self .client .read_object(&bucket_path, object) @@ -229,37 +228,22 @@ impl GoogleCloudStorage { }) } - /// Upload a single file to GCS with gzip compression. - fn upload_file_compressed( + /// Upload a single file to GCS. + fn upload_file( &self, bucket: &str, object: &str, local_path: &Path, ) -> Result<()> { - use flate2::Compression; - run_async(async { - // Read entire file into memory let data = std::fs::read(local_path) .with_context(|| format!("failed to read {}", local_path.display()))?; - // Compress with gzip - let mut encoder = - flate2::write::GzEncoder::new(Vec::new(), Compression::default()); - encoder.write_all(&data)?; - let compressed_data = encoder.finish()?; - // Format bucket name with projects/_/buckets/ prefix let bucket_path = format!("projects/_/buckets/{}", bucket); - // Upload with Content-Encoding: gzip self.client - .write_object( - &bucket_path, - object, - bytes::Bytes::from(compressed_data), - ) - .set_content_encoding("gzip") + .write_object(&bucket_path, object, bytes::Bytes::from(data)) .send_buffered() .await?; From 8792213320f3f77040a4c3a562357688c1cd16b0 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 17:55:03 -0500 Subject: [PATCH 14/28] thing --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e09e978..ab3e5b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,7 +103,7 @@ jobs: - name: Install PostgreSQL (macOS) if: runner.os == 'macOS' - run: brew install postgresql@14 + run: brew install libpq - name: Install PostgreSQL (Windows) if: runner.os == 'Windows' From c5d353a9021b247c12ee0c06b03d3f9fac49b17f Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:01:57 -0500 Subject: [PATCH 15/28] Try --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab3e5b3..fbb2bd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,7 +103,10 @@ jobs: - name: Install PostgreSQL (macOS) if: runner.os == 'macOS' - run: brew install libpq + run: | + brew install libpq + echo "export LDFLAGS=\"-L/usr/local/opt/libpq/lib\"" >> $GITHUB_ENV + echo "export CPPFLAGS=\"-I/usr/local/opt/libpq/include\"" >> $GITHUB_ENV - name: Install PostgreSQL (Windows) if: runner.os == 'Windows' From 75ba95c1ba60aaba318366dc95b2ce6b5a29a2b1 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:18 -0500 Subject: [PATCH 16/28] Revert "Try" This reverts commit c5d353a9021b247c12ee0c06b03d3f9fac49b17f. --- .github/workflows/ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbb2bd3..ab3e5b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,10 +103,7 @@ jobs: - name: Install PostgreSQL (macOS) if: runner.os == 'macOS' - run: | - brew install libpq - echo "export LDFLAGS=\"-L/usr/local/opt/libpq/lib\"" >> $GITHUB_ENV - echo "export CPPFLAGS=\"-I/usr/local/opt/libpq/include\"" >> $GITHUB_ENV + run: brew install libpq - name: Install PostgreSQL (Windows) if: runner.os == 'Windows' From 34375de0e494c67a3c62f9985c12bb5464545239 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:21 -0500 Subject: [PATCH 17/28] Revert "thing" This reverts commit 8792213320f3f77040a4c3a562357688c1cd16b0. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab3e5b3..e09e978 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,7 +103,7 @@ jobs: - name: Install PostgreSQL (macOS) if: runner.os == 'macOS' - run: brew install libpq + run: brew install postgresql@14 - name: Install PostgreSQL (Windows) if: runner.os == 'Windows' From c7622391289439948b1fc86e1fba19ddd5114ce3 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:25 -0500 Subject: [PATCH 18/28] Revert "no more auto compress. fix postgres on mac and windows" This reverts commit 49a6218c13068fe79fb447d8d274e1b8cf8f2056. --- .github/workflows/ci.yml | 8 -------- CHANGELOG.md | 2 +- Cargo.lock | 27 +++++++++++++++++++++++++++ falconeri_common/Cargo.toml | 1 + falconeri_common/src/storage/gs.rs | 28 ++++++++++++++++++++++------ 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e09e978..78a4ce3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,14 +101,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install PostgreSQL (macOS) - if: runner.os == 'macOS' - run: brew install postgresql@14 - - - name: Install PostgreSQL (Windows) - if: runner.os == 'Windows' - run: choco install postgresql14 --params '/Password:postgres' --no-progress - - name: Install Rust uses: dtolnay/rust-toolchain@stable with: diff --git a/CHANGELOG.md b/CHANGELOG.md index d44f8dd..d84e686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Native Google Cloud Storage (GCS) support using the official `google-cloud-rust` SDK. -- Support for `gs://` URIs. Automatic decompression for files that were uploaded with Content-Encoding: gzip. +- Support for `gs://` URIs with automatic compression/decompression. - Authentication via `GCLOUD_SERVICE_ACCOUNT_KEY` environment variable or standard Application Default Credentials. ### Changed diff --git a/Cargo.lock b/Cargo.lock index 4d5ba7b..4314d34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,6 +494,15 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -951,6 +960,7 @@ dependencies = [ "chrono", "diesel", "diesel_migrations", + "flate2", "futures", "glob", "google-cloud-auth", @@ -1015,6 +1025,16 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2103,6 +2123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -3257,6 +3278,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + [[package]] name = "slab" version = "0.4.11" diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index 38b373c..15909c4 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -34,4 +34,5 @@ tokio = { version = "1.48", features = ["rt-multi-thread", "macros", "fs"] } tokio-util = { version = "0.7", features = ["io", "compat"] } futures = "0.3" bytes = "1.11" +flate2 = "1.1" glob = "0.3" diff --git a/falconeri_common/src/storage/gs.rs b/falconeri_common/src/storage/gs.rs index e3412b8..f0d6ad3 100644 --- a/falconeri_common/src/storage/gs.rs +++ b/falconeri_common/src/storage/gs.rs @@ -1,6 +1,7 @@ //! Support for Google Cloud Storage. use std::future::Future; +use std::io::Write; use std::path::Path; use google_cloud_auth::credentials::service_account; @@ -182,7 +183,8 @@ impl CloudStorage for GoogleCloudStorage { ) }; - self.upload_file(&bucket, &object_name, &entry)?; + // Upload the file with gzip compression + self.upload_file_compressed(&bucket, &object_name, &entry)?; } Ok(()) @@ -208,8 +210,7 @@ impl GoogleCloudStorage { // Format bucket name with projects/_/buckets/ prefix let bucket_path = format!("projects/_/buckets/{}", bucket); - // Download with automatic decompression enabled - this only affects files - // with Content-Encoding: gzip, not files that are natively .gz format + // Download with automatic decompression enabled let mut reader = self .client .read_object(&bucket_path, object) @@ -228,22 +229,37 @@ impl GoogleCloudStorage { }) } - /// Upload a single file to GCS. - fn upload_file( + /// Upload a single file to GCS with gzip compression. + fn upload_file_compressed( &self, bucket: &str, object: &str, local_path: &Path, ) -> Result<()> { + use flate2::Compression; + run_async(async { + // Read entire file into memory let data = std::fs::read(local_path) .with_context(|| format!("failed to read {}", local_path.display()))?; + // Compress with gzip + let mut encoder = + flate2::write::GzEncoder::new(Vec::new(), Compression::default()); + encoder.write_all(&data)?; + let compressed_data = encoder.finish()?; + // Format bucket name with projects/_/buckets/ prefix let bucket_path = format!("projects/_/buckets/{}", bucket); + // Upload with Content-Encoding: gzip self.client - .write_object(&bucket_path, object, bytes::Bytes::from(data)) + .write_object( + &bucket_path, + object, + bytes::Bytes::from(compressed_data), + ) + .set_content_encoding("gzip") .send_buffered() .await?; From 172ad172a7b1f4acb86401fd0ecb8fce2ce912fb Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:27 -0500 Subject: [PATCH 19/28] Revert "unbundle" This reverts commit 3fbc36a99899a9e8d2d939c6a96dd6d0895744cc. --- Cargo.lock | 23 +++++++++++++++++++++++ falconeri_common/Cargo.toml | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 4314d34..4516805 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2232,6 +2232,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "opentelemetry-semantic-conventions" version = "0.31.0" @@ -2410,6 +2422,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "pq-src" +version = "0.3.10+libpq-18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ef39ce621f4993d6084fdcd4cbf1e01c84bdba53109cfad095d2cf441b85b9" +dependencies = [ + "cc", + "openssl-sys", +] + [[package]] name = "pq-sys" version = "0.7.5" @@ -2418,6 +2440,7 @@ checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" dependencies = [ "libc", "pkg-config", + "pq-src", "vcpkg", ] diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index 15909c4..aadb528 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -13,7 +13,7 @@ cast = { version = "0.3.0", features = ["std"] } chrono = { version = "0.4.42", features = ["serde"] } diesel = { version = "2.3.4", features = ["chrono", "postgres", "r2d2", "serde_json", "uuid"] } diesel_migrations = "2.3.1" -pq-sys = "0.7" +pq-sys = { version = "0.7", features = ["bundled"] } handlebars = "6.3.2" humantime-serde = "1.1.1" lazy_static = "1.5.0" From b5802d5f5433473846f4439e48ea1356845db747 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:29 -0500 Subject: [PATCH 20/28] Revert "simplify" This reverts commit b8931187249ceb92abb99591df16e97ad2169b50. --- .github/workflows/ci.yml | 37 +++++++++++++++++++---------- .github/workflows/release.yml | 44 ++++++++++++++++++----------------- Dockerfile.build | 22 ++++++++++++++++++ build-release | 34 +++++++++++++++++++++++++++ install-static | 23 ++++++++++++++++++ justfile | 43 ++++++++++++++++++++++++---------- 6 files changed, 158 insertions(+), 45 deletions(-) create mode 100644 Dockerfile.build create mode 100755 build-release create mode 100755 install-static diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78a4ce3..01e5f80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run tests - run: cargo test --all-features + run: cargo test --verbose check: name: Check @@ -38,7 +38,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run cargo check - run: cargo check --all-features + run: cargo check --verbose fmt: name: Format @@ -69,7 +69,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run clippy - run: cargo clippy --all-features -- -D warnings + run: cargo clippy --verbose -- -D warnings deny: name: Deny @@ -77,11 +77,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install cargo-deny - run: cargo install --locked cargo-deny - - - name: Run cargo deny - run: cargo deny check advisories licenses sources + - uses: EmbarkStudios/cargo-deny-action@v2 build: name: Build ${{ matrix.target }} @@ -90,26 +86,43 @@ jobs: matrix: include: - os: ubuntu-latest - target: x86_64-unknown-linux-gnu + target: x86_64-unknown-linux-musl + use_container: true - os: macos-latest target: x86_64-apple-darwin + use_container: false - os: macos-latest target: aarch64-apple-darwin + use_container: false - os: windows-latest target: x86_64-pc-windows-msvc + use_container: false steps: - uses: actions/checkout@v4 - - name: Install Rust + - name: Build (Linux musl with Docker) + if: matrix.use_container + run: | + docker build -f Dockerfile.build -t build-falconeri . + docker run --name build-falconeri-container -e CARGO_ARGS=--release build-falconeri + mkdir -p bin/release + docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri bin/release/ + docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconerid bin/release/ + docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri-worker bin/release/ + + - name: Install Rust (non-Linux) + if: ${{ !matrix.use_container }} uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - - name: Cache dependencies + - name: Cache dependencies (non-Linux) + if: ${{ !matrix.use_container }} uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.target }} - - name: Build + - name: Build (non-Linux) + if: ${{ !matrix.use_container }} run: cargo build --release --target ${{ matrix.target }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7ec4eec..68f8495 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,17 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate tag is on modernize branch + run: | + git fetch origin modernize + if ! git branch -r --contains ${{ github.ref }} | grep -q 'origin/modernize'; then + echo "Error: Tag ${{ github.ref }} is not on the modernize branch" + exit 1 + fi + echo "Tag is on modernize branch ✓" - name: Extract version from tag id: tag_version @@ -48,12 +59,12 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Run tests - run: cargo test --all-features + run: cargo test --verbose - name: Run clippy run: | rustup component add clippy - cargo clippy --all-features -- -D warnings + cargo clippy --verbose -- -D warnings build: name: Build ${{ matrix.target }} @@ -63,7 +74,7 @@ jobs: matrix: include: - os: ubuntu-latest - target: x86_64-unknown-linux-gnu + target: x86_64-unknown-linux-musl archive_name: falconeri-${{ github.ref_name }}-linux-x86_64.zip - os: macos-latest target: x86_64-apple-darwin @@ -83,6 +94,12 @@ jobs: with: targets: ${{ matrix.target }} + - name: Install dependencies (Linux) + if: matrix.target == 'x86_64-unknown-linux-musl' + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + - name: Build run: cargo build --release --target ${{ matrix.target }} @@ -123,29 +140,14 @@ jobs: find artifacts -name "*.zip" -exec cp {} release-files/ \; ls -lh release-files/ - - name: Extract changelog for this version - id: changelog - run: | - VERSION="${GITHUB_REF#refs/tags/v}" - echo "Extracting changelog for version $VERSION" - - # Extract the section between this version and the next one - CHANGELOG=$(awk "/## $VERSION/,/## [0-9]/" CHANGELOG.md | sed '1d;$d') - - # If empty, use a default message - if [ -z "$CHANGELOG" ]; then - CHANGELOG="Release $VERSION" - fi - - # Save to file for multi-line handling - echo "$CHANGELOG" > changelog.txt - - name: Create Release uses: softprops/action-gh-release@v2 with: files: release-files/* - body_path: changelog.txt draft: false prerelease: false + generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + diff --git a/Dockerfile.build b/Dockerfile.build new file mode 100644 index 0000000..4d14a59 --- /dev/null +++ b/Dockerfile.build @@ -0,0 +1,22 @@ +FROM rust:1.85 + +# Install PostgreSQL development libraries (for dynamic linking) +RUN apt-get update && \ + apt-get install -y \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install mdbook for building the guide +RUN cargo install mdbook + +WORKDIR /volume + +# Copy source code +COPY . . + +# Extra arguments to pass to cargo. +ENV CARGO_ARGS= + +# Build all binaries (dynamically linked for x86_64-unknown-linux-gnu) +CMD cargo build --all ${CARGO_ARGS} && \ + cd guide && mdbook build diff --git a/build-release b/build-release new file mode 100755 index 0000000..f3ce978 --- /dev/null +++ b/build-release @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Usage: ./build-release ${TRAVIS_TAG}-${TRAVIS_OS_NAME} +# +# The original/latest version of this script is available at +# https://github.com/emk/rust-musl-builder/blob/master/examples/build-release +# +# Called by `.travis.yml` to build release binaries. We use +# ekidd/rust-musl-builder to make the Linux binaries so that we can run +# them unchanged on any distro, including tiny distros like Alpine (which +# is heavily used for Docker containers). Other platforms get regular +# binaries, which will generally be dynamically linked against libc. + +set -euo pipefail + +case `uname -s` in + Linux) + echo "Building static binaries using ekidd/rust-musl-builder" + docker build -f Dockerfile.build -t build-"$1" . + docker run -e CARGO_ARGS=--release --name build-"$1"-run build-"$1" + mkdir bin + docker cp build-"$1"-run:/home/rust/src/target/x86_64-unknown-linux-musl/release/falconeri bin/falconeri + docker cp build-"$1"-run:/home/rust/src/target/x86_64-unknown-linux-musl/release/falconeri-worker bin/falconeri-worker + docker cp build-"$1"-run:/home/rust/src/guide/book gh-pages + docker rm build-"$1"-run + docker rmi build-"$1" + zip -j "$1"_"$2".zip bin/falconeri bin/falconeri-worker + ;; + *) + echo "Building standard release binaries" + cargo build -p falconeri --release + zip -j "$1"_"$2".zip target/release/"$1" + ;; +esac diff --git a/install-static b/install-static new file mode 100755 index 0000000..9ee68ed --- /dev/null +++ b/install-static @@ -0,0 +1,23 @@ +#!/bin/bash +# +# Usage: ./install-static +# +# Build a static version of the `falconeri` tools and install it. Only works on +# x86_64 systems. This assumes the current user has UID 1000. (We can remove +# that restriction later by adding the source to the container and mounting +# a volume on ./target, then using `docker cp` to copy out the binaries.) + +# Standard paranoia. +set -euo pipefail + +# Build our binaries. +docker run --rm -it \ + -v falconeri-cargo-git:/home/rust/.cargo/git \ + -v falconeri-cargo-registry:/home/rust/.cargo/registry \ + -v "$(pwd)":/home/rust/src \ + ekidd/rust-musl-builder \ + bash -c 'sudo chown -R rust:rust /home/rust/.cargo/git /home/rust/.cargo/registry && cargo build --all --release' + +# Install our binaries. +target_dir=./target/x86_64-unknown-linux-musl/release +sudo cp "$target_dir/falconeri" "$target_dir/falconeri-worker" /usr/local/bin diff --git a/justfile b/justfile index 448a7b2..f33fa3d 100644 --- a/justfile +++ b/justfile @@ -9,7 +9,8 @@ # 1. Run `just set-version 0.x.y-alpha.z`, where `0.x.y` will be the next # release. # 2. Run `just publish-image`. -# 3. Run `cargo run -p falconeri -- deploy` to update `falconerid`. +# 3. Grab `bin/debug/falconeri-worker` and rebuild your worker image. +# 4. Run `cargo run -p falconeri -- deploy` to update `falconerid`. # This should be either "debug" or "release". You can pass `mode=release` on # the command line to perform a release build. @@ -33,25 +34,42 @@ set-version NEW_VERSION: # If this fails, run `cargo install cargo-edit`. cargo set-version --workspace {{NEW_VERSION}} -# Build all binaries and create a `bin/{{MODE}}/` directory. -bin: +# The docker image `build-falconeri`, which we use to compile things. +_build_falconeri_image: + docker build -f Dockerfile.build -t build-falconeri . + +# The container `build-falconeri-run`, which contains our binaries and docs. +# +# This uses a bash script so it can get access to more features. +_build_falconeri_container: _build_falconeri_image #!/usr/bin/env bash set -euo pipefail - if [ "{{MODE}}" == "release" ]; then - cargo build --all --release + docker rm build-falconeri-container || true + if [ "{{MODE}}" == debug ]; then + docker run \ + -v falconeri-cargo-git:/volume/.cargo/git \ + -v falconeri-cargo-git:/volume/.cargo/registry \ + -v falconeri-target:/volume/target \ + --name build-falconeri-container \ + build-falconeri else - cargo build --all + docker run \ + -e CARGO_ARGS=--release \ + --name build-falconeri-container \ + build-falconeri fi + +# Create a `bin/{{MODE}}/` directory with our various binaries. +bin: _build_falconeri_container mkdir -p 'bin/{{MODE}}' - cp 'target/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' - cp 'target/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' - cp 'target/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' + docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' + docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' + docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' # Create a `gh-pages` directory with our "GitHub pages" documentation. -gh-pages: - cd guide && mdbook build +gh-pages: _build_falconeri_container rm -rf gh-pages - cp -r guide/book gh-pages + docker cp build-falconeri-container:/volume/guide/book gh-pages # Our `falconeri` Docker image. image: bin @@ -86,6 +104,7 @@ check-clean: # # just set-version x.y.z-alpha.n # just publish-image +# # Copy falconeri-worker from bin/debug # # Call this as: # From f6e23ce479e514d5daeb00adff3e6008516440d0 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:31 -0500 Subject: [PATCH 21/28] Revert "dynamically link postgres" This reverts commit ed4da0d992b3e4a69bea84c0b796a4854fc4e9f1. --- CHANGELOG.md | 9 ++------- Dockerfile.build | 22 ++++++++++++---------- falconeri_common/src/models/output_file.rs | 20 +++++--------------- justfile | 10 +++++----- 4 files changed, 24 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d84e686..d497f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] - -### Fixed - -- Fixed race condition causing "duplicate key value violates unique constraint" errors when retrying failed datums. Output file inserts now use `ON CONFLICT DO UPDATE` to properly handle concurrent retries, ensuring workers can always update file statuses and making the entire retry flow idempotent. +## [1.0.0-beta.13] - 2025-12-03 ### Added @@ -19,7 +15,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Switched from static musl builds to dynamically-linked binaries. The build process now uses standard Rust with glibc instead of musl, requiring `libpq` to be available at runtime. This simplifies the build process and avoids static linking complications with PostgreSQL. - Updated all dependencies to latest versions. - Replaced unmaintained `structopt` with `clap` v4. - Replaced unmaintained `backoff` crate with simple built-in retry logic. @@ -117,7 +112,7 @@ We plan to stabilize a `falconeri` 1.0 with approximately this feature set. It h ### Added - Wrote some basic developer documentation to supplement the `justfile`s. -- Allow specifying `--falconerid-log-level` for `falconeri deploy`. This uses standard `RUST_LOG` syntax, as described in the CLI help. +- Allow specifying `--falconerid-log-level` for `falconeri deploy`. This uses standard `RUST_LOG` syntax, as described in the CLI help. ### Fixed diff --git a/Dockerfile.build b/Dockerfile.build index 4d14a59..fd5d02f 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,22 +1,24 @@ -FROM rust:1.85 +FROM clux/muslrust:stable -# Install PostgreSQL development libraries (for dynamic linking) +# Install build tools needed for bundled libpq compilation +# The pq-sys crate with "bundled" feature will compile PostgreSQL from source +# which requires make, perl, and other build tools RUN apt-get update && \ apt-get install -y \ - libpq-dev \ + make \ + perl \ && rm -rf /var/lib/apt/lists/* -# Install mdbook for building the guide -RUN cargo install mdbook - -WORKDIR /volume +# Set environment variables for static linking +ENV PKG_CONFIG_ALLOW_CROSS=1 # Copy source code -COPY . . +COPY --chown=rust:rust . . # Extra arguments to pass to cargo. ENV CARGO_ARGS= -# Build all binaries (dynamically linked for x86_64-unknown-linux-gnu) -CMD cargo build --all ${CARGO_ARGS} && \ +# Build all binaries. +CMD if [ -d target ]; then chown -R rust:rust /volume/.cargo/git /volume/.cargo/registry /volume/target; fi && \ + cargo build --all ${CARGO_ARGS} --target x86_64-unknown-linux-musl && \ cd guide && mdbook build diff --git a/falconeri_common/src/models/output_file.rs b/falconeri_common/src/models/output_file.rs index 801915b..72f28c9 100644 --- a/falconeri_common/src/models/output_file.rs +++ b/falconeri_common/src/models/output_file.rs @@ -123,35 +123,25 @@ impl NewOutputFile { output_files: &[Self], conn: &mut PgConnection, ) -> Result> { - use diesel::upsert::excluded; - let input_count = output_files.len(); - let result_files = diesel::insert_into(output_files::table) + let inserted_files = diesel::insert_into(output_files::table) .values(output_files) .on_conflict((output_files::job_id, output_files::uri)) - .do_update() - .set(( - output_files::updated_at.eq(Utc::now().naive_utc()), - output_files::datum_id.eq(excluded(output_files::datum_id)), - )) + .do_nothing() .get_results::(conn) .context("error inserting output files")?; - let inserted_count = result_files - .iter() - .filter(|f| f.created_at == f.updated_at) - .count(); - + let inserted_count = inserted_files.len(); if inserted_count < input_count { let conflict_count = input_count - inserted_count; tracing::warn!( conflict_count, input_count, inserted_count, - "detected duplicate output files, updated existing records" + "detected duplicate output files, skipped inserting due to conflicts" ); } - Ok(result_files) + Ok(inserted_files) } } diff --git a/justfile b/justfile index f33fa3d..0e01a47 100644 --- a/justfile +++ b/justfile @@ -60,11 +60,11 @@ _build_falconeri_container: _build_falconeri_image fi # Create a `bin/{{MODE}}/` directory with our various binaries. -bin: _build_falconeri_container +static-bin: _build_falconeri_container mkdir -p 'bin/{{MODE}}' - docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' - docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' - docker cp 'build-falconeri-container:/volume/target/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' + docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' + docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' + docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' # Create a `gh-pages` directory with our "GitHub pages" documentation. gh-pages: _build_falconeri_container @@ -72,7 +72,7 @@ gh-pages: _build_falconeri_container docker cp build-falconeri-container:/volume/guide/book gh-pages # Our `falconeri` Docker image. -image: bin +image: static-bin docker build --build-arg MODE={{MODE}} -t faraday/falconeri:{{VERSION}} . # This will publish our image to Docker Hub. Obviously, this requires an From 8562167365db330ab76b8b06962f2a24e8b43d95 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:34 -0500 Subject: [PATCH 22/28] Revert "let's try" This reverts commit f5f6e885484ed5882653a0a32605e177f86bf2bc. --- Cargo.lock | 24 ------------------------ Dockerfile.build | 13 +++++++------ falconeri_common/Cargo.toml | 1 - 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4516805..c94deb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -968,7 +968,6 @@ dependencies = [ "handlebars", "humantime-serde", "lazy_static", - "pq-sys", "r2d2", "rand 0.9.2", "regex", @@ -2232,18 +2231,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "opentelemetry-semantic-conventions" version = "0.31.0" @@ -2422,16 +2409,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "pq-src" -version = "0.3.10+libpq-18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ef39ce621f4993d6084fdcd4cbf1e01c84bdba53109cfad095d2cf441b85b9" -dependencies = [ - "cc", - "openssl-sys", -] - [[package]] name = "pq-sys" version = "0.7.5" @@ -2440,7 +2417,6 @@ checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" dependencies = [ "libc", "pkg-config", - "pq-src", "vcpkg", ] diff --git a/Dockerfile.build b/Dockerfile.build index fd5d02f..f5eecbc 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,16 +1,17 @@ FROM clux/muslrust:stable -# Install build tools needed for bundled libpq compilation -# The pq-sys crate with "bundled" feature will compile PostgreSQL from source -# which requires make, perl, and other build tools +# Install PostgreSQL development libraries (needed for diesel with postgres feature) +# We need both the regular dev package and the static libraries for musl linking RUN apt-get update && \ apt-get install -y \ - make \ - perl \ + libpq-dev \ + postgresql-server-dev-all \ + libkrb5-dev \ && rm -rf /var/lib/apt/lists/* -# Set environment variables for static linking +# Set environment variables to help pkg-config find the static libraries ENV PKG_CONFIG_ALLOW_CROSS=1 +ENV PQ_LIB_STATIC=1 # Copy source code COPY --chown=rust:rust . . diff --git a/falconeri_common/Cargo.toml b/falconeri_common/Cargo.toml index aadb528..39b1867 100644 --- a/falconeri_common/Cargo.toml +++ b/falconeri_common/Cargo.toml @@ -13,7 +13,6 @@ cast = { version = "0.3.0", features = ["std"] } chrono = { version = "0.4.42", features = ["serde"] } diesel = { version = "2.3.4", features = ["chrono", "postgres", "r2d2", "serde_json", "uuid"] } diesel_migrations = "2.3.1" -pq-sys = { version = "0.7", features = ["bundled"] } handlebars = "6.3.2" humantime-serde = "1.1.1" lazy_static = "1.5.0" From 88fa40e1509694a429d837a71da301c705a6ed4b Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:36 -0500 Subject: [PATCH 23/28] Revert "let's see" This reverts commit 8016a24b0dbb7fe6334ba6fb452d2767374e8c14. --- .github/workflows/release.yml | 11 ----------- Dockerfile.build | 12 +----------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68f8495..065b330 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,17 +14,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Validate tag is on modernize branch - run: | - git fetch origin modernize - if ! git branch -r --contains ${{ github.ref }} | grep -q 'origin/modernize'; then - echo "Error: Tag ${{ github.ref }} is not on the modernize branch" - exit 1 - fi - echo "Tag is on modernize branch ✓" - name: Extract version from tag id: tag_version diff --git a/Dockerfile.build b/Dockerfile.build index f5eecbc..c00d75a 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,17 +1,7 @@ FROM clux/muslrust:stable # Install PostgreSQL development libraries (needed for diesel with postgres feature) -# We need both the regular dev package and the static libraries for musl linking -RUN apt-get update && \ - apt-get install -y \ - libpq-dev \ - postgresql-server-dev-all \ - libkrb5-dev \ - && rm -rf /var/lib/apt/lists/* - -# Set environment variables to help pkg-config find the static libraries -ENV PKG_CONFIG_ALLOW_CROSS=1 -ENV PQ_LIB_STATIC=1 +RUN apt-get update && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/* # Copy source code COPY --chown=rust:rust . . From 88a79d8b39d689b6a8f83f3d299c8c2b2ce25947 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:38 -0500 Subject: [PATCH 24/28] Revert "more" This reverts commit 216a5254afba8bba3d1fdb0a3fb17da147825e37. --- Dockerfile.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.build b/Dockerfile.build index c00d75a..70f47c9 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,7 +1,7 @@ FROM clux/muslrust:stable # Install PostgreSQL development libraries (needed for diesel with postgres feature) -RUN apt-get update && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/* +RUN sudo apt-get update && sudo apt-get install -y libpq-dev && sudo rm -rf /var/lib/apt/lists/* # Copy source code COPY --chown=rust:rust . . From d615552dde86dd9c2b57c8ce61f19547c1f809b0 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:40 -0500 Subject: [PATCH 25/28] Revert "more fixes" This reverts commit f4685707171725544639425c178bae0af8301422. --- Dockerfile.build | 3 --- falconeri_common/src/models/output_file.rs | 21 +++------------------ 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/Dockerfile.build b/Dockerfile.build index 70f47c9..30a99b3 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,8 +1,5 @@ FROM clux/muslrust:stable -# Install PostgreSQL development libraries (needed for diesel with postgres feature) -RUN sudo apt-get update && sudo apt-get install -y libpq-dev && sudo rm -rf /var/lib/apt/lists/* - # Copy source code COPY --chown=rust:rust . . diff --git a/falconeri_common/src/models/output_file.rs b/falconeri_common/src/models/output_file.rs index 72f28c9..7f05dd5 100644 --- a/falconeri_common/src/models/output_file.rs +++ b/falconeri_common/src/models/output_file.rs @@ -123,25 +123,10 @@ impl NewOutputFile { output_files: &[Self], conn: &mut PgConnection, ) -> Result> { - let input_count = output_files.len(); - let inserted_files = diesel::insert_into(output_files::table) + let output_files = diesel::insert_into(output_files::table) .values(output_files) - .on_conflict((output_files::job_id, output_files::uri)) - .do_nothing() .get_results::(conn) - .context("error inserting output files")?; - - let inserted_count = inserted_files.len(); - if inserted_count < input_count { - let conflict_count = input_count - inserted_count; - tracing::warn!( - conflict_count, - input_count, - inserted_count, - "detected duplicate output files, skipped inserting due to conflicts" - ); - } - - Ok(inserted_files) + .context("error inserting datums")?; + Ok(output_files) } } From a43764c3a12b1ba03af1b04d1707a3a6c9e8fe4f Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:43 -0500 Subject: [PATCH 26/28] Revert "more" This reverts commit e7bf5dc4a6b91dea8549ec5f3dc6062e92d99e29. --- .github/workflows/ci.yml | 8 -------- Dockerfile.build | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01e5f80..1250721 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,14 +71,6 @@ jobs: - name: Run clippy run: cargo clippy --verbose -- -D warnings - deny: - name: Deny - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: EmbarkStudios/cargo-deny-action@v2 - build: name: Build ${{ matrix.target }} runs-on: ${{ matrix.os }} diff --git a/Dockerfile.build b/Dockerfile.build index 30a99b3..88d08ca 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -8,5 +8,6 @@ ENV CARGO_ARGS= # Build all binaries. CMD if [ -d target ]; then chown -R rust:rust /volume/.cargo/git /volume/.cargo/registry /volume/target; fi && \ + cargo deny check && \ cargo build --all ${CARGO_ARGS} --target x86_64-unknown-linux-musl && \ cd guide && mdbook build From 794c90e1c5f3cd96877a6e5002740a34cd667936 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:45 -0500 Subject: [PATCH 27/28] Revert "buikld" This reverts commit 1fa22560effb32a0ef21cbff3332d75af3d40b34. --- .github/workflows/ci.yml | 29 +++++++++-------------------- Dockerfile.build | 12 +++++++----- justfile | 14 +++++++------- 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1250721..343e21b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,42 +79,31 @@ jobs: include: - os: ubuntu-latest target: x86_64-unknown-linux-musl - use_container: true - os: macos-latest target: x86_64-apple-darwin - use_container: false - os: macos-latest target: aarch64-apple-darwin - use_container: false - os: windows-latest target: x86_64-pc-windows-msvc - use_container: false steps: - uses: actions/checkout@v4 - - name: Build (Linux musl with Docker) - if: matrix.use_container - run: | - docker build -f Dockerfile.build -t build-falconeri . - docker run --name build-falconeri-container -e CARGO_ARGS=--release build-falconeri - mkdir -p bin/release - docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri bin/release/ - docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconerid bin/release/ - docker cp build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/release/falconeri-worker bin/release/ - - - name: Install Rust (non-Linux) - if: ${{ !matrix.use_container }} + - name: Install Rust uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - - name: Cache dependencies (non-Linux) - if: ${{ !matrix.use_container }} + - name: Install dependencies (Linux) + if: matrix.target == 'x86_64-unknown-linux-musl' + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + + - name: Cache dependencies uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.target }} - - name: Build (non-Linux) - if: ${{ !matrix.use_container }} + - name: Build run: cargo build --release --target ${{ matrix.target }} diff --git a/Dockerfile.build b/Dockerfile.build index 88d08ca..aff093e 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,13 +1,15 @@ -FROM clux/muslrust:stable +FROM ekidd/rust-musl-builder:stable -# Copy source code -COPY --chown=rust:rust . . +# We need to add the source code to the image because `rust-musl-builder` +# assumes a UID of 1000, but TravisCI has switched to 2000. +ADD . ./ +RUN sudo chown -R rust:rust . # Extra arguments to pass to cargo. ENV CARGO_ARGS= # Build all binaries. -CMD if [ -d target ]; then chown -R rust:rust /volume/.cargo/git /volume/.cargo/registry /volume/target; fi && \ +CMD if [ -d target ]; then sudo chown -R rust:rust /home/rust/.cargo/git /home/rust/.cargo/registry /home/rust/src/target; fi && \ cargo deny check && \ - cargo build --all ${CARGO_ARGS} --target x86_64-unknown-linux-musl && \ + cargo build --all ${CARGO_ARGS} && \ cd guide && mdbook build diff --git a/justfile b/justfile index 0e01a47..cf92a8c 100644 --- a/justfile +++ b/justfile @@ -47,9 +47,9 @@ _build_falconeri_container: _build_falconeri_image docker rm build-falconeri-container || true if [ "{{MODE}}" == debug ]; then docker run \ - -v falconeri-cargo-git:/volume/.cargo/git \ - -v falconeri-cargo-git:/volume/.cargo/registry \ - -v falconeri-target:/volume/target \ + -v falconeri-cargo-git:/home/rust/.cargo/git \ + -v falconeri-cargo-git:/home/rust/.cargo/registry \ + -v falconeri-target:/home/rust/src/target \ --name build-falconeri-container \ build-falconeri else @@ -62,14 +62,14 @@ _build_falconeri_container: _build_falconeri_image # Create a `bin/{{MODE}}/` directory with our various binaries. static-bin: _build_falconeri_container mkdir -p 'bin/{{MODE}}' - docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' - docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' - docker cp 'build-falconeri-container:/volume/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' + docker cp 'build-falconeri-container:/home/rust/src/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri' 'bin/{{MODE}}/falconeri' + docker cp 'build-falconeri-container:/home/rust/src/target/x86_64-unknown-linux-musl/{{MODE}}/falconerid' 'bin/{{MODE}}/falconerid' + docker cp 'build-falconeri-container:/home/rust/src/target/x86_64-unknown-linux-musl/{{MODE}}/falconeri-worker' 'bin/{{MODE}}/falconeri-worker' # Create a `gh-pages` directory with our "GitHub pages" documentation. gh-pages: _build_falconeri_container rm -rf gh-pages - docker cp build-falconeri-container:/volume/guide/book gh-pages + docker cp build-falconeri-container:/home/rust/src/guide/book gh-pages # Our `falconeri` Docker image. image: static-bin From a251b9c321e35cd9a62b4c125bf9fb2023b26b97 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Sun, 4 Jan 2026 18:32:47 -0500 Subject: [PATCH 28/28] Revert "modernize ci" This reverts commit b93f9fb092479a7e89815ad74502f6b5dd0082b2. --- .github/workflows/ci.yml | 174 +++++++++++++++++----------------- .github/workflows/release.yml | 142 --------------------------- 2 files changed, 88 insertions(+), 228 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 343e21b..5c0c75b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,109 +1,111 @@ name: CI +# Controls when the action will run. Triggers the workflow on push or pull +# request events but only for the main branch. on: push: + # Run on the main branch. branches: - main + - ci + tags: + - "v*" pull_request: - -permissions: - contents: read + # Only run on pull requests against main. + branches: [main] jobs: - test: - name: Test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - - - name: Cache dependencies - uses: Swatinem/rust-cache@v2 - - - name: Run tests - run: cargo test --verbose - - check: - name: Check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - - - name: Cache dependencies - uses: Swatinem/rust-cache@v2 - - - name: Run cargo check - run: cargo check --verbose - - fmt: - name: Format + # We run this job first, to create any GitHub release that we might need. + # Creating a release can only be done once, so we need to split it out from + # other jobs. + create_release: + name: Create release (if needed) runs-on: ubuntu-latest + outputs: + release_version: ${{ steps.extract_release_version.outputs.release_version }} + upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - components: rustfmt - - - name: Check formatting - run: cargo fmt --all -- --check - - clippy: - name: Clippy - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Extract release version + id: extract_release_version + run: | + release_version="$(echo '${{ github.ref }}' | sed 's,^.*/\([^/]*\)$,\1,; s,^v,,' )" + echo Release version: $release_version + echo "::set-output name=release_version::$release_version" + - name: Extract release body from CHANGELOG.md + id: extract_release_body + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + # Use `clparse` to parse `CHANGELOG.md` and extract release notes. + run: | + curl -sLO https://github.com/marcaddeo/clparse/releases/download/0.8.0/clparse-0.8.0-x86_64-unknown-linux-musl.tar.gz + tar xzf clparse*.tar.gz + sudo cp clparse /usr/local/bin + rm -rf clparse* + clparse -f json CHANGELOG.md | \ + jq ".releases[] | select(.version == \"${{ steps.extract_release_version.outputs.release_version }}\") | { title: \"\", description: \"\", releases: [.] }" | \ + clparse - | \ + tail -n +3 > RELEASE_BODY.md + - name: "Make release" + id: create_release + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - components: clippy + tag_name: ${{ github.ref }} + release_name: "${{ steps.extract_release_version.outputs.release_version }}" + body_path: RELEASE_BODY.md - - name: Cache dependencies - uses: Swatinem/rust-cache@v2 + # We use a matrix to run our build on every supported platform. + release: + name: "Build" - - name: Run clippy - run: cargo clippy --verbose -- -D warnings + needs: + - create_release - build: - name: Build ${{ matrix.target }} - runs-on: ${{ matrix.os }} strategy: matrix: + # target: Official name of system to compile for. + # os: GitHub CI OS image to use on runner. include: - - os: ubuntu-latest - target: x86_64-unknown-linux-musl - - os: macos-latest - target: x86_64-apple-darwin - - os: macos-latest - target: aarch64-apple-darwin - - os: windows-latest - target: x86_64-pc-windows-msvc + - target: x86_64-unknown-linux-musl + os: ubuntu-latest - steps: - - uses: actions/checkout@v4 + runs-on: ${{ matrix.os }} - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + steps: + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 with: - targets: ${{ matrix.target }} - - - name: Install dependencies (Linux) - if: matrix.target == 'x86_64-unknown-linux-musl' + profile: minimal + # We track latest stable Rust instead of hardcoding it because it + # virtually never breaks old code. + toolchain: stable + components: rustfmt, clippy + target: ${{ matrix.target }} + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Check source formatting and warnings run: | - sudo apt-get update - sudo apt-get install -y musl-tools - - - name: Cache dependencies - uses: Swatinem/rust-cache@v2 + cargo fmt -- --check + cargo clippy -- -D warnings + - name: Test + run: | + cargo test + - name: Build release + id: build_release + run: | + ./build-release falconeri ${{ needs.create_release.outputs.release_version }}_${{ matrix.target }} + release_file=falconeri_${{ needs.create_release.outputs.release_version }}_${{ matrix.target }}.zip + echo "::set-output name=release_file::$release_file" + - name: Upload Release Asset + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - key: ${{ matrix.target }} - - - name: Build - run: cargo build --release --target ${{ matrix.target }} + upload_url: ${{ needs.create_release.outputs.upload_url }} + asset_path: ./${{ steps.build_release.outputs.release_file }} + asset_name: ${{ steps.build_release.outputs.release_file }} + asset_content_type: application/zip \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 065b330..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,142 +0,0 @@ -name: Release - -on: - push: - tags: - - "v*" - -permissions: - contents: write - -jobs: - validate: - name: Validate version - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Extract version from tag - id: tag_version - run: | - TAG="${GITHUB_REF#refs/tags/v}" - echo "version=$TAG" >> $GITHUB_OUTPUT - echo "Tag version: $TAG" - - - name: Extract version from Cargo.toml - id: cargo_version - run: | - CARGO_VERSION=$(grep '^version = ' falconeri/Cargo.toml | head -1 | cut -d'"' -f2) - echo "version=$CARGO_VERSION" >> $GITHUB_OUTPUT - echo "Cargo.toml version: $CARGO_VERSION" - - - name: Validate versions match - run: | - if [ "${{ steps.tag_version.outputs.version }}" != "${{ steps.cargo_version.outputs.version }}" ]; then - echo "Error: Tag version (${{ steps.tag_version.outputs.version }}) does not match Cargo.toml version (${{ steps.cargo_version.outputs.version }})" - exit 1 - fi - echo "Version validation passed: ${{ steps.tag_version.outputs.version }}" - - test: - name: Run tests before release - needs: validate - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - - - name: Run tests - run: cargo test --verbose - - - name: Run clippy - run: | - rustup component add clippy - cargo clippy --verbose -- -D warnings - - build: - name: Build ${{ matrix.target }} - needs: test - runs-on: ${{ matrix.os }} - strategy: - matrix: - include: - - os: ubuntu-latest - target: x86_64-unknown-linux-musl - archive_name: falconeri-${{ github.ref_name }}-linux-x86_64.zip - - os: macos-latest - target: x86_64-apple-darwin - archive_name: falconeri-${{ github.ref_name }}-macos-x86_64.zip - - os: macos-latest - target: aarch64-apple-darwin - archive_name: falconeri-${{ github.ref_name }}-macos-aarch64.zip - - os: windows-latest - target: x86_64-pc-windows-msvc - archive_name: falconeri-${{ github.ref_name }}-windows-x86_64.zip - - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - targets: ${{ matrix.target }} - - - name: Install dependencies (Linux) - if: matrix.target == 'x86_64-unknown-linux-musl' - run: | - sudo apt-get update - sudo apt-get install -y musl-tools - - - name: Build - run: cargo build --release --target ${{ matrix.target }} - - - name: Create archive (Unix) - if: runner.os != 'Windows' - run: | - cd target/${{ matrix.target }}/release - zip ../../../${{ matrix.archive_name }} falconeri falconerid falconeri-worker - - - name: Create archive (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - cd target/${{ matrix.target }}/release - Compress-Archive -Path falconeri.exe,falconerid.exe,falconeri-worker.exe -DestinationPath ../../../${{ matrix.archive_name }} - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.target }} - path: ${{ matrix.archive_name }} - - release: - name: Create GitHub Release - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Download all artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Prepare release files - run: | - mkdir release-files - find artifacts -name "*.zip" -exec cp {} release-files/ \; - ls -lh release-files/ - - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - files: release-files/* - draft: false - prerelease: false - generate_release_notes: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - -