diff --git a/Cargo.lock b/Cargo.lock index 5f858ad..5fc84d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,21 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.12" @@ -95,9 +110,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "async-channel" @@ -142,7 +157,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -159,7 +174,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -201,9 +216,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aws-config" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7af266887e24cd5f6d2ea7433cacd25dcd4773b7f70e488701968a7cdf51df57" +checksum = "3182c19847238b50b62ae0383a6dbfc14514e552eb5e307e1ea83ccf5840b8a6" dependencies = [ "aws-credential-types", "aws-runtime", @@ -231,9 +246,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d56f287a9e65e4914bfedb5b22c056b65e4c232fca512d5509a9df36386759f" +checksum = "e5635d8707f265c773282a22abe1ecd4fbe96a8eb2f0f14c0796f8016f11a41a" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -243,9 +258,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6a29eca8ea8982028a4df81883e7001e250a21d323b86418884b5345950a4b" +checksum = "6f82b9ae2adfd9d6582440d0eeb394c07f74d21b4c0cc72bdb73735c9e1a9c0e" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -267,9 +282,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c977e92277652aefb9a76a0fca652b26757d6845dce0d7bf4426da80f13d85b0" +checksum = "5076637347e7d0218e61facae853110682ae58efabd2f4e2a9e530c203d5fa7b" dependencies = [ "aws-credential-types", "aws-runtime", @@ -296,9 +311,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d7f527c7b28af1a641f7d89f9e6a4863e8ec00f39d2b731b056fc5ec5ce829" +checksum = "ca7e8097448832fcd22faf6bb227e97d76b40e354509d1307653a885811c7151" dependencies = [ "aws-credential-types", "aws-runtime", @@ -318,9 +333,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0be3224cd574ee8ab5fd7c32087876f25c134c27ac603fcb38669ed8d346b0" +checksum = "a75073590e23d63044606771afae309fada8eb10ded54a1ce4598347221d3fef" dependencies = [ "aws-credential-types", "aws-runtime", @@ -340,9 +355,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3167c60d82a13bbaef569da06041644ff41e85c6377e5dad53fa2526ccfe9d" +checksum = "650e4aaae41547151dea4d8142f7ffcc8ab8ba76d5dccc8933936ef2102c3356" dependencies = [ "aws-credential-types", "aws-runtime", @@ -363,9 +378,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b1cbe0eee57a213039088dbdeca7be9352f24e0d72332d961e8a1cb388f82d" +checksum = "404c64a104188ac70dd1684718765cb5559795458e446480e41984e68e57d888" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -549,9 +564,9 @@ dependencies = [ [[package]] name = "aws-types" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ff7e122ee50ca962e9de91f5850cc37e2184b1219611eef6d44aa85929b54f6" +checksum = "8fbb5d48aae496f628e7aa2e41991dd4074f606d9e3ade1ce1059f293d40f9a2" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -603,7 +618,7 @@ dependencies = [ "http 1.0.0", "http-body 1.0.0", "http-body-util", - "hyper 1.1.0", + "hyper 1.2.0", "hyper-util", "itoa", "matchit", @@ -762,9 +777,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.0" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" +checksum = "a3b1be7772ee4501dba05acbe66bb1e8760f6a6c474a36035631638e4415f130" [[package]] name = "byteorder" @@ -790,12 +805,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" [[package]] name = "cfg-if" @@ -803,6 +815,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.2", +] + [[package]] name = "clap" version = "4.5.1" @@ -834,7 +860,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -1002,7 +1028,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -1288,6 +1314,7 @@ dependencies = [ "aws-config", "aws-sdk-s3", "axum 0.7.4", + "chrono", "clap", "dotenv", "lazy_static", @@ -1664,9 +1691,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes", "futures-channel", @@ -1678,6 +1705,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "smallvec", "tokio", ] @@ -1732,12 +1760,35 @@ dependencies = [ "futures-util", "http 1.0.0", "http-body 1.0.0", - "hyper 1.1.0", + "hyper 1.2.0", "pin-project-lite", "socket2", "tokio", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.5.0" @@ -2127,9 +2178,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.63" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.4.2", "cfg-if", @@ -2148,7 +2199,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -2159,9 +2210,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.99" +version = "0.9.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" dependencies = [ "cc", "libc", @@ -2269,7 +2320,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -2357,7 +2408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -2396,7 +2447,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.49", + "syn 2.0.50", "tempfile", "which", ] @@ -2411,7 +2462,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -2696,9 +2747,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -2773,35 +2824,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -2835,7 +2886,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -3016,6 +3067,7 @@ dependencies = [ "atoi", "byteorder", "bytes", + "chrono", "crc", "crossbeam-queue", "dotenvy", @@ -3044,6 +3096,7 @@ dependencies = [ "tokio-stream", "tracing", "url", + "uuid", ] [[package]] @@ -3097,6 +3150,7 @@ dependencies = [ "bitflags 2.4.2", "byteorder", "bytes", + "chrono", "crc", "digest", "dotenvy", @@ -3125,6 +3179,7 @@ dependencies = [ "stringprep", "thiserror", "tracing", + "uuid", "whoami", ] @@ -3138,6 +3193,7 @@ dependencies = [ "base64 0.21.7", "bitflags 2.4.2", "byteorder", + "chrono", "crc", "dotenvy", "etcetera", @@ -3164,6 +3220,7 @@ dependencies = [ "stringprep", "thiserror", "tracing", + "uuid", "whoami", ] @@ -3174,6 +3231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" dependencies = [ "atoi", + "chrono", "flume", "futures-channel", "futures-core", @@ -3188,6 +3246,7 @@ dependencies = [ "tracing", "url", "urlencoding", + "uuid", ] [[package]] @@ -3226,9 +3285,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.49" +version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", @@ -3302,14 +3361,14 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -3398,7 +3457,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -3484,7 +3543,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -3539,7 +3598,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -3603,9 +3662,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -3737,7 +3796,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", "wasm-bindgen-shared", ] @@ -3771,7 +3830,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3841,6 +3900,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3856,7 +3924,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.2", ] [[package]] @@ -3876,17 +3944,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "d98532992affa02e52709d5b4d145a3668ae10d9081eea4a7f26f719a8476f71" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.1", + "windows_aarch64_msvc 0.52.1", + "windows_i686_gnu 0.52.1", + "windows_i686_msvc 0.52.1", + "windows_x86_64_gnu 0.52.1", + "windows_x86_64_gnullvm 0.52.1", + "windows_x86_64_msvc 0.52.1", ] [[package]] @@ -3897,9 +3965,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "e7269c1442e75af9fa59290383f7665b828efc76c429cc0b7f2ecb33cf51ebae" [[package]] name = "windows_aarch64_msvc" @@ -3909,9 +3977,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "f70ab2cebf332b7ecbdd98900c2da5298a8c862472fb35c75fc297eabb9d89b8" [[package]] name = "windows_i686_gnu" @@ -3921,9 +3989,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "679f235acf6b1639408c0f6db295697a19d103b0cdc88146aa1b992c580c647d" [[package]] name = "windows_i686_msvc" @@ -3933,9 +4001,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "3480ac194b55ae274a7e135c21645656825da4a7f5b6e9286291b2113c94a78b" [[package]] name = "windows_x86_64_gnu" @@ -3945,9 +4013,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "42c46bab241c121402d1cb47d028ea3680ee2f359dcc287482dcf7fdddc73363" [[package]] name = "windows_x86_64_gnullvm" @@ -3957,9 +4025,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "dc885a4332ee1afb9a1bacf11514801011725570d35675abc229ce7e3afe4d20" [[package]] name = "windows_x86_64_msvc" @@ -3969,9 +4037,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "9e440c60457f84b0bee09208e62acc7ade264b38c4453f6312b8c9ab1613e73c" [[package]] name = "winreg" @@ -4017,7 +4085,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] diff --git a/crates/flux-releaser/Cargo.toml b/crates/flux-releaser/Cargo.toml index ca69d29..ec8d669 100644 --- a/crates/flux-releaser/Cargo.toml +++ b/crates/flux-releaser/Cargo.toml @@ -24,7 +24,8 @@ walkdir = "2.4.0" tar = "0.4.40" tokio-stream = { version = "0.1.14", features = ["full"] } rand = "0.8.5" -sqlx = { version = "0.7.3", features = ["postgres", "runtime-tokio"] } +sqlx = { version = "0.7.3", features = ["postgres", "runtime-tokio", "uuid", "chrono"] } +chrono = "0.4.34" [build-dependencies] tonic-build = "0.11.0" diff --git a/crates/flux-releaser/migrations/crdb/20240221054936_init.sql b/crates/flux-releaser/migrations/crdb/20240221054936_init.sql index 8ddc1d3..51dd579 100644 --- a/crates/flux-releaser/migrations/crdb/20240221054936_init.sql +++ b/crates/flux-releaser/migrations/crdb/20240221054936_init.sql @@ -1 +1,8 @@ -- Add migration script here +CREATE TABLE IF NOT EXISTS artifacts ( + app VARCHAR NOT NULL, + branch VARCHAR NOT NULL, + artifact_id UUID NOT NULL PRIMARY KEY, + created_at TIMESTAMP DEFAULT NOW(), + UNIQUE (app, artifact_id) +); diff --git a/crates/flux-releaser/schemas/proto/flux_releaser.proto b/crates/flux-releaser/schemas/proto/flux_releaser.proto index 4fde587..797de61 100644 --- a/crates/flux-releaser/schemas/proto/flux_releaser.proto +++ b/crates/flux-releaser/schemas/proto/flux_releaser.proto @@ -5,6 +5,7 @@ package flux_releaser; service FluxReleaser { rpc UploadArtifact (stream UploadArtifactRequest) returns (UploadArtifactResponse) {} rpc CommitArtifact (CommitArtifactRequest) returns (CommitArtifactResponse) {} + rpc TriggerRelease (TriggerReleaseRequest) returns (TriggerReleaseResponse) {} } message UploadArtifactRequest { @@ -24,3 +25,11 @@ message CommitArtifactRequest { message CommitArtifactResponse { string artifact_id = 1; } + +message TriggerReleaseRequest { + string app = 1; + string branch = 2; + string cluster = 3; +} + +message TriggerReleaseResponse {} diff --git a/crates/flux-releaser/src/cli.rs b/crates/flux-releaser/src/cli.rs index e923ef6..3d4d1db 100644 --- a/crates/flux-releaser/src/cli.rs +++ b/crates/flux-releaser/src/cli.rs @@ -32,6 +32,20 @@ pub enum Commands { #[arg(env = "FLUX_RELEASER_REGISTRY", long)] registry: String, }, + + Release { + #[arg(long)] + app: String, + + #[arg(long)] + branch: String, + + #[arg(long)] + cluster: String, + + #[arg(env = "FLUX_RELEASER_REGISTRY", long)] + registry: String, + }, } impl Command { @@ -55,7 +69,19 @@ impl Command { .package_clusters(include) .await?; } - _ => (), + Some(Commands::Release { + app: service_app, + branch, + cluster, + registry, + }) => { + let app = client::get_local_app(registry).await?; + + app.flux_local_cluster_manager() + .trigger_release(service_app, branch, cluster) + .await?; + } + None => (), } Ok(()) diff --git a/crates/flux-releaser/src/grpc.rs b/crates/flux-releaser/src/grpc.rs index 70e3629..6eaad11 100644 --- a/crates/flux-releaser/src/grpc.rs +++ b/crates/flux-releaser/src/grpc.rs @@ -8,13 +8,15 @@ use uuid::Uuid; use crate::{ app::SharedApp, services::release_manager::{ - extensions::ReleaseManagerExt, models::CommitArtifact, ReleaseManager, + extensions::ReleaseManagerExt, + models::{CommitArtifact, Release}, + ReleaseManager, }, }; use self::gen::{ - flux_releaser_server, CommitArtifactRequest, CommitArtifactResponse, UploadArtifactRequest, - UploadArtifactResponse, + flux_releaser_server, CommitArtifactRequest, CommitArtifactResponse, TriggerReleaseRequest, + TriggerReleaseResponse, UploadArtifactRequest, UploadArtifactResponse, }; pub mod gen { @@ -80,12 +82,29 @@ impl flux_releaser_server::FluxReleaser for FluxReleaserGrpc { .map_err(|e: anyhow::Error| tonic::Status::invalid_argument(e.to_string()))?, ) .await - .unwrap(); + .map_err(|e: anyhow::Error| tonic::Status::internal(e.to_string()))?; Ok(tonic::Response::new(CommitArtifactResponse { artifact_id: artifact.to_string(), })) } + + async fn trigger_release( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + + self.release_manager + .release( + req.try_into() + .map_err(|e: anyhow::Error| tonic::Status::invalid_argument(e.to_string()))?, + ) + .await + .map_err(|e| tonic::Status::internal(e.to_string()))?; + + Ok(tonic::Response::new(TriggerReleaseResponse {})) + } } impl TryFrom for CommitArtifact { @@ -110,6 +129,30 @@ impl TryFrom for CommitArtifact { } } +impl TryFrom for Release { + type Error = anyhow::Error; + + fn try_from(value: TriggerReleaseRequest) -> Result { + if value.app.is_empty() { + anyhow::bail!("app cannot be empty"); + } + + if value.branch.is_empty() { + anyhow::bail!("branch canot be empty"); + } + + if value.cluster.is_empty() { + anyhow::bail!("cluster canot be empty"); + } + + Ok(Self { + app: value.app, + branch: value.branch, + cluster: value.cluster, + }) + } +} + pub async fn tonic_serve(host: SocketAddr, app: SharedApp) -> anyhow::Result<()> { tracing::info!("grpc listening on: {}", host); Server::builder() diff --git a/crates/flux-releaser/src/services.rs b/crates/flux-releaser/src/services.rs index 4ebf58d..2a2e08a 100644 --- a/crates/flux-releaser/src/services.rs +++ b/crates/flux-releaser/src/services.rs @@ -5,3 +5,5 @@ pub mod file_store; pub mod flux_local_cluster; pub mod flux_releaser_uploader; pub mod release_manager; + +pub mod artifacts_db; diff --git a/crates/flux-releaser/src/services/artifacts_db.rs b/crates/flux-releaser/src/services/artifacts_db.rs new file mode 100644 index 0000000..dcf585a --- /dev/null +++ b/crates/flux-releaser/src/services/artifacts_db.rs @@ -0,0 +1,132 @@ +use std::sync::Arc; + +use sqlx::{prelude::FromRow, PgPool}; + +use self::defaults::DefaultArtifactsDB; + +#[derive(Clone, Debug)] +pub struct AddCommitArtifact { + pub app: String, + pub branch: String, + pub artifact_id: uuid::Uuid, +} + +#[derive(Clone, Debug, FromRow)] +pub struct Artifact { + pub app: String, + pub branch: String, + pub artifact_id: uuid::Uuid, + pub created_at: chrono::NaiveDateTime, +} + +#[derive(Clone, Debug)] +pub struct GetLatestArtifact { + pub app: String, + pub branch: String, +} + +pub mod traits { + use axum::async_trait; + + use super::{AddCommitArtifact, Artifact, GetLatestArtifact}; + + #[async_trait] + pub trait ArtifactsDB { + async fn commit_artifact(&self, commit_artifact: AddCommitArtifact) -> anyhow::Result<()>; + async fn get_latest_artifact( + &self, + get_latest_artifact: GetLatestArtifact, + ) -> anyhow::Result; + } +} + +pub mod defaults { + use axum::async_trait; + use sqlx::PgPool; + + use super::{traits, AddCommitArtifact, Artifact, GetLatestArtifact}; + + pub struct DefaultArtifactsDB { + db: PgPool, + } + + impl DefaultArtifactsDB { + pub fn new(db: PgPool) -> Self { + Self { db } + } + } + + #[async_trait] + impl traits::ArtifactsDB for DefaultArtifactsDB { + async fn commit_artifact(&self, commit_artifact: AddCommitArtifact) -> anyhow::Result<()> { + sqlx::query("INSERT INTO artifacts (app, branch, artifact_id) VALUES ($1, $2, $3)") + .bind(commit_artifact.app) + .bind(commit_artifact.branch) + .bind(commit_artifact.artifact_id) + .execute(&self.db) + .await?; + + Ok(()) + } + + async fn get_latest_artifact( + &self, + get_latest_artifact: GetLatestArtifact, + ) -> anyhow::Result { + let artifact = sqlx::query_as::<_, Artifact>( + "SELECT + * + FROM + artifacts + WHERE + app = $1 AND + branch = $2 + ORDER BY created_at DESC + LIMIT 1", + ) + .bind(get_latest_artifact.app) + .bind(get_latest_artifact.branch) + .fetch_one(&self.db) + .await?; + + Ok(artifact) + } + } +} + +#[derive(Clone)] +pub struct ArtifactsDB { + inner: Arc, +} + +impl ArtifactsDB { + pub fn new(db: PgPool) -> Self { + Self { + inner: Arc::new(DefaultArtifactsDB::new(db)), + } + } +} + +impl std::ops::Deref for ArtifactsDB { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +pub mod extensions { + use crate::app::App; + + use super::ArtifactsDB; + + pub trait ArtifactsDBExt { + fn artifacts_db(&self) -> ArtifactsDB; + } + + impl ArtifactsDBExt for App { + fn artifacts_db(&self) -> ArtifactsDB { + ArtifactsDB::new(self.database.clone()) + } + } +} diff --git a/crates/flux-releaser/src/services/flux_local_cluster.rs b/crates/flux-releaser/src/services/flux_local_cluster.rs index f9fab03..8f12c8b 100644 --- a/crates/flux-releaser/src/services/flux_local_cluster.rs +++ b/crates/flux-releaser/src/services/flux_local_cluster.rs @@ -1,6 +1,11 @@ use std::path::PathBuf; -use crate::{app::infra::grpc::FluxReleaserGrpcClient, grpc::gen::CommitArtifactRequest}; +use anyhow::Context; + +use crate::{ + app::infra::grpc::FluxReleaserGrpcClient, + grpc::gen::{CommitArtifactRequest, TriggerReleaseRequest}, +}; use super::{ archive::Archive, @@ -61,6 +66,36 @@ impl FluxLocalClusterManager { artifact_id.into_inner().artifact_id.try_into() } + + pub async fn trigger_release( + &self, + app: impl Into, + branch: impl Into, + cluster: impl Into, + ) -> anyhow::Result<()> { + self.flux_releaser_client + .lock() + .await + .trigger_release(tonic::Request::new(TriggerReleaseRequest { + app: app.into(), + branch: branch.into(), + cluster: cluster.into(), + })) + .await + .context("failed to trigger release")?; + + // Send release proto to upstream + + // 1. find app by app + branch + + // 2. Unpack latest artifact by app + branch + + // 3. Unpack by cluster + + // 4. Upload + + Ok(()) + } } pub mod extensions { diff --git a/crates/flux-releaser/src/services/release_manager.rs b/crates/flux-releaser/src/services/release_manager.rs index c55bc96..48251cc 100644 --- a/crates/flux-releaser/src/services/release_manager.rs +++ b/crates/flux-releaser/src/services/release_manager.rs @@ -1,19 +1,21 @@ use serde::Serialize; -use crate::services::archive::extensions::ArchiveUploadExt; +use crate::services::artifacts_db::{AddCommitArtifact, GetLatestArtifact}; use crate::services::file_store::FileStore; use super::archive::Archive; +use super::artifacts_db::ArtifactsDB; use super::domain_events::DomainEvents; use super::file_reader::FileReader; -use self::models::{ArtifactID, CommitArtifact, UploadArtifact, UploadArtifactID}; +use self::models::*; pub struct ReleaseManager { archive: Archive, file_reader: FileReader, file_store: FileStore, domain_events: DomainEvents, + artifacts_db: ArtifactsDB, } impl ReleaseManager { @@ -22,12 +24,14 @@ impl ReleaseManager { file_store: FileStore, archive: Archive, domain_events: DomainEvents, + artifacts_db: ArtifactsDB, ) -> Self { Self { archive, file_reader, file_store, domain_events, + artifacts_db, } } @@ -60,8 +64,37 @@ impl ReleaseManager { })?) .await?; + self.artifacts_db + .commit_artifact(AddCommitArtifact { + app: request.app, + branch: request.branch, + artifact_id: artifact_id.clone().into(), + }) + .await?; + Ok(artifact_id) } + + pub async fn release(&self, release_req: Release) -> anyhow::Result<()> { + tracing::debug!( + app = release_req.app, + branch = release_req.branch, + cluster = release_req.cluster, + "releasing latest commit" + ); + + let artifact = self + .artifacts_db + .get_latest_artifact(GetLatestArtifact { + app: release_req.app, + branch: release_req.branch, + }) + .await?; + + tracing::trace!("found latest artifact: {:?}", artifact); + + Ok(()) + } } #[derive(Serialize)] diff --git a/crates/flux-releaser/src/services/release_manager/extensions.rs b/crates/flux-releaser/src/services/release_manager/extensions.rs index 43ff52d..6e5f298 100644 --- a/crates/flux-releaser/src/services/release_manager/extensions.rs +++ b/crates/flux-releaser/src/services/release_manager/extensions.rs @@ -1,12 +1,15 @@ use crate::{ app::SharedApp, services::{ - archive::extensions::ArchiveExt, domain_events::extensions::DomainEventsExt, - file_reader::extensions::FileReaderExt, file_store::extensions::FileStoreExt, + archive::extensions::ArchiveExt, + artifacts_db::{extensions::ArtifactsDBExt, AddCommitArtifact}, + domain_events::extensions::DomainEventsExt, + file_reader::extensions::FileReaderExt, + file_store::extensions::FileStoreExt, }, }; -use super::ReleaseManager; +use super::{CommitArtifact, ReleaseManager}; pub trait ReleaseManagerExt { fn release_manager(&self) -> ReleaseManager; @@ -19,6 +22,7 @@ impl ReleaseManagerExt for SharedApp { self.file_store(), self.archive(), self.domain_events(), + self.artifacts_db(), ) } } diff --git a/crates/flux-releaser/src/services/release_manager/models.rs b/crates/flux-releaser/src/services/release_manager/models.rs index 4fba5c3..2b18475 100644 --- a/crates/flux-releaser/src/services/release_manager/models.rs +++ b/crates/flux-releaser/src/services/release_manager/models.rs @@ -7,6 +7,13 @@ pub struct CommitArtifact { pub upload_id: UploadArtifactID, } +#[derive(Clone, Debug)] +pub struct Release { + pub app: String, + pub branch: String, + pub cluster: String, +} + #[derive(Debug, Clone)] pub struct ArtifactID(uuid::Uuid); @@ -52,6 +59,12 @@ impl From for UploadArtifactID { } } +impl From for uuid::Uuid { + fn from(value: ArtifactID) -> Self { + value.0 + } +} + impl TryFrom for UploadArtifactID { type Error = anyhow::Error; diff --git a/crates/flux-releaser/tests/publish_artifacts.rs b/crates/flux-releaser/tests/publish_artifacts.rs index 293a772..24e8e31 100644 --- a/crates/flux-releaser/tests/publish_artifacts.rs +++ b/crates/flux-releaser/tests/publish_artifacts.rs @@ -15,7 +15,6 @@ use flux_releaser::{ }, }; use tokio::{net::TcpListener, runtime::Runtime, sync::Mutex, time::sleep}; -use uuid::Uuid; struct Server { endpoints: Endpoints, @@ -200,4 +199,41 @@ async fn can_publish_artifact() -> anyhow::Result<()> { Ok(()) } +#[tokio::test] +async fn can_trigger_latest_release() -> anyhow::Result<()> { + let test_id = uuid::Uuid::now_v7(); + + std::env::set_var("RUST_LOG", "flux_releaser=trace"); + + let (endpoints, app) = setup().await?; + let local_app = local_setup(endpoints.clone()).await?; + + let upload_id = local_app + .flux_local_cluster_manager() + .package_clusters("testdata/flux_local_cluster") + .await?; + + let archive = app.file_store().get_temp(upload_id.clone()).await?; + + assert!(archive.exists()); + + let _ = local_app + .flux_local_cluster_manager() + .commit_artifact(test_id, "some-branch", upload_id) + .await?; + + local_app + .flux_local_cluster_manager() + .trigger_release(test_id, "some-branch", "flux_local_cluster") + .await?; + + // 1. Verify that release event has been sent + // 2. Verify that we've splatted the flux cluster over the upstream registry + // 3. Verify database has a release record + + todo!(); + + Ok(()) +} + pub struct TestGreeter {}