From 089947d973efe375123e7d80e13317ae8a025168 Mon Sep 17 00:00:00 2001 From: Julio Date: Mon, 2 Mar 2026 17:56:33 +0100 Subject: [PATCH 01/26] ci: create workspace for actions Create actions workspace to share and build code for repo actions: * Move code from clippy-annotation-reporter to ci-shared crate. * Port code from changed-crates bash script to changed-crates binary inside ci-crates. * Create affected-crates binary to compute dependency graph and get affected crates by the PR. * Modify lint workflow to manage affected crates. --- .../Cargo.lock | 1256 ++++++++++------- .github/actions/Cargo.toml | 10 + .github/actions/affected-crates/action.yml | 51 + .github/actions/changed-crates/action.yml | 160 +-- .github/actions/ci-crates/Cargo.toml | 26 + .../ci-crates/src/bin/affected_crates.rs | 158 +++ .../ci-crates/src/bin/changed_crates.rs | 111 ++ .github/actions/ci-crates/src/git.rs | 53 + .github/actions/ci-crates/src/lib.rs | 5 + .github/actions/ci-crates/src/workspace.rs | 110 ++ .github/actions/ci-shared/Cargo.toml | 19 + .../src}/crate_detection.rs | 201 ++- .../actions/ci-shared/src/github_output.rs | 45 + .github/actions/ci-shared/src/lib.rs | 5 + .../clippy-annotation-reporter/Cargo.toml | 6 +- .../clippy-annotation-reporter/action.yml | 10 +- .../src/analyzer/annotation.rs | 2 +- .../src/analyzer/mod.rs | 1 - .github/workflows/fuzz.yml | 19 +- .github/workflows/lint.yml | 23 +- 20 files changed, 1558 insertions(+), 713 deletions(-) rename .github/actions/{clippy-annotation-reporter => }/Cargo.lock (69%) create mode 100644 .github/actions/Cargo.toml create mode 100644 .github/actions/affected-crates/action.yml create mode 100644 .github/actions/ci-crates/Cargo.toml create mode 100644 .github/actions/ci-crates/src/bin/affected_crates.rs create mode 100644 .github/actions/ci-crates/src/bin/changed_crates.rs create mode 100644 .github/actions/ci-crates/src/git.rs create mode 100644 .github/actions/ci-crates/src/lib.rs create mode 100644 .github/actions/ci-crates/src/workspace.rs create mode 100644 .github/actions/ci-shared/Cargo.toml rename .github/actions/{clippy-annotation-reporter/src/analyzer => ci-shared/src}/crate_detection.rs (67%) create mode 100644 .github/actions/ci-shared/src/github_output.rs create mode 100644 .github/actions/ci-shared/src/lib.rs diff --git a/.github/actions/clippy-annotation-reporter/Cargo.lock b/.github/actions/Cargo.lock similarity index 69% rename from .github/actions/clippy-annotation-reporter/Cargo.lock rename to .github/actions/Cargo.lock index b579e625a1..7e38c57229 100644 --- a/.github/actions/clippy-annotation-reporter/Cargo.lock +++ b/.github/actions/Cargo.lock @@ -2,36 +2,15 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +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" @@ -43,9 +22,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -58,50 +37,53 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arc-swap" -version = "1.7.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" +dependencies = [ + "rustversion", +] [[package]] name = "ascii-canvas" @@ -135,9 +117,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -147,14 +129,14 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", "fastrand 2.3.0", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "pin-project-lite", "slab", ] @@ -165,41 +147,40 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-executor", "async-io", "async-lock", "blocking", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "once_cell", ] [[package]] name = "async-io" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "parking", - "polling 3.8.0", + "polling 3.11.0", "rustix", "slab", - "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.0" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -215,28 +196,27 @@ dependencies = [ [[package]] name = "async-process" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-io", "async-lock", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener 5.4.0", - "futures-lite 2.6.0", + "event-listener 5.4.1", + "futures-lite 2.6.1", "rustix", - "tracing", ] [[package]] name = "async-signal" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ "async-io", "async-lock", @@ -247,14 +227,14 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "async-std" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" dependencies = [ "async-channel 1.9.0", "async-global-executor", @@ -265,7 +245,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "gloo-timers", "kv-log-macro", "log", @@ -285,9 +265,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -302,24 +282,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.75" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base64" @@ -367,34 +332,34 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "blocking" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-task", "futures-io", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "piper", ] [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "castaway" @@ -404,26 +369,26 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.2.25" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" 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 = "chrono" -version = "0.4.41" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", @@ -432,11 +397,36 @@ dependencies = [ "windows-link", ] +[[package]] +name = "ci-crates" +version = "0.1.0" +dependencies = [ + "anyhow", + "ci-shared", + "clap", + "env_logger 0.11.9", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "ci-shared" +version = "0.1.0" +dependencies = [ + "anyhow", + "log", + "serde", + "serde_json", + "tempfile", + "toml", +] + [[package]] name = "clap" -version = "4.5.39" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", @@ -444,9 +434,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream", "anstyle", @@ -456,9 +446,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", @@ -468,18 +458,19 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "clippy-annotation-reporter" version = "0.1.0" dependencies = [ "anyhow", + "ci-shared", "clap", - "env_logger", - "http 1.3.1", + "env_logger 0.10.2", + "http 1.4.0", "httpmock", "log", "mockall", @@ -488,15 +479,14 @@ dependencies = [ "serde_json", "tempfile", "tokio", - "toml", "url", ] [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "concurrent-queue" @@ -531,30 +521,30 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "curl" -version = "0.4.47" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265" +checksum = "79fc3b6dd0b87ba36e565715bf9a2ced221311db47bd18011676f24a6066edbc" dependencies = [ "curl-sys", "libc", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", - "socket2", - "windows-sys 0.52.0", + "socket2 0.6.2", + "windows-sys 0.59.0", ] [[package]] name = "curl-sys" -version = "0.4.80+curl-8.12.1" +version = "0.4.85+curl-8.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f7df2eac63200c3ab25bde3b2268ef2ee56af3d238e76d61f01c3c49bff734" +checksum = "c0efa6142b5ecc05f6d3eaa39e6af4888b9d3939273fb592c92b7088a8cf3fdb" dependencies = [ "cc", "libc", @@ -563,14 +553,14 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -610,9 +600,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "ena" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] @@ -626,6 +616,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_filter" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" version = "0.10.2" @@ -639,6 +639,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -647,12 +660,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -663,9 +676,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -678,7 +691,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "pin-project-lite", ] @@ -697,6 +710,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "fixedbitset" version = "0.4.2" @@ -709,11 +728,17 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -726,9 +751,9 @@ checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -741,9 +766,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -751,15 +776,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -768,9 +793,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -789,9 +814,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ "fastrand 2.3.0", "futures-core", @@ -802,9 +827,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", @@ -813,21 +838,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -837,41 +862,35 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", + "wasip3", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "gloo-timers" version = "0.3.0" @@ -886,9 +905,18 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" @@ -898,9 +926,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "http" @@ -915,12 +943,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -942,7 +969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http 1.4.0", ] [[package]] @@ -953,7 +980,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", + "http 1.4.0", "http-body 1.0.1", "pin-project-lite", ] @@ -1000,9 +1027,9 @@ dependencies = [ [[package]] name = "humantime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" @@ -1020,7 +1047,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -1029,18 +1056,20 @@ dependencies = [ [[package]] name = "hyper" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", - "http 1.3.1", + "futures-core", + "http 1.4.0", "http-body 1.0.1", "httparse", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -1048,12 +1077,12 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.6" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http 1.3.1", - "hyper 1.6.0", + "http 1.4.0", + "hyper 1.8.1", "hyper-util", "log", "rustls", @@ -1070,7 +1099,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.6.0", + "hyper 1.8.1", "hyper-util", "pin-project-lite", "tokio", @@ -1079,20 +1108,19 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.13" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", - "http 1.3.1", + "http 1.4.0", "http-body 1.0.1", - "hyper 1.6.0", + "hyper 1.8.1", "libc", "pin-project-lite", - "socket2", + "socket2 0.6.2", "tokio", "tower-service", "tracing", @@ -1100,9 +1128,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1122,6 +1150,12 @@ dependencies = [ "cc", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "idna" version = "0.5.0" @@ -1134,12 +1168,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] @@ -1153,9 +1189,9 @@ dependencies = [ [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -1163,20 +1199,20 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "isahc" @@ -1216,15 +1252,39 @@ dependencies = [ [[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.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819b44bc7c87d9117eb522f14d46e918add69ff12713c475946b0a29363ed1c2" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "470252db18ecc35fd766c0891b1e3ec6cbbcd62507e85276c01bf75d8e94d4a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -1291,6 +1351,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "levenshtein" version = "1.0.5" @@ -1299,15 +1365,15 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libnghttp2-sys" -version = "0.1.11+1.64.0" +version = "0.1.12+1.68.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6c24e48a7167cffa7119da39d577fa482e66c688a4aac016bee862e1a713c4" +checksum = "31d4c51112b381b39a072a6010bc5d3e5557996c5d0150abacd1d349b2636299" dependencies = [ "cc", "libc", @@ -1315,19 +1381,18 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ - "bitflags 2.9.1", "libc", ] [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "4735e9cbde5aac84a5ce588f6b23a90b9b0b528f6c5a8db8a4aff300463a0839" dependencies = [ "cc", "libc", @@ -1337,34 +1402,33 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" dependencies = [ "value-bag", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "mime" @@ -1372,24 +1436,15 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" -dependencies = [ - "adler2", -] - [[package]] name = "mio" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -1436,9 +1491,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-integer" @@ -1458,15 +1513,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "octocrab" version = "0.44.1" @@ -1482,10 +1528,10 @@ dependencies = [ "either", "futures", "futures-util", - "http 1.3.1", + "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.8.1", "hyper-rustls", "hyper-timeout", "hyper-util", @@ -1515,9 +1561,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl-probe" @@ -1525,11 +1571,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -1545,9 +1597,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1555,32 +1607,32 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" @@ -1609,18 +1661,18 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", @@ -1629,9 +1681,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -1641,9 +1693,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand 2.3.0", @@ -1674,17 +1726,31 @@ dependencies = [ [[package]] name = "polling" -version = "3.8.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", "rustix", - "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" +dependencies = [ + "portable-atomic", ] [[package]] @@ -1701,9 +1767,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "predicates-core", @@ -1711,51 +1777,61 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", ] +[[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 = "proc-macro2" -version = "1.0.95" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "redox_syscall" -version = "0.5.12" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.11.0", ] [[package]] @@ -1764,16 +1840,16 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -1783,9 +1859,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -1794,9 +1870,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "ring" @@ -1806,36 +1882,30 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.27" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "log", "once_cell", @@ -1848,11 +1918,11 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe", + "openssl-probe 0.2.1", "rustls-pki-types", "schannel", "security-framework", @@ -1860,18 +1930,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "ring", "rustls-pki-types", @@ -1880,15 +1950,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -1901,11 +1971,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1925,11 +1995,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.11.0", "core-foundation", "core-foundation-sys", "libc", @@ -1938,28 +2008,44 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +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 = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1968,24 +2054,26 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] name = "serde_path_to_error" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", + "serde_core", ] [[package]] @@ -2000,9 +2088,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -2027,10 +2115,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -2042,30 +2131,27 @@ checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "simple_asn1" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.12", + "thiserror 2.0.18", "time", ] [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "sluice" @@ -2080,24 +2166,24 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "snafu" -version = "0.8.6" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320b01e011bf8d5d7a4a4a4be966d9160968935849c83b918827f6a435e7f627" +checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" dependencies = [ "snafu-derive", ] [[package]] name = "snafu-derive" -version = "0.8.6" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" +checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" dependencies = [ "heck", "proc-macro2", @@ -2115,6 +2201,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "string_cache" version = "0.8.9" @@ -2141,9 +2237,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -2158,15 +2254,15 @@ checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "tempfile" -version = "3.20.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand 2.3.0", - "getrandom 0.3.3", + "getrandom 0.4.1", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2206,11 +2302,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.18", ] [[package]] @@ -2226,9 +2322,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -2237,30 +2333,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -2277,9 +2373,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -2292,25 +2388,24 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.1" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "backtrace", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.2", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -2319,9 +2414,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -2329,9 +2424,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -2342,9 +2437,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -2354,18 +2449,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.26" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", @@ -2377,15 +2472,15 @@ dependencies = [ [[package]] name = "toml_write" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -2400,14 +2495,14 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.4" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.11.0", "bytes", "futures-util", - "http 1.3.1", + "http 1.4.0", "http-body 1.0.1", "iri-string", "pin-project-lite", @@ -2431,9 +2526,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -2443,9 +2538,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -2454,9 +2549,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] @@ -2485,15 +2580,15 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] @@ -2530,9 +2625,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "value-bag" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" [[package]] name = "vcpkg" @@ -2567,52 +2662,49 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "wasm-bindgen" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -2621,9 +2713,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2631,31 +2723,65 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -2690,11 +2816,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2705,9 +2831,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", @@ -2718,9 +2844,9 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -2729,9 +2855,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", @@ -2740,24 +2866,24 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] @@ -2789,6 +2915,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +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" @@ -2813,13 +2957,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "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.48.5" @@ -2832,6 +2993,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" 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.48.5" @@ -2844,6 +3011,12 @@ 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 = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -2856,12 +3029,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" 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.48.5" @@ -2874,6 +3059,12 @@ 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 = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -2886,6 +3077,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" 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.48.5" @@ -2898,6 +3095,12 @@ 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 = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -2910,26 +3113,117 @@ 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 = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ - "bitflags 2.9.1", + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/.github/actions/Cargo.toml b/.github/actions/Cargo.toml new file mode 100644 index 0000000000..3c798000f7 --- /dev/null +++ b/.github/actions/Cargo.toml @@ -0,0 +1,10 @@ +# Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ +# SPDX-License-Identifier: Apache-2.0 + +[workspace] +members = [ + "ci-shared", + "ci-crates", + "clippy-annotation-reporter", +] +resolver = "2" diff --git a/.github/actions/affected-crates/action.yml b/.github/actions/affected-crates/action.yml new file mode 100644 index 0000000000..ec15c320d6 --- /dev/null +++ b/.github/actions/affected-crates/action.yml @@ -0,0 +1,51 @@ +# Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +# SPDX-License-Identifier: Apache-2.0 + +name: 'Get Affected Crates' +description: 'Computes all crates affected (direct + transitive) by changes in a PR or push' + +inputs: + include-non-publishable: + description: 'Include crates with publish = false' + required: false + default: 'false' + base-ref: + description: 'Base ref for comparison (defaults to PR base or HEAD~1 for push)' + required: false + default: '' + +outputs: + affected_crates: + description: 'JSON array of affected crates with name, version, path and manifest' + value: ${{ steps.detect.outputs.affected_crates }} + affected_crates_count: + description: 'Number of affected crates' + value: ${{ steps.detect.outputs.affected_crates_count }} + has_changes: + description: '"true" if any crates are affected' + value: ${{ steps.detect.outputs.has_changes }} + +runs: + using: 'composite' + steps: + - name: Cache [ci-crates build] + uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # 2.8.1 + with: + workspaces: .github/actions + cache-targets: true + + - name: Build ci-crates + shell: bash + run: | + cd ${{ github.action_path }}/.. + cargo build --release -p ci-crates + + - id: detect + name: Detect affected crates + shell: bash + env: + INPUT_INCLUDE_NON_PUBLISHABLE: ${{ inputs.include-non-publishable }} + INPUT_BASE_REF: ${{ inputs.base-ref }} + RUST_LOG: info + run: | + ${{ github.action_path }}/../target/release/affected-crates diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/changed-crates/action.yml index d4333a2993..a9d399afbe 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/changed-crates/action.yml @@ -28,153 +28,23 @@ outputs: runs: using: 'composite' steps: + - name: Cache [ci-crates build] + uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # 2.8.1 + with: + workspaces: .github/actions + cache-targets: true + + - name: Build ci-crates + shell: bash + run: | + cd ${{ github.action_path }}/.. + cargo build --release -p ci-crates + - id: detect + name: Detect changed crates shell: bash env: - INCLUDE_NON_PUBLISHABLE: ${{ inputs.include-non-publishable }} + INPUT_INCLUDE_NON_PUBLISHABLE: ${{ inputs.include-non-publishable }} INPUT_BASE_REF: ${{ inputs.base-ref }} - EVENT_NAME: ${{ github.event_name }} - PR_BASE_REF: ${{ github.base_ref }} run: | - set -uo pipefail - - # Debug trap to see where failures occur - trap 'echo "Error on line $LINENO"; exit 1' ERR - - # Determine base ref for comparison - if [[ -n "$INPUT_BASE_REF" ]]; then - BASE_REF="$INPUT_BASE_REF" - elif [[ "$EVENT_NAME" == "pull_request" ]]; then - BASE_REF="origin/$PR_BASE_REF" - # Ensure base branch is fetched - echo "Fetching base branch: $PR_BASE_REF" - git fetch --depth=1 origin "$PR_BASE_REF:refs/remotes/origin/$PR_BASE_REF" || true - else - # For push events, compare with previous commit - BASE_REF="HEAD~1" - fi - - echo "Using base ref: $BASE_REF" - echo "base_ref=$BASE_REF" >> "$GITHUB_OUTPUT" - - # Get list of changed files (use three-dot diff to compare with merge-base) - # This compares against where the branch diverged, not the current tip of base - if ! CHANGED_FILES=$(git diff --name-only "$BASE_REF"...HEAD 2>/dev/null); then - echo "Warning: Failed to diff against $BASE_REF, exiting" - exit 1 - fi - - # Extract unique crate directories from changed files - CRATES=() - for file in $CHANGED_FILES; do - # Check if file is in a crate directory (has Cargo.toml) - dir=$(dirname "$file") - while [[ "$dir" != "." && "$dir" != "/" ]]; do - if [[ -f "$dir/Cargo.toml" ]]; then - # Check if this crate should be included - if [[ "$INCLUDE_NON_PUBLISHABLE" == "true" ]]; then - CRATES+=("$dir") - elif ! grep -qE '^\s*publish\s*=\s*false' "$dir/Cargo.toml"; then - CRATES+=("$dir") - fi - break - fi - dir=$(dirname "$dir") - done - done - - # Remove duplicates and sort - if [[ ${#CRATES[@]} -eq 0 ]]; then - UNIQUE_CRATES=() - echo "No crates found" - else - UNIQUE_CRATES=($(printf '%s\n' "${CRATES[@]}" | sort -u)) - echo "Unique crates: ${UNIQUE_CRATES[*]}" - fi - - # Build JSON array of objects with name, version, and path - JSON_ARRAY="[" - FIRST=true - - # Handle empty array with set -u - if [[ ${#UNIQUE_CRATES[@]} -eq 0 ]]; then - echo "No crates to process" - else - for crate_path in "${UNIQUE_CRATES[@]}"; do - if [[ -z "$crate_path" ]]; then - continue - fi - - echo "Processing crate: $crate_path" - - # Extract name and version from Cargo.toml - CARGO_TOML="$crate_path/Cargo.toml" - if [[ ! -f "$CARGO_TOML" ]]; then - echo "Warning: Cargo.toml not found at $CARGO_TOML" - continue - fi - - # Check if file is empty (this avoids issues with pipefail + grep on empty files) - if [[ ! -s "$CARGO_TOML" ]]; then - echo "Warning: $CARGO_TOML is empty, skipping" - continue - fi - - # Extract name and version (disable pipefail temporarily for grep) - set +eo pipefail - CRATE_NAME=$(grep -E '^\s*name\s*=' "$CARGO_TOML" 2>/dev/null | head -1 | sed -E 's/.*=\s*"([^"]+)".*/\1/') - CRATE_VERSION=$(grep -E '^\s*version\s*=' "$CARGO_TOML" 2>/dev/null | head -1 | sed -E 's/.*=\s*"([^"]+)".*/\1/') - set -eo pipefail - - if [[ -z "$CRATE_NAME" ]]; then - echo "Warning: Could not extract name from $CARGO_TOML" - continue - fi - - echo " Found: $CRATE_NAME (version: $CRATE_VERSION)" - - # Handle version.workspace = true - if [[ -z "$CRATE_VERSION" ]] || [[ "$CRATE_VERSION" == *"workspace"* ]]; then - CRATE_VERSION="workspace" - fi - - if [[ "$FIRST" == "true" ]]; then - FIRST=false - else - JSON_ARRAY+="," - fi - - JSON_ARRAY+="{\"name\":\"$CRATE_NAME\",\"version\":\"$CRATE_VERSION\",\"path\":\"$crate_path\",\"manifest\":\"$CARGO_TOML\"}" - done - fi - JSON_ARRAY+="]" - - echo "Finished processing all crates" - echo "JSON_ARRAY: $JSON_ARRAY" - - # Ensure JSON is compact (single line) for GITHUB_OUTPUT - # Check if jq is available - if command -v jq &> /dev/null; then - echo "Validating JSON with jq..." - if ! echo "$JSON_ARRAY" | jq -c . >/dev/null 2>&1; then - echo "Error: Invalid JSON generated:" - echo "$JSON_ARRAY" - exit 1 - fi - JSON_ARRAY=$(echo "$JSON_ARRAY" | jq -c .) - CRATES_COUNT=$(echo "$JSON_ARRAY" | jq 'length') - else - echo "Warning: jq not found, using raw JSON" - # Count manually by counting commas + 1, or 0 if empty - if [[ "$JSON_ARRAY" == "[]" ]]; then - CRATES_COUNT=0 - else - CRATES_COUNT=$(echo "$JSON_ARRAY" | grep -o '},{' | wc -l) - CRATES_COUNT=$((CRATES_COUNT + 1)) - fi - fi - - echo "Changed crates: $(echo "$JSON_ARRAY" | tr '\n' ' ')" - echo "crates=$JSON_ARRAY" >> "$GITHUB_OUTPUT" - echo "crates_count=$CRATES_COUNT" >> "$GITHUB_OUTPUT" - + ${{ github.action_path }}/../target/release/changed-crates diff --git a/.github/actions/ci-crates/Cargo.toml b/.github/actions/ci-crates/Cargo.toml new file mode 100644 index 0000000000..61709583ad --- /dev/null +++ b/.github/actions/ci-crates/Cargo.toml @@ -0,0 +1,26 @@ +# Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "ci-crates" +version = "0.1.0" +edition = "2021" +rust-version = "1.84.1" +publish = false + +[[bin]] +name = "changed-crates" +path = "src/bin/changed_crates.rs" + +[[bin]] +name = "affected-crates" +path = "src/bin/affected_crates.rs" + +[dependencies] +ci-shared = { path = "../ci-shared" } +anyhow = "1.0" +clap = { version = "4", features = ["derive", "env"] } +log = "0.4" +env_logger = "0.11" +serde = { version = "1", features = ["derive"] } +serde_json = "1" diff --git a/.github/actions/ci-crates/src/bin/affected_crates.rs b/.github/actions/ci-crates/src/bin/affected_crates.rs new file mode 100644 index 0000000000..7f1b9f8782 --- /dev/null +++ b/.github/actions/ci-crates/src/bin/affected_crates.rs @@ -0,0 +1,158 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +//! Computes all crates affected (direct + transitive) by changes in a PR or push. +//! +//! Reads env vars following the GitHub Actions INPUT_* convention and writes +//! to $GITHUB_OUTPUT. +//! +//! Outputs: +//! affected_crates – JSON array of {name, version, path, manifest} +//! affected_crates_count – integer +//! has_changes – "true" if any crates are affected + +use anyhow::Result; +use ci_crates::git; +use ci_crates::workspace; +use ci_shared::crate_detection::{find_closest_cargo_toml, parse_crate_info, CrateInfo}; +use ci_shared::github_output::set_output; +use std::collections::HashSet; +use std::path::PathBuf; + +const BASE_DEFAULT: &str = "origin/main"; + +fn main() -> Result<()> { + env_logger::init(); + + let include_non_publishable = std::env::var("INPUT_INCLUDE_NON_PUBLISHABLE") + .unwrap_or_default() + .to_lowercase() + == "true"; + + let base_ref = std::env::var("INPUT_BASE_REF").unwrap_or(BASE_DEFAULT.to_string()); + log::info!("Using base ref: {base_ref}"); + + let changed_files = git::changed_files(&base_ref)?; + log::info!("Changed files: {:?}", changed_files); + + // TODO: Check heuristics when workspace manifest (Cargo.toml) or config.toml changed. This could indicate a + // change in: + // * Rust version. + // * Edition. + // * Profile. + // * Compilation flags. + + let meta = workspace::load()?; + let ws_names: HashSet = meta.members().iter().map(|p| p.name.clone()).collect(); + + let direct_crates = collect_changed_crates(&changed_files, include_non_publishable, &ws_names); + + if direct_crates.is_empty() { + return build_output(None) + } + + // Compute transitive affected set + let direct_names: Vec = direct_crates.iter().map(|c| c.name.clone()).collect(); + log::info!("Directly changed crates: {:?}", direct_names); + let affected_names = meta.affected_from(&direct_names); + log::info!("Affected crates (transitive): {:?}", affected_names); + + // Build affected crate info list + let affected_infos: Vec<&CrateInfo> = direct_crates + .iter() + .filter(|c| affected_names.contains(&c.name)) + .collect(); + + // Build CrateInfo for transitively-added crates (not in direct_crates) + let direct_names_set: HashSet<&String> = direct_names.iter().collect(); + let transitive_only: Vec = affected_names + .iter() + .filter(|n| !direct_names_set.contains(n)) + .cloned() + .collect(); + + // Look up transitive-only crates from workspace metadata + let mut all_infos: Vec = affected_infos + .iter() + .map(|c| crate_info_to_json(c)) + .collect(); + + for pkg in meta.members() { + if transitive_only.contains(&pkg.name) { + // pkg.manifest_path is the path to Cargo.toml + let manifest = PathBuf::from(&pkg.manifest_path); + if let Ok(info) = parse_crate_info(&manifest) { + all_infos.push(crate_info_to_json(&info)); + } + } + } + + + build_output(Some(all_infos)) +} + +fn collect_changed_crates( + changed_files: &[String], + include_non_publishable: bool, + ws_names: &HashSet, +) -> Vec { + let mut seen_manifests: HashSet = HashSet::new(); + let mut crates: Vec = Vec::new(); + + for file in changed_files { + let path = std::path::Path::new(file); + let Some(manifest) = find_closest_cargo_toml(path) else { + continue; + }; + if seen_manifests.contains(&manifest) { + continue; + } + seen_manifests.insert(manifest.clone()); + + match parse_crate_info(&manifest) { + Ok(info) => { + if !ws_names.contains(&info.name) { + log::debug!("Skipping {} (not in main workspace)", info.name); + continue; + } + if include_non_publishable || info.publish { + crates.push(info); + } + } + Err(e) => { + log::warn!("Skipping {}: {e}", manifest.display()); + } + } + } + + crates +} + +fn crate_info_to_json(c: &CrateInfo) -> serde_json::Value { + serde_json::json!({ + "name": c.name, + "version": c.version, + "path": c.path, + "manifest": c.manifest, + }) +} + +fn build_output(affected_crates: Option>) -> Result<()> { + + let (crates, len, has_changes): (String, String, String) = if let Some(crates) = affected_crates { + (serde_json::to_string(&crates).unwrap_or("[]".to_string()), crates.len().to_string(), "true".to_string()) + } else { + ("[]".to_string(), "0".to_string(), "false".to_string()) + }; + + if std::env::var("DEBUG").is_ok() { + log::info!("affected_crates: {:?}", crates); + log::info!("len: {:?}", len); + log::info!("has_changes: {:?}", len); + } else { + set_output("affected_crates", &crates)?; + set_output("affected_crates_count", &len)?; + set_output("has_changes", &has_changes)?; + } + Ok(()) +} diff --git a/.github/actions/ci-crates/src/bin/changed_crates.rs b/.github/actions/ci-crates/src/bin/changed_crates.rs new file mode 100644 index 0000000000..62b8befcfe --- /dev/null +++ b/.github/actions/ci-crates/src/bin/changed_crates.rs @@ -0,0 +1,111 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +//! Detects which Rust crates have changed files in a PR or push. +//! +//! Reads env vars following the GitHub Actions INPUT_* convention and writes +//! to $GITHUB_OUTPUT. +//! +//! Outputs: +//! crates – JSON array of {name, version, path, manifest} +//! crates_count – integer count +//! base_ref – the base ref used for comparison + +use anyhow::Result; +use ci_crates::git; +use ci_shared::crate_detection::{find_closest_cargo_toml, parse_crate_info, CrateInfo}; +use ci_shared::github_output::set_output; +use std::collections::HashSet; +use std::path::PathBuf; + +fn main() -> Result<()> { + env_logger::init(); + + let include_non_publishable = std::env::var("INPUT_INCLUDE_NON_PUBLISHABLE") + .unwrap_or_default() + .to_lowercase() + == "true"; + + let input_base_ref = std::env::var("INPUT_BASE_REF").unwrap_or_default(); + let event_name = std::env::var("GITHUB_EVENT_NAME").unwrap_or_default(); + let pr_base_ref = std::env::var("GITHUB_BASE_REF").unwrap_or_default(); + + let base_ref = determine_base_ref(&input_base_ref, &event_name, &pr_base_ref)?; + + log::info!("Using base ref: {base_ref}"); + set_output("base_ref", &base_ref)?; + + let changed = git::changed_files(&base_ref)?; + log::info!("Changed files: {:?}", changed); + + let crates = collect_changed_crates(&changed, include_non_publishable); + + let json = serde_json::to_string(&crates)?; + log::info!("Changed crates: {json}"); + + set_output("crates", &json)?; + set_output("crates_count", &crates.len().to_string())?; + + Ok(()) +} + +fn determine_base_ref( + input_base_ref: &str, + event_name: &str, + pr_base_ref: &str, +) -> Result { + if !input_base_ref.is_empty() { + return Ok(input_base_ref.to_string()); + } + + if event_name == "pull_request" { + let base = format!("origin/{pr_base_ref}"); + git::fetch_base(&base)?; + return Ok(base); + } + + Ok("HEAD~1".to_string()) +} + +pub fn collect_changed_crates( + changed_files: &[String], + include_non_publishable: bool, +) -> Vec { + let mut seen_manifests: HashSet = HashSet::new(); + let mut crates: Vec = Vec::new(); + + for file in changed_files { + let path = std::path::Path::new(file); + let Some(manifest) = find_closest_cargo_toml(path) else { + continue; + }; + + if seen_manifests.contains(&manifest) { + continue; + } + seen_manifests.insert(manifest.clone()); + + match parse_crate_info(&manifest) { + Ok(info) => { + if include_non_publishable || info.publish { + crates.push(info); + } + } + Err(e) => { + log::warn!("Skipping {}: {e}", manifest.display()); + } + } + } + + crates + .into_iter() + .map(|c| { + serde_json::json!({ + "name": c.name, + "version": c.version, + "path": c.path, + "manifest": c.manifest, + }) + }) + .collect() +} diff --git a/.github/actions/ci-crates/src/git.rs b/.github/actions/ci-crates/src/git.rs new file mode 100644 index 0000000000..6ccb0d7c75 --- /dev/null +++ b/.github/actions/ci-crates/src/git.rs @@ -0,0 +1,53 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{bail, Context, Result}; +use std::process::Command; + +/// Run `git fetch --depth=1 origin ` to ensure the base ref is available locally. +pub fn fetch_base(base_ref: &str) -> Result<()> { + // Strip "origin/" prefix if present — we pass it to `git fetch origin ` + let branch = base_ref.strip_prefix("origin/").unwrap_or(base_ref); + log::info!("Fetching base branch: {branch}"); + + let status = Command::new("git") + .args([ + "fetch", + "--depth=1", + "origin", + &format!("{branch}:refs/remotes/origin/{branch}"), + ]) + .status() + .context("Failed to run git fetch")?; + + if !status.success() { + // Non-fatal: warn but do not abort (mirrors `|| true` in the bash version) + log::warn!("git fetch for {base_ref} returned non-zero exit code; continuing"); + } + + Ok(()) +} + +/// Return the list of files changed between `...HEAD` (three-dot diff). +/// +/// Uses `git diff --name-only ...HEAD`. +pub fn changed_files(base_ref: &str) -> Result> { + let output = Command::new("git") + .args(["diff", "--name-only", &format!("{base_ref}...HEAD")]) + .output() + .context("Failed to run git diff")?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + bail!("git diff failed against {base_ref}: {stderr}"); + } + + let stdout = String::from_utf8_lossy(&output.stdout); + let files: Vec = stdout + .lines() + .map(|l| l.to_string()) + .filter(|l| !l.is_empty()) + .collect(); + + Ok(files) +} diff --git a/.github/actions/ci-crates/src/lib.rs b/.github/actions/ci-crates/src/lib.rs new file mode 100644 index 0000000000..a85f13e761 --- /dev/null +++ b/.github/actions/ci-crates/src/lib.rs @@ -0,0 +1,5 @@ +// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +pub mod git; +pub mod workspace; diff --git a/.github/actions/ci-crates/src/workspace.rs b/.github/actions/ci-crates/src/workspace.rs new file mode 100644 index 0000000000..340eaa9c81 --- /dev/null +++ b/.github/actions/ci-crates/src/workspace.rs @@ -0,0 +1,110 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{Context, Result}; +use serde::Deserialize; +use std::collections::{HashMap, HashSet, VecDeque}; +use std::process::Command; + +/// A workspace member as returned by `cargo metadata`. +#[derive(Debug, Deserialize)] +pub struct Package { + pub name: String, + pub manifest_path: String, + pub dependencies: Vec, +} + +#[derive(Debug, Deserialize)] +pub struct Dependency { + pub name: String, +} + +#[derive(Debug, Deserialize)] +struct CargoMetadata { + packages: Vec, + workspace_members: Vec, +} + +/// Parsed workspace metadata with reverse-dependency index. +pub struct WorkspaceMetadata { + packages: Vec, + reverse_deps: HashMap>, +} + +pub fn load() -> Result { + let output = Command::new("cargo") + .args(["metadata", "--format-version=1", "--no-deps"]) + .output() + .context("Failed to run cargo metadata")?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + anyhow::bail!("cargo metadata failed: {stderr}"); + } + + let meta: CargoMetadata = + serde_json::from_slice(&output.stdout).context("Failed to parse cargo metadata output")?; + + let ws_member_ids: HashSet<&str> = meta.workspace_members.iter().map(|s| s.as_str()).collect(); + + let ws_packages: Vec = meta + .packages + .into_iter() + .filter(|p| { + ws_member_ids + .iter() + .any(|id| id.starts_with(&format!("{} ", p.name))) + }) + .collect(); + + let ws_names: HashSet = ws_packages.iter().map(|p| p.name.clone()).collect(); + let mut reverse_deps: HashMap> = HashMap::new(); + for pkg in &ws_packages { + for dep in &pkg.dependencies { + if ws_names.contains(&dep.name) { + reverse_deps + .entry(dep.name.clone()) + .or_default() + .push(pkg.name.clone()); + } + } + } + + Ok(WorkspaceMetadata { + packages: ws_packages, + reverse_deps, + }) +} + +impl WorkspaceMetadata { + pub fn members(&self) -> &[Package] { + &self.packages + } + + pub fn affected_from(&self, seeds: &[String]) -> Vec { + let mut visited: HashSet = HashSet::new(); + let mut queue: VecDeque = VecDeque::new(); + + for seed in seeds { + if !visited.contains(seed) { + visited.insert(seed.clone()); + queue.push_back(seed.clone()); + } + } + + while let Some(current) = queue.pop_front() { + if let Some(dependents) = self.reverse_deps.get(¤t) { + for dep in dependents { + if !visited.contains(dep) { + visited.insert(dep.clone()); + queue.push_back(dep.clone()); + } + } + } + } + + let mut result: Vec = visited.into_iter().collect(); + result.sort(); + result + } +} diff --git a/.github/actions/ci-shared/Cargo.toml b/.github/actions/ci-shared/Cargo.toml new file mode 100644 index 0000000000..265f227d28 --- /dev/null +++ b/.github/actions/ci-shared/Cargo.toml @@ -0,0 +1,19 @@ +# Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "ci-shared" +version = "0.1.0" +edition = "2021" +rust-version = "1.84.1" +publish = false + +[dependencies] +anyhow = "1.0" +log = "0.4" +toml = "0.8" +serde = { version = "1", features = ["derive"] } +serde_json = "1" + +[dev-dependencies] +tempfile = "3" diff --git a/.github/actions/clippy-annotation-reporter/src/analyzer/crate_detection.rs b/.github/actions/ci-shared/src/crate_detection.rs similarity index 67% rename from .github/actions/clippy-annotation-reporter/src/analyzer/crate_detection.rs rename to .github/actions/ci-shared/src/crate_detection.rs index 3e5847bbdf..2c53ac84a5 100644 --- a/.github/actions/clippy-annotation-reporter/src/analyzer/crate_detection.rs +++ b/.github/actions/ci-shared/src/crate_detection.rs @@ -1,31 +1,29 @@ -// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 -use log::error; +use anyhow::{Context, Result}; +use serde::{Deserialize, Serialize}; use std::fs; use std::path::{Path, PathBuf}; use toml::Value; -/// Get crate information for a given file path by finding the closest Cargo.toml -pub(super) fn get_crate_for_file(file_path: &str) -> String { - let path = Path::new(file_path); - - // Try to find the closest Cargo.toml file - if let Some(cargo_toml_path) = find_closest_cargo_toml(path) { - if let Some(crate_name) = extract_package_name(&cargo_toml_path) { - return crate_name; - } - } - - error!( - "Could not find crate for {}, falling back to unknown-crate", - file_path - ); - "unknown-crate".to_owned() +/// Information about a Rust crate parsed from its Cargo.toml +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CrateInfo { + pub name: String, + /// "workspace" if version.workspace = true, otherwise the literal version string + pub version: String, + /// Directory containing Cargo.toml + pub path: PathBuf, + /// Full path to Cargo.toml + pub manifest: PathBuf, + /// false only if publish = false explicitly + pub publish: bool, } -/// Find the closest Cargo.toml file by traversing up the directory tree -fn find_closest_cargo_toml(mut path: &Path) -> Option { +/// Find the closest Cargo.toml file by traversing up the directory tree. +/// Returns None if no Cargo.toml is found before the filesystem root. +pub fn find_closest_cargo_toml(mut path: &Path) -> Option { // Start with the directory containing the file if !path.is_dir() { path = path.parent()?; @@ -41,41 +39,83 @@ fn find_closest_cargo_toml(mut path: &Path) -> Option { // Check if we've reached the root let parent = path.parent()?; if parent == path { - // We've reached the root without finding Cargo.toml return None; } - // Move up one directory path = parent; } } -/// Extract package name from Cargo.toml -fn extract_package_name(cargo_toml_path: &Path) -> Option { - // Read the Cargo.toml file - let content = match fs::read_to_string(cargo_toml_path) { - Ok(content) => content, - Err(e) => { - log::warn!("Failed to read {}: {}", cargo_toml_path.display(), e); - return None; +/// Parse full crate information from a Cargo.toml manifest path. +pub fn parse_crate_info(manifest: &Path) -> Result { + let content = fs::read_to_string(manifest) + .with_context(|| format!("Failed to read {}", manifest.display()))?; + + let toml_value: Value = content + .parse() + .with_context(|| format!("Failed to parse {}", manifest.display()))?; + + let package = toml_value + .get("package") + .with_context(|| format!("No [package] section in {}", manifest.display()))?; + + let name = package + .get("name") + .and_then(|v| v.as_str()) + .with_context(|| format!("No package.name in {}", manifest.display()))? + .to_string(); + + // version.workspace = true → use "workspace" as the version string + let version = if let Some(ver_table) = package.get("version").and_then(|v| v.as_table()) { + if ver_table.get("workspace").and_then(|v| v.as_bool()) == Some(true) { + "workspace".to_string() + } else { + "workspace".to_string() // unusual but treat as workspace } + } else { + package + .get("version") + .and_then(|v| v.as_str()) + .unwrap_or("workspace") + .to_string() }; - // Parse the TOML - let toml_value: Value = match content.parse() { - Ok(value) => value, - Err(e) => { - log::warn!("Failed to parse {}: {}", cargo_toml_path.display(), e); - return None; - } + // publish = false means not publishable; anything else (missing, true, list) means publishable + let publish = match package.get("publish") { + Some(Value::Boolean(false)) => false, + _ => true, }; - // Extract the package name - toml_value - .get("package")? - .get("name")? - .as_str() - .map(|s| s.to_string()) + let path = manifest + .parent() + .with_context(|| format!("Manifest {} has no parent directory", manifest.display()))? + .to_path_buf(); + + Ok(CrateInfo { + name, + version, + path, + manifest: manifest.to_path_buf(), + publish, + }) +} + +/// Get crate name for a given file path by finding the closest Cargo.toml. +/// Returns "unknown-crate" if no crate can be determined. +pub fn get_crate_for_file(file_path: &str) -> String { + let path = Path::new(file_path); + + if let Some(cargo_toml_path) = find_closest_cargo_toml(path) { + if let Ok(info) = parse_crate_info(&cargo_toml_path) { + return info.name; + } + } + + log::error!( + "Could not find crate for {}, falling back to unknown-crate", + file_path + ); + "unknown-crate".to_owned() } #[cfg(test)] @@ -85,7 +125,6 @@ mod tests { use std::io::Write; use tempfile::TempDir; - // Helper function to create a Cargo.toml file with a specific package name fn create_cargo_toml(path: &Path, package_name: &str) -> std::io::Result<()> { let mut file = File::create(path)?; writeln!( @@ -102,17 +141,14 @@ edition = "2021" #[test] fn test_get_crate_for_file_direct_parent() { - // Create a temporary directory with a specific crate structure let temp_dir = TempDir::new().expect("Failed to create temp directory"); let crate_root = temp_dir.path().join("my-crate"); fs::create_dir_all(&crate_root).expect("Failed to create crate directory"); - // Create Cargo.toml in the crate root let cargo_toml_path = crate_root.join("Cargo.toml"); create_cargo_toml(&cargo_toml_path, "my-awesome-crate") .expect("Failed to create Cargo.toml"); - // Create a source file in the same directory let source_file_path = crate_root.join("lib.rs"); File::create(&source_file_path).expect("Failed to create source file"); @@ -126,18 +162,15 @@ edition = "2021" #[test] fn test_get_crate_for_file_nested_directory() { - // Create a temporary directory with a nested structure let temp_dir = TempDir::new().expect("Failed to create temp directory"); let crate_root = temp_dir.path().join("my-crate"); let src_dir = crate_root.join("src"); let module_dir = src_dir.join("module"); fs::create_dir_all(&module_dir).expect("Failed to create nested directories"); - // Create Cargo.toml in the crate root let cargo_toml_path = crate_root.join("Cargo.toml"); create_cargo_toml(&cargo_toml_path, "nested-crate").expect("Failed to create Cargo.toml"); - // Create a source file in the nested directory let source_file_path = module_dir.join("mod.rs"); File::create(&source_file_path).expect("Failed to create source file"); @@ -151,7 +184,6 @@ edition = "2021" #[test] fn test_get_crate_for_file_multiple_cargo_tomls() { - // Create a temporary directory with nested crates let temp_dir = TempDir::new().expect("Failed to create temp directory"); let workspace_dir = temp_dir.path().join("workspace"); let parent_crate_dir = workspace_dir.join("parent-crate"); @@ -161,7 +193,6 @@ edition = "2021" fs::create_dir_all(&parent_crate_dir).expect("Failed to create parent crate directory"); fs::create_dir_all(&child_src_dir).expect("Failed to create child crate src directory"); - // Create Cargo.toml in both crate directories let parent_cargo_toml = parent_crate_dir.join("Cargo.toml"); create_cargo_toml(&parent_cargo_toml, "parent-crate") .expect("Failed to create parent Cargo.toml"); @@ -170,7 +201,6 @@ edition = "2021" create_cargo_toml(&child_cargo_toml, "child-crate") .expect("Failed to create child Cargo.toml"); - // Create a source file in the child crate let source_file_path = child_src_dir.join("lib.rs"); File::create(&source_file_path).expect("Failed to create source file"); @@ -184,12 +214,10 @@ edition = "2021" #[test] fn test_get_crate_for_file_no_cargo_toml() { - // Create a temporary directory with no Cargo.toml let temp_dir = TempDir::new().expect("Failed to create temp directory"); let src_dir = temp_dir.path().join("src"); fs::create_dir_all(&src_dir).expect("Failed to create src directory"); - // Create a source file let source_file_path = src_dir.join("orphan.rs"); File::create(&source_file_path).expect("Failed to create source file"); @@ -203,12 +231,10 @@ edition = "2021" #[test] fn test_get_crate_for_file_invalid_cargo_toml() { - // Create a temporary directory with an invalid Cargo.toml let temp_dir = TempDir::new().expect("Failed to create temp directory"); let crate_dir = temp_dir.path().join("invalid-crate"); fs::create_dir_all(&crate_dir).expect("Failed to create crate directory"); - // Create an invalid Cargo.toml (missing package name) let cargo_toml_path = crate_dir.join("Cargo.toml"); let mut file = File::create(&cargo_toml_path).expect("Failed to create Cargo.toml"); writeln!( @@ -221,7 +247,6 @@ edition = "2021" ) .expect("Failed to write to Cargo.toml"); - // Create a source file let source_file_path = crate_dir.join("lib.rs"); File::create(&source_file_path).expect("Failed to create source file"); @@ -235,12 +260,10 @@ edition = "2021" #[test] fn test_get_crate_for_file_workspace_member() { - // Create a temporary directory with a workspace structure let temp_dir = TempDir::new().expect("Failed to create temp directory"); let workspace_dir = temp_dir.path().join("workspace"); fs::create_dir_all(&workspace_dir).expect("Failed to create workspace directory"); - // Create workspace Cargo.toml let workspace_cargo_toml = workspace_dir.join("Cargo.toml"); let mut file = File::create(&workspace_cargo_toml).expect("Failed to create workspace Cargo.toml"); @@ -253,17 +276,14 @@ members = ["member1", "member2"] ) .expect("Failed to write to workspace Cargo.toml"); - // Create member1 crate let member1_dir = workspace_dir.join("member1"); let member1_src_dir = member1_dir.join("src"); fs::create_dir_all(&member1_src_dir).expect("Failed to create member1 src directory"); - // Create member1 Cargo.toml let member1_cargo_toml = member1_dir.join("Cargo.toml"); create_cargo_toml(&member1_cargo_toml, "workspace-member1") .expect("Failed to create member1 Cargo.toml"); - // Create a source file in member1 let source_file_path = member1_src_dir.join("lib.rs"); File::create(&source_file_path).expect("Failed to create source file"); @@ -277,7 +297,6 @@ members = ["member1", "member2"] #[test] fn test_get_crate_for_file_non_existent_file() { - // Test with a non-existent file path let crate_name = get_crate_for_file("/path/to/non/existent/file.rs"); assert_eq!( @@ -288,17 +307,14 @@ members = ["member1", "member2"] #[test] fn test_get_crate_for_file_with_special_chars() { - // Create a temporary directory with spaces and special characters let temp_dir = TempDir::new().expect("Failed to create temp directory"); let crate_dir = temp_dir.path().join("my crate with spaces"); fs::create_dir_all(&crate_dir).expect("Failed to create crate directory with spaces"); - // Create Cargo.toml let cargo_toml_path = crate_dir.join("Cargo.toml"); create_cargo_toml(&cargo_toml_path, "special-chars-crate") .expect("Failed to create Cargo.toml"); - // Create a source file let source_file_path = crate_dir.join("special file.rs"); File::create(&source_file_path).expect("Failed to create source file with spaces"); @@ -312,13 +328,11 @@ members = ["member1", "member2"] #[test] fn test_get_crate_for_file_with_directory_not_file() { - // Create a temporary directory structure let temp_dir = TempDir::new().expect("Failed to create temp directory"); let crate_dir = temp_dir.path().join("directory-test"); let src_dir = crate_dir.join("src"); fs::create_dir_all(&src_dir).expect("Failed to create directories"); - // Create Cargo.toml let cargo_toml_path = crate_dir.join("Cargo.toml"); create_cargo_toml(&cargo_toml_path, "directory-crate") .expect("Failed to create Cargo.toml"); @@ -330,4 +344,53 @@ members = ["member1", "member2"] "Should work with directory paths" ); } + + #[test] + fn test_parse_crate_info_publish_false() { + let temp_dir = TempDir::new().expect("Failed to create temp directory"); + let crate_dir = temp_dir.path().join("my-crate"); + fs::create_dir_all(&crate_dir).expect("Failed to create crate directory"); + + let cargo_toml_path = crate_dir.join("Cargo.toml"); + let mut file = File::create(&cargo_toml_path).expect("Failed to create Cargo.toml"); + writeln!( + file, + r#"[package] +name = "my-crate" +version = "1.2.3" +edition = "2021" +publish = false +"# + ) + .expect("Failed to write Cargo.toml"); + + let info = parse_crate_info(&cargo_toml_path).expect("parse should succeed"); + assert_eq!(info.name, "my-crate"); + assert_eq!(info.version, "1.2.3"); + assert!(!info.publish); + } + + #[test] + fn test_parse_crate_info_workspace_version() { + let temp_dir = TempDir::new().expect("Failed to create temp directory"); + let crate_dir = temp_dir.path().join("ws-crate"); + fs::create_dir_all(&crate_dir).expect("Failed to create crate directory"); + + let cargo_toml_path = crate_dir.join("Cargo.toml"); + let mut file = File::create(&cargo_toml_path).expect("Failed to create Cargo.toml"); + writeln!( + file, + r#"[package] +name = "ws-crate" +version.workspace = true +edition = "2021" +"# + ) + .expect("Failed to write Cargo.toml"); + + let info = parse_crate_info(&cargo_toml_path).expect("parse should succeed"); + assert_eq!(info.name, "ws-crate"); + assert_eq!(info.version, "workspace"); + assert!(info.publish); + } } diff --git a/.github/actions/ci-shared/src/github_output.rs b/.github/actions/ci-shared/src/github_output.rs new file mode 100644 index 0000000000..134a8e65b8 --- /dev/null +++ b/.github/actions/ci-shared/src/github_output.rs @@ -0,0 +1,45 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{Context, Result}; +use std::fs::OpenOptions; +use std::io::Write; + +fn github_output_path() -> Result { + std::env::var("GITHUB_OUTPUT").context("GITHUB_OUTPUT environment variable not set") +} + +/// Append `key=value\n` to the file at `$GITHUB_OUTPUT`. +pub fn set_output(key: &str, value: &str) -> Result<()> { + let path = github_output_path()?; + let mut file = OpenOptions::new() + .create(true) + .append(true) + .open(&path) + .with_context(|| format!("Failed to open GITHUB_OUTPUT file at {path}"))?; + writeln!(file, "{key}={value}") + .with_context(|| format!("Failed to write to GITHUB_OUTPUT file at {path}"))?; + Ok(()) +} + +/// Append a multiline value using the heredoc delimiter format required by GitHub Actions. +/// +/// Format: +/// ```text +/// key<<_DELIMITER_ +/// value line 1 +/// value line 2 +/// _DELIMITER_ +/// ``` +pub fn set_multiline_output(key: &str, value: &str) -> Result<()> { + let path = github_output_path()?; + let mut file = OpenOptions::new() + .create(true) + .append(true) + .open(&path) + .with_context(|| format!("Failed to open GITHUB_OUTPUT file at {path}"))?; + writeln!(file, "{key}<<_DELIMITER_")?; + writeln!(file, "{value}")?; + writeln!(file, "_DELIMITER_")?; + Ok(()) +} diff --git a/.github/actions/ci-shared/src/lib.rs b/.github/actions/ci-shared/src/lib.rs new file mode 100644 index 0000000000..ac3c51bfb1 --- /dev/null +++ b/.github/actions/ci-shared/src/lib.rs @@ -0,0 +1,5 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +pub mod crate_detection; +pub mod github_output; diff --git a/.github/actions/clippy-annotation-reporter/Cargo.toml b/.github/actions/clippy-annotation-reporter/Cargo.toml index 7ec2ae971b..7cf5bcf390 100644 --- a/.github/actions/clippy-annotation-reporter/Cargo.toml +++ b/.github/actions/clippy-annotation-reporter/Cargo.toml @@ -18,14 +18,10 @@ log = "0.4" env_logger = "0.10" # Octocrab has a defined MSRV < 1.78 and depends on url 2.5.4 which also has a defined MSRV < 1.78 but url has a dependency on `idna` has a MSRV of 1.81. Not sure what is going on here. url = "=2.5.2" -toml = "0.8.22" mockall = "0.13.1" +ci-shared = { path = "../ci-shared" } [dev-dependencies] httpmock = "0.6" http = "1.1.0" tempfile = "3.20.0" - -# TODO: Remove this when move to separate repo -[workspace] -members = ["."] diff --git a/.github/actions/clippy-annotation-reporter/action.yml b/.github/actions/clippy-annotation-reporter/action.yml index 467255524f..b0cdeceb26 100644 --- a/.github/actions/clippy-annotation-reporter/action.yml +++ b/.github/actions/clippy-annotation-reporter/action.yml @@ -37,16 +37,12 @@ runs: - name: Build annotation reporter shell: bash run: | - cd ${{ github.action_path }} - cargo build --release - - name: Debug step - shell: bash - run: | - FILE_PATH="data-pipeline/src/trace_exporter/mod.rs" + cd ${{ github.action_path }}/.. + cargo build --release -p clippy-annotation-reporter - name: Run annotation reporter shell: bash run: | - ${{ github.action_path }}/target/release/clippy-annotation-reporter \ + ${{ github.action_path }}/../target/release/clippy-annotation-reporter \ --token "${{ inputs.github-token }}" \ --rules "${{ inputs.allow-annotation-rules }}" \ --repo "${{ github.repository }}" \ diff --git a/.github/actions/clippy-annotation-reporter/src/analyzer/annotation.rs b/.github/actions/clippy-annotation-reporter/src/analyzer/annotation.rs index f4e0ab485c..2930f6f58c 100644 --- a/.github/actions/clippy-annotation-reporter/src/analyzer/annotation.rs +++ b/.github/actions/clippy-annotation-reporter/src/analyzer/annotation.rs @@ -3,9 +3,9 @@ //! Functions for finding and parsing clippy annotations -use crate::analyzer::crate_detection::get_crate_for_file; use crate::analyzer::ClippyAnnotation; use anyhow::{Context, Result}; +use ci_shared::crate_detection::get_crate_for_file; use regex::Regex; use std::collections::HashMap; use std::rc::Rc; diff --git a/.github/actions/clippy-annotation-reporter/src/analyzer/mod.rs b/.github/actions/clippy-annotation-reporter/src/analyzer/mod.rs index de82fbe68b..734514912b 100644 --- a/.github/actions/clippy-annotation-reporter/src/analyzer/mod.rs +++ b/.github/actions/clippy-annotation-reporter/src/analyzer/mod.rs @@ -18,7 +18,6 @@ use std::collections::{HashMap, HashSet}; use std::rc::Rc; mod annotation; -mod crate_detection; mod git; /// Represents a clippy annotation in code diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index a44010700f..c8d2f2a293 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,12 +1,29 @@ name: Fuzz test on: + pull_request: push: + branches: [main, 'julio/rd-week-*'] jobs: + compute-scope: + runs-on: ubuntu-latest + outputs: + run_full: ${{ steps.scope.outputs.run_full }} + has_changes: ${{ steps.scope.outputs.has_changes }} + affected_fuzz_dirs: ${{ steps.scope.outputs.affected_fuzz_dirs }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + fetch-depth: 0 + - id: scope + uses: ./.github/actions/affected-crates + run-fuzz: + needs: [compute-scope] + if: needs.compute-scope.outputs.affected_fuzz_dirs != '[]' runs-on: ubuntu-latest strategy: matrix: - directory: [libdd-alloc, libdd-profiling, libdd-common-ffi, libdd-trace-utils] + directory: ${{ fromJSON(needs.compute-scope.outputs.affected_fuzz_dirs) }} env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b33af83d94..d01ef9b793 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,10 +1,24 @@ name: Lint on: + pull_request: push: + branches: [main, 'julio/rd-week-*'] env: CARGO_TERM_COLOR: always jobs: + compute-scope: + runs-on: ubuntu-latest + outputs: + has_changes: ${{ steps.scope.outputs.has_changes }} + affected_crates: ${{ steps.scope.outputs.affected_crates }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + fetch-depth: 0 + - id: scope + uses: ./.github/actions/affected-crates + actionlint: runs-on: ubuntu-latest steps: @@ -32,6 +46,8 @@ jobs: - run: cargo fmt --all -- --check clippy: name: "clippy #${{ matrix.platform }} ${{ matrix.rust_version }}" + needs: [compute-scope] + if: needs.compute-scope.outputs.has_changes == 'true' runs-on: ${{ matrix.platform }} strategy: fail-fast: false @@ -54,8 +70,9 @@ jobs: if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then export AWS_LC_FIPS_SYS_NO_ASM=1 fi - # shellcheck disable=SC2046 - cargo clippy --workspace --all-targets --all-features -- -D warnings + + AFFECTED_CRATES_ARGS=$(echo '${{ needs.compute-scope.outputs.affected_crates }}' | jq -r '[.[].name] | map("-p " + .) | join(" ")') + cargo clippy $AFFECTED_CRATES_ARGS --all-targets --all-features -- -D warnings licensecheck: runs-on: ubuntu-latest @@ -77,7 +94,7 @@ jobs: # cargo-bundle-licenses is "unsure" or "semi" confident. This means that # when the found license was compared to a template license it was found to # have diverged in more than a few words. You should verify that the licence - # text is in fact correct in these cases. + # text is in fact correct in these cases. license-3rdparty: runs-on: ubuntu-latest name: "Valid LICENSE-3rdparty.yml" From 313ee4a41e545dcade76316a6d0d36122c857e6d Mon Sep 17 00:00:00 2001 From: Julio Date: Wed, 4 Mar 2026 17:46:19 +0100 Subject: [PATCH 02/26] Unify all computation in one action --- .github/actions/Cargo.lock | 38 ++++ .github/actions/affected-crates/action.yml | 51 ----- .github/actions/changed-crates/action.yml | 29 +-- .github/actions/ci-crates/Cargo.toml | 5 +- .../ci-crates/src/bin/affected_crates.rs | 158 ------------- .../ci-crates/src/bin/changed_crates.rs | 155 ++++++------- .github/actions/ci-crates/src/git.rs | 1 + .github/actions/ci-crates/src/workspace.rs | 211 ++++++++++++------ .../actions/ci-shared/src/crate_detection.rs | 1 + 9 files changed, 262 insertions(+), 387 deletions(-) delete mode 100644 .github/actions/affected-crates/action.yml delete mode 100644 .github/actions/ci-crates/src/bin/affected_crates.rs diff --git a/.github/actions/Cargo.lock b/.github/actions/Cargo.lock index 7e38c57229..f89dda4a45 100644 --- a/.github/actions/Cargo.lock +++ b/.github/actions/Cargo.lock @@ -361,6 +361,39 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.18", +] + [[package]] name = "castaway" version = "0.1.2" @@ -402,6 +435,7 @@ name = "ci-crates" version = "0.1.0" dependencies = [ "anyhow", + "cargo_metadata", "ci-shared", "clap", "env_logger 0.11.9", @@ -2021,6 +2055,10 @@ name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "serde" diff --git a/.github/actions/affected-crates/action.yml b/.github/actions/affected-crates/action.yml deleted file mode 100644 index ec15c320d6..0000000000 --- a/.github/actions/affected-crates/action.yml +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ -# SPDX-License-Identifier: Apache-2.0 - -name: 'Get Affected Crates' -description: 'Computes all crates affected (direct + transitive) by changes in a PR or push' - -inputs: - include-non-publishable: - description: 'Include crates with publish = false' - required: false - default: 'false' - base-ref: - description: 'Base ref for comparison (defaults to PR base or HEAD~1 for push)' - required: false - default: '' - -outputs: - affected_crates: - description: 'JSON array of affected crates with name, version, path and manifest' - value: ${{ steps.detect.outputs.affected_crates }} - affected_crates_count: - description: 'Number of affected crates' - value: ${{ steps.detect.outputs.affected_crates_count }} - has_changes: - description: '"true" if any crates are affected' - value: ${{ steps.detect.outputs.has_changes }} - -runs: - using: 'composite' - steps: - - name: Cache [ci-crates build] - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # 2.8.1 - with: - workspaces: .github/actions - cache-targets: true - - - name: Build ci-crates - shell: bash - run: | - cd ${{ github.action_path }}/.. - cargo build --release -p ci-crates - - - id: detect - name: Detect affected crates - shell: bash - env: - INPUT_INCLUDE_NON_PUBLISHABLE: ${{ inputs.include-non-publishable }} - INPUT_BASE_REF: ${{ inputs.base-ref }} - RUST_LOG: info - run: | - ${{ github.action_path }}/../target/release/affected-crates diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/changed-crates/action.yml index a9d399afbe..82c2d58e2d 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/changed-crates/action.yml @@ -4,16 +4,6 @@ name: 'Get Changed Crates' description: 'Detects which Rust crates have changed files in a PR or push' -inputs: - include-non-publishable: - description: 'Include crates with publish = false' - required: false - default: 'false' - base-ref: - description: 'Base ref for comparison (defaults to PR base or HEAD~1 for push)' - required: false - default: '' - outputs: crates: description: 'JSON array of changed crates with name, version, path and manifest' @@ -28,23 +18,10 @@ outputs: runs: using: 'composite' steps: - - name: Cache [ci-crates build] - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # 2.8.1 - with: - workspaces: .github/actions - cache-targets: true - - - name: Build ci-crates - shell: bash - run: | - cd ${{ github.action_path }}/.. - cargo build --release -p ci-crates - - id: detect - name: Detect changed crates shell: bash env: - INPUT_INCLUDE_NON_PUBLISHABLE: ${{ inputs.include-non-publishable }} - INPUT_BASE_REF: ${{ inputs.base-ref }} + EVENT_NAME: ${{ github.event_name }} + PR_BASE_REF: ${{ github.base_ref }} run: | - ${{ github.action_path }}/../target/release/changed-crates + ${{ github.action_path }}/../target/release/changed-crates $PR_BASE_REF diff --git a/.github/actions/ci-crates/Cargo.toml b/.github/actions/ci-crates/Cargo.toml index 61709583ad..f188a22ef2 100644 --- a/.github/actions/ci-crates/Cargo.toml +++ b/.github/actions/ci-crates/Cargo.toml @@ -12,10 +12,6 @@ publish = false name = "changed-crates" path = "src/bin/changed_crates.rs" -[[bin]] -name = "affected-crates" -path = "src/bin/affected_crates.rs" - [dependencies] ci-shared = { path = "../ci-shared" } anyhow = "1.0" @@ -24,3 +20,4 @@ log = "0.4" env_logger = "0.11" serde = { version = "1", features = ["derive"] } serde_json = "1" +cargo_metadata = "0.23.1" diff --git a/.github/actions/ci-crates/src/bin/affected_crates.rs b/.github/actions/ci-crates/src/bin/affected_crates.rs deleted file mode 100644 index 7f1b9f8782..0000000000 --- a/.github/actions/ci-crates/src/bin/affected_crates.rs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ -// SPDX-License-Identifier: Apache-2.0 - -//! Computes all crates affected (direct + transitive) by changes in a PR or push. -//! -//! Reads env vars following the GitHub Actions INPUT_* convention and writes -//! to $GITHUB_OUTPUT. -//! -//! Outputs: -//! affected_crates – JSON array of {name, version, path, manifest} -//! affected_crates_count – integer -//! has_changes – "true" if any crates are affected - -use anyhow::Result; -use ci_crates::git; -use ci_crates::workspace; -use ci_shared::crate_detection::{find_closest_cargo_toml, parse_crate_info, CrateInfo}; -use ci_shared::github_output::set_output; -use std::collections::HashSet; -use std::path::PathBuf; - -const BASE_DEFAULT: &str = "origin/main"; - -fn main() -> Result<()> { - env_logger::init(); - - let include_non_publishable = std::env::var("INPUT_INCLUDE_NON_PUBLISHABLE") - .unwrap_or_default() - .to_lowercase() - == "true"; - - let base_ref = std::env::var("INPUT_BASE_REF").unwrap_or(BASE_DEFAULT.to_string()); - log::info!("Using base ref: {base_ref}"); - - let changed_files = git::changed_files(&base_ref)?; - log::info!("Changed files: {:?}", changed_files); - - // TODO: Check heuristics when workspace manifest (Cargo.toml) or config.toml changed. This could indicate a - // change in: - // * Rust version. - // * Edition. - // * Profile. - // * Compilation flags. - - let meta = workspace::load()?; - let ws_names: HashSet = meta.members().iter().map(|p| p.name.clone()).collect(); - - let direct_crates = collect_changed_crates(&changed_files, include_non_publishable, &ws_names); - - if direct_crates.is_empty() { - return build_output(None) - } - - // Compute transitive affected set - let direct_names: Vec = direct_crates.iter().map(|c| c.name.clone()).collect(); - log::info!("Directly changed crates: {:?}", direct_names); - let affected_names = meta.affected_from(&direct_names); - log::info!("Affected crates (transitive): {:?}", affected_names); - - // Build affected crate info list - let affected_infos: Vec<&CrateInfo> = direct_crates - .iter() - .filter(|c| affected_names.contains(&c.name)) - .collect(); - - // Build CrateInfo for transitively-added crates (not in direct_crates) - let direct_names_set: HashSet<&String> = direct_names.iter().collect(); - let transitive_only: Vec = affected_names - .iter() - .filter(|n| !direct_names_set.contains(n)) - .cloned() - .collect(); - - // Look up transitive-only crates from workspace metadata - let mut all_infos: Vec = affected_infos - .iter() - .map(|c| crate_info_to_json(c)) - .collect(); - - for pkg in meta.members() { - if transitive_only.contains(&pkg.name) { - // pkg.manifest_path is the path to Cargo.toml - let manifest = PathBuf::from(&pkg.manifest_path); - if let Ok(info) = parse_crate_info(&manifest) { - all_infos.push(crate_info_to_json(&info)); - } - } - } - - - build_output(Some(all_infos)) -} - -fn collect_changed_crates( - changed_files: &[String], - include_non_publishable: bool, - ws_names: &HashSet, -) -> Vec { - let mut seen_manifests: HashSet = HashSet::new(); - let mut crates: Vec = Vec::new(); - - for file in changed_files { - let path = std::path::Path::new(file); - let Some(manifest) = find_closest_cargo_toml(path) else { - continue; - }; - if seen_manifests.contains(&manifest) { - continue; - } - seen_manifests.insert(manifest.clone()); - - match parse_crate_info(&manifest) { - Ok(info) => { - if !ws_names.contains(&info.name) { - log::debug!("Skipping {} (not in main workspace)", info.name); - continue; - } - if include_non_publishable || info.publish { - crates.push(info); - } - } - Err(e) => { - log::warn!("Skipping {}: {e}", manifest.display()); - } - } - } - - crates -} - -fn crate_info_to_json(c: &CrateInfo) -> serde_json::Value { - serde_json::json!({ - "name": c.name, - "version": c.version, - "path": c.path, - "manifest": c.manifest, - }) -} - -fn build_output(affected_crates: Option>) -> Result<()> { - - let (crates, len, has_changes): (String, String, String) = if let Some(crates) = affected_crates { - (serde_json::to_string(&crates).unwrap_or("[]".to_string()), crates.len().to_string(), "true".to_string()) - } else { - ("[]".to_string(), "0".to_string(), "false".to_string()) - }; - - if std::env::var("DEBUG").is_ok() { - log::info!("affected_crates: {:?}", crates); - log::info!("len: {:?}", len); - log::info!("has_changes: {:?}", len); - } else { - set_output("affected_crates", &crates)?; - set_output("affected_crates_count", &len)?; - set_output("has_changes", &has_changes)?; - } - Ok(()) -} diff --git a/.github/actions/ci-crates/src/bin/changed_crates.rs b/.github/actions/ci-crates/src/bin/changed_crates.rs index 62b8befcfe..9c709d59a9 100644 --- a/.github/actions/ci-crates/src/bin/changed_crates.rs +++ b/.github/actions/ci-crates/src/bin/changed_crates.rs @@ -1,111 +1,116 @@ // Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 -//! Detects which Rust crates have changed files in a PR or push. +//! Computes all crates affected (direct + transitive) by changes in a PR or push. //! //! Reads env vars following the GitHub Actions INPUT_* convention and writes //! to $GITHUB_OUTPUT. //! //! Outputs: -//! crates – JSON array of {name, version, path, manifest} -//! crates_count – integer count -//! base_ref – the base ref used for comparison +//! changed_crates - JSON array +//! affected_crates – JSON array of {name, version, path, manifest} +//! affected_crates_count – integer -use anyhow::Result; +use anyhow::{anyhow, Result}; +use cargo_metadata::Package; use ci_crates::git; -use ci_shared::crate_detection::{find_closest_cargo_toml, parse_crate_info, CrateInfo}; +use ci_crates::workspace; +use ci_shared::crate_detection::CrateInfo; use ci_shared::github_output::set_output; use std::collections::HashSet; -use std::path::PathBuf; fn main() -> Result<()> { env_logger::init(); + // Parse args + let args: Vec = std::env::args().collect(); + if args.len() < 2 { + return Err(anyhow!("A reference base needs to be passed")) + } - let include_non_publishable = std::env::var("INPUT_INCLUDE_NON_PUBLISHABLE") - .unwrap_or_default() - .to_lowercase() - == "true"; - - let input_base_ref = std::env::var("INPUT_BASE_REF").unwrap_or_default(); - let event_name = std::env::var("GITHUB_EVENT_NAME").unwrap_or_default(); - let pr_base_ref = std::env::var("GITHUB_BASE_REF").unwrap_or_default(); - - let base_ref = determine_base_ref(&input_base_ref, &event_name, &pr_base_ref)?; - - log::info!("Using base ref: {base_ref}"); - set_output("base_ref", &base_ref)?; - - let changed = git::changed_files(&base_ref)?; - log::info!("Changed files: {:?}", changed); - - let crates = collect_changed_crates(&changed, include_non_publishable); + let base_ref = &args[1]; + + let changed_files = git::changed_files(&base_ref)?; + log::info!("Changed files: {:?}", changed_files); - let json = serde_json::to_string(&crates)?; - log::info!("Changed crates: {json}"); + // TODO: Check heuristics when workspace manifest (Cargo.toml) or config.toml changed. This could indicate a + // change in: + // * Rust version. + // * Edition. + // * Profile. + // * Compilation flags. - set_output("crates", &json)?; - set_output("crates_count", &crates.len().to_string())?; + let workspace = workspace::load()?; + let changed_crates = collect_changed_crates(&changed_files, workspace.members()); - Ok(()) -} -fn determine_base_ref( - input_base_ref: &str, - event_name: &str, - pr_base_ref: &str, -) -> Result { - if !input_base_ref.is_empty() { - return Ok(input_base_ref.to_string()); + if changed_crates.is_empty() { + log::info!("Changed crates is empty"); + return build_output(None, None, base_ref) } - if event_name == "pull_request" { - let base = format!("origin/{pr_base_ref}"); - git::fetch_base(&base)?; - return Ok(base); - } + let seeds: Vec = changed_crates.iter().map(|c| c.name.clone()).collect(); - Ok("HEAD~1".to_string()) + let result = workspace.affected_from(&seeds); + + build_output(Some(changed_crates), Some(result.into_iter().collect()), base_ref) } -pub fn collect_changed_crates( +fn collect_changed_crates( changed_files: &[String], - include_non_publishable: bool, -) -> Vec { - let mut seen_manifests: HashSet = HashSet::new(); + members: &[Package], +) -> Vec { let mut crates: Vec = Vec::new(); + let mut crate_inventory: HashSet = HashSet::new(); for file in changed_files { - let path = std::path::Path::new(file); - let Some(manifest) = find_closest_cargo_toml(path) else { - continue; - }; - - if seen_manifests.contains(&manifest) { - continue; - } - seen_manifests.insert(manifest.clone()); - - match parse_crate_info(&manifest) { - Ok(info) => { - if include_non_publishable || info.publish { - crates.push(info); + for member in members { + if file.contains(member.name.as_str()) { + if crate_inventory.insert(member.name.to_string()) { + crates.push(CrateInfo { + name: member.name.as_str().to_string(), + version: format!("{}.{}.{}", member.version.major, member.version.minor, member.version.patch), + manifest: member.manifest_path.clone().into(), + path: member.manifest_path.parent().unwrap().into(), + publish: if let Some(publishable) = &member.publish { + !publishable.is_empty() + } else { + true + } + }); } } - Err(e) => { - log::warn!("Skipping {}: {e}", manifest.display()); - } } } crates - .into_iter() - .map(|c| { - serde_json::json!({ - "name": c.name, - "version": c.version, - "path": c.path, - "manifest": c.manifest, - }) - }) - .collect() +} + +fn build_output(changed_crates: Option>, affected_crates: Option>, base_ref: &str) -> Result<()> { + + let (changed, changed_len): (String, String) = if let Some(crates) = changed_crates { + (serde_json::to_string(&crates).unwrap_or("[]".to_string()), crates.len().to_string()) + } else { + ("[]".to_string(), "0".to_string()) + }; + + let (affected, affected_len): (String, String) = if let Some(crates) = affected_crates { + (serde_json::to_string(&crates).unwrap_or("[]".to_string()), crates.len().to_string()) + } else { + ("[]".to_string(), "0".to_string()) + }; + + if std::env::var("DEBUG").is_ok() { + log::info!("crates: {:?}", changed); + log::info!("crates_count: {:?}", changed_len); + log::info!("dependants: {:?}", affected); + log::info!("dependants_count: {:?}", affected_len); + log::info!("base_ref: {:?}", base_ref); + } else { + set_output("crates", &changed)?; + set_output("crates_count", &changed_len)?; + set_output("dependants", &affected)?; + set_output("has_changes", &affected_len)?; + set_output("base_ref", base_ref)?; + } + Ok(()) } diff --git a/.github/actions/ci-crates/src/git.rs b/.github/actions/ci-crates/src/git.rs index 6ccb0d7c75..d9a8b2b622 100644 --- a/.github/actions/ci-crates/src/git.rs +++ b/.github/actions/ci-crates/src/git.rs @@ -47,6 +47,7 @@ pub fn changed_files(base_ref: &str) -> Result> { .lines() .map(|l| l.to_string()) .filter(|l| !l.is_empty()) + .filter(|l| !l.contains(".github/")) .collect(); Ok(files) diff --git a/.github/actions/ci-crates/src/workspace.rs b/.github/actions/ci-crates/src/workspace.rs index 340eaa9c81..0a125637ef 100644 --- a/.github/actions/ci-crates/src/workspace.rs +++ b/.github/actions/ci-crates/src/workspace.rs @@ -1,110 +1,175 @@ // Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 -use anyhow::{Context, Result}; -use serde::Deserialize; +use anyhow::Result; +use cargo_metadata::{MetadataCommand, Package}; use std::collections::{HashMap, HashSet, VecDeque}; -use std::process::Command; - -/// A workspace member as returned by `cargo metadata`. -#[derive(Debug, Deserialize)] -pub struct Package { - pub name: String, - pub manifest_path: String, - pub dependencies: Vec, -} - -#[derive(Debug, Deserialize)] -pub struct Dependency { - pub name: String, -} - -#[derive(Debug, Deserialize)] -struct CargoMetadata { - packages: Vec, - workspace_members: Vec, -} /// Parsed workspace metadata with reverse-dependency index. pub struct WorkspaceMetadata { packages: Vec, + /// Maps each crate name to the list of workspace crates that depend on it. reverse_deps: HashMap>, } -pub fn load() -> Result { - let output = Command::new("cargo") - .args(["metadata", "--format-version=1", "--no-deps"]) - .output() - .context("Failed to run cargo metadata")?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr); - anyhow::bail!("cargo metadata failed: {stderr}"); +impl WorkspaceMetadata { + pub fn members(&self) -> &[Package] { + &self.packages + } + + pub fn affected_from(&self, seeds: &[String]) -> HashSet { + let mut visited: HashSet = HashSet::new(); + let mut queue: VecDeque = VecDeque::new(); + + for name in seeds { + if visited.insert(name.clone()) { + queue.push_back(name.clone()); + } + } + + while let Some(name) = queue.pop_front() { + if let Some(dependents) = self.reverse_deps.get(&name) { + for dep in dependents { + if visited.insert(dep.clone()) { + queue.push_back(dep.clone()); + } + } + } + } + + visited } +} - let meta: CargoMetadata = - serde_json::from_slice(&output.stdout).context("Failed to parse cargo metadata output")?; +pub fn load() -> Result { + let metadata = MetadataCommand::new().exec()?; - let ws_member_ids: HashSet<&str> = meta.workspace_members.iter().map(|s| s.as_str()).collect(); + let packages: Vec = metadata.workspace_packages().into_iter().cloned().collect(); - let ws_packages: Vec = meta - .packages - .into_iter() - .filter(|p| { - ws_member_ids - .iter() - .any(|id| id.starts_with(&format!("{} ", p.name))) - }) - .collect(); + let member_names: HashSet = packages.iter().map(|p| p.name.as_str().to_string()).collect(); - let ws_names: HashSet = ws_packages.iter().map(|p| p.name.clone()).collect(); let mut reverse_deps: HashMap> = HashMap::new(); - for pkg in &ws_packages { + for pkg in &packages { for dep in &pkg.dependencies { - if ws_names.contains(&dep.name) { + if member_names.contains(&dep.name) { reverse_deps .entry(dep.name.clone()) .or_default() - .push(pkg.name.clone()); + .push(pkg.name.as_str().to_string()); } } } Ok(WorkspaceMetadata { - packages: ws_packages, + packages, reverse_deps, }) } -impl WorkspaceMetadata { - pub fn members(&self) -> &[Package] { - &self.packages +#[cfg(test)] +mod tests { + use super::*; + + /// Build a `WorkspaceMetadata` with an empty package list and a custom + /// reverse-dep map expressed as `&[("crate", &["dependent", ...])]`. + fn make_meta(deps: &[(&str, &[&str])]) -> WorkspaceMetadata { + let reverse_deps = deps + .iter() + .map(|(k, vs)| { + ( + k.to_string(), + vs.iter().map(|s| s.to_string()).collect(), + ) + }) + .collect(); + WorkspaceMetadata { + packages: vec![], + reverse_deps, + } } - pub fn affected_from(&self, seeds: &[String]) -> Vec { - let mut visited: HashSet = HashSet::new(); - let mut queue: VecDeque = VecDeque::new(); + fn names(s: &[&str]) -> Vec { + s.iter().map(|s| s.to_string()).collect() + } - for seed in seeds { - if !visited.contains(seed) { - visited.insert(seed.clone()); - queue.push_back(seed.clone()); - } - } + fn set(s: &[&str]) -> HashSet { + s.iter().map(|s| s.to_string()).collect() + } - while let Some(current) = queue.pop_front() { - if let Some(dependents) = self.reverse_deps.get(¤t) { - for dep in dependents { - if !visited.contains(dep) { - visited.insert(dep.clone()); - queue.push_back(dep.clone()); - } - } - } - } + // --- affected_from --- + + #[test] + fn affected_from_empty_seeds_returns_empty() { + let meta = make_meta(&[]); + assert!(meta.affected_from(&[]).is_empty()); + } + + #[test] + fn affected_from_seed_with_no_dependents() { + let meta = make_meta(&[]); + assert_eq!(meta.affected_from(&names(&["a"])), set(&["a"])); + } + + #[test] + fn affected_from_direct_dependents() { + // b and c both depend on a + let meta = make_meta(&[("a", &["b", "c"])]); + assert_eq!(meta.affected_from(&names(&["a"])), set(&["a", "b", "c"])); + } + + #[test] + fn affected_from_transitive_chain() { + // a → b → c + let meta = make_meta(&[("a", &["b"]), ("b", &["c"])]); + assert_eq!(meta.affected_from(&names(&["a"])), set(&["a", "b", "c"])); + } + + #[test] + fn affected_from_diamond() { + // b and c depend on a; d depends on both b and c + let meta = make_meta(&[("a", &["b", "c"]), ("b", &["d"]), ("c", &["d"])]); + assert_eq!( + meta.affected_from(&names(&["a"])), + set(&["a", "b", "c", "d"]) + ); + } + + #[test] + fn affected_from_multiple_seeds() { + // independent chains: a → b, c → d + let meta = make_meta(&[("a", &["b"]), ("c", &["d"])]); + assert_eq!( + meta.affected_from(&names(&["a", "c"])), + set(&["a", "b", "c", "d"]) + ); + } + + #[test] + fn affected_from_duplicate_seeds_no_duplicates_in_result() { + let meta = make_meta(&[("a", &["b"])]); + assert_eq!( + meta.affected_from(&names(&["a", "a"])), + set(&["a", "b"]) + ); + } + + #[test] + fn affected_from_unknown_seed_returns_seed_only() { + let meta = make_meta(&[]); + assert_eq!( + meta.affected_from(&names(&["not-in-workspace"])), + set(&["not-in-workspace"]) + ); + } + + // --- load() integration --- - let mut result: Vec = visited.into_iter().collect(); - result.sort(); - result + #[test] + fn load_returns_non_empty_workspace() { + let meta = load().expect("load() should succeed against the real workspace"); + assert!( + !meta.members().is_empty(), + "expected at least one workspace member" + ); } } diff --git a/.github/actions/ci-shared/src/crate_detection.rs b/.github/actions/ci-shared/src/crate_detection.rs index 2c53ac84a5..e6cd6d88db 100644 --- a/.github/actions/ci-shared/src/crate_detection.rs +++ b/.github/actions/ci-shared/src/crate_detection.rs @@ -33,6 +33,7 @@ pub fn find_closest_cargo_toml(mut path: &Path) -> Option { loop { let cargo_path = path.join("Cargo.toml"); if cargo_path.exists() { + log::info!("Return {:?}", cargo_path); return Some(cargo_path); } From 34635e3ac150e63e53df60dc1752b0b6acf8bf75 Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 5 Mar 2026 14:46:30 +0100 Subject: [PATCH 03/26] remove depth --- .github/actions/changed-crates/action.yml | 6 ++++++ .github/actions/ci-crates/src/bin/changed_crates.rs | 8 ++++---- .github/actions/ci-crates/src/git.rs | 1 - 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/changed-crates/action.yml index 82c2d58e2d..e134069fe3 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/changed-crates/action.yml @@ -11,6 +11,12 @@ outputs: crates_count: description: 'Number of changed crates' value: ${{ steps.detect.outputs.crates_count }} + affected_crates: + description: 'Affected crates by the changes' + value: ${{ steps.detect.outputs.affected_crates }} + affected_crates_count: + description: 'Number of affected crates by the changes' + value: ${{ steps.detect.outputs.affected_crates_count }} base_ref: description: 'The base ref used for comparison' value: ${{ steps.detect.outputs.base_ref }} diff --git a/.github/actions/ci-crates/src/bin/changed_crates.rs b/.github/actions/ci-crates/src/bin/changed_crates.rs index 9c709d59a9..1fbd6a66ef 100644 --- a/.github/actions/ci-crates/src/bin/changed_crates.rs +++ b/.github/actions/ci-crates/src/bin/changed_crates.rs @@ -102,14 +102,14 @@ fn build_output(changed_crates: Option>, affected_crates: Option< if std::env::var("DEBUG").is_ok() { log::info!("crates: {:?}", changed); log::info!("crates_count: {:?}", changed_len); - log::info!("dependants: {:?}", affected); - log::info!("dependants_count: {:?}", affected_len); + log::info!("affected_crates: {:?}", affected); + log::info!("affected_crates_count: {:?}", affected_len); log::info!("base_ref: {:?}", base_ref); } else { set_output("crates", &changed)?; set_output("crates_count", &changed_len)?; - set_output("dependants", &affected)?; - set_output("has_changes", &affected_len)?; + set_output("affected_crates", &affected)?; + set_output("affected_crates_count", &affected_len)?; set_output("base_ref", base_ref)?; } Ok(()) diff --git a/.github/actions/ci-crates/src/git.rs b/.github/actions/ci-crates/src/git.rs index d9a8b2b622..205b0f3d72 100644 --- a/.github/actions/ci-crates/src/git.rs +++ b/.github/actions/ci-crates/src/git.rs @@ -13,7 +13,6 @@ pub fn fetch_base(base_ref: &str) -> Result<()> { let status = Command::new("git") .args([ "fetch", - "--depth=1", "origin", &format!("{branch}:refs/remotes/origin/{branch}"), ]) From c9785c8ec8aac962ec871fbd6c530443084dd7f2 Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 5 Mar 2026 15:11:44 +0100 Subject: [PATCH 04/26] Fix call to action --- .github/workflows/fuzz.yml | 2 +- .github/workflows/lint.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index c8d2f2a293..37ca8d4b33 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -15,7 +15,7 @@ jobs: with: fetch-depth: 0 - id: scope - uses: ./.github/actions/affected-crates + uses: ./.github/actions/changed-crates run-fuzz: needs: [compute-scope] diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d01ef9b793..b060459b68 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: with: fetch-depth: 0 - id: scope - uses: ./.github/actions/affected-crates + uses: ./.github/actions/changed-crates actionlint: runs-on: ubuntu-latest @@ -71,7 +71,7 @@ jobs: export AWS_LC_FIPS_SYS_NO_ASM=1 fi - AFFECTED_CRATES_ARGS=$(echo '${{ needs.compute-scope.outputs.affected_crates }}' | jq -r '[.[].name] | map("-p " + .) | join(" ")') + AFFECTED_CRATES_ARGS=$(echo '${{ needs.compute-scope.outputs.crates }}' | jq -r '[.[].name] | map("-p " + .) | join(" ")') cargo clippy $AFFECTED_CRATES_ARGS --all-targets --all-features -- -D warnings licensecheck: From 8fd143e0c3219e6f320971c9e298a351e884df2b Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 5 Mar 2026 15:20:13 +0100 Subject: [PATCH 05/26] compile action --- .github/actions/changed-crates/action.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/changed-crates/action.yml index e134069fe3..988e61ac4f 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/changed-crates/action.yml @@ -24,7 +24,24 @@ outputs: runs: using: 'composite' steps: - - id: detect + - name: Set up Rust + shell: bash + run: rustup install stable && rustup default stable + + - name: Fetch all branches + shell: bash + run: | + git fetch --all + echo "Available branches:" + git branch -a + + - name: Build change reporter + shell: bash + run: | + cd ${{ github.action_path }}/.. + cargo build --release -p ci-crates + + - name: Run change reporter shell: bash env: EVENT_NAME: ${{ github.event_name }} From 344aa1874aeb17a229d983d1e985b4e1890c6933 Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 5 Mar 2026 15:37:34 +0100 Subject: [PATCH 06/26] Restore workflows. --- .github/workflows/fuzz.yml | 19 +------------------ .github/workflows/lint.yml | 23 +++-------------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 37ca8d4b33..a44010700f 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,29 +1,12 @@ name: Fuzz test on: - pull_request: push: - branches: [main, 'julio/rd-week-*'] jobs: - compute-scope: - runs-on: ubuntu-latest - outputs: - run_full: ${{ steps.scope.outputs.run_full }} - has_changes: ${{ steps.scope.outputs.has_changes }} - affected_fuzz_dirs: ${{ steps.scope.outputs.affected_fuzz_dirs }} - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 - with: - fetch-depth: 0 - - id: scope - uses: ./.github/actions/changed-crates - run-fuzz: - needs: [compute-scope] - if: needs.compute-scope.outputs.affected_fuzz_dirs != '[]' runs-on: ubuntu-latest strategy: matrix: - directory: ${{ fromJSON(needs.compute-scope.outputs.affected_fuzz_dirs) }} + directory: [libdd-alloc, libdd-profiling, libdd-common-ffi, libdd-trace-utils] env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b060459b68..b33af83d94 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,24 +1,10 @@ name: Lint on: - pull_request: push: - branches: [main, 'julio/rd-week-*'] env: CARGO_TERM_COLOR: always jobs: - compute-scope: - runs-on: ubuntu-latest - outputs: - has_changes: ${{ steps.scope.outputs.has_changes }} - affected_crates: ${{ steps.scope.outputs.affected_crates }} - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 - with: - fetch-depth: 0 - - id: scope - uses: ./.github/actions/changed-crates - actionlint: runs-on: ubuntu-latest steps: @@ -46,8 +32,6 @@ jobs: - run: cargo fmt --all -- --check clippy: name: "clippy #${{ matrix.platform }} ${{ matrix.rust_version }}" - needs: [compute-scope] - if: needs.compute-scope.outputs.has_changes == 'true' runs-on: ${{ matrix.platform }} strategy: fail-fast: false @@ -70,9 +54,8 @@ jobs: if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then export AWS_LC_FIPS_SYS_NO_ASM=1 fi - - AFFECTED_CRATES_ARGS=$(echo '${{ needs.compute-scope.outputs.crates }}' | jq -r '[.[].name] | map("-p " + .) | join(" ")') - cargo clippy $AFFECTED_CRATES_ARGS --all-targets --all-features -- -D warnings + # shellcheck disable=SC2046 + cargo clippy --workspace --all-targets --all-features -- -D warnings licensecheck: runs-on: ubuntu-latest @@ -94,7 +77,7 @@ jobs: # cargo-bundle-licenses is "unsure" or "semi" confident. This means that # when the found license was compared to a template license it was found to # have diverged in more than a few words. You should verify that the licence - # text is in fact correct in these cases. + # text is in fact correct in these cases. license-3rdparty: runs-on: ubuntu-latest name: "Valid LICENSE-3rdparty.yml" From 32182b8dd4a40406b95bb055a321257be2c87e07 Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 5 Mar 2026 15:44:44 +0100 Subject: [PATCH 07/26] Modify fuzz to just run the tests if the crates just changed --- .github/workflows/fuzz.yml | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index a44010700f..1154c27db4 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,12 +1,45 @@ name: Fuzz test on: push: + pull_request: jobs: + setup: + runs-on: ubuntu-latest + outputs: + fuzz-dirs: ${{ steps.set-dirs.outputs.fuzz-dirs }} + fuzz-dirs-count: ${{ steps.set-dirs.outputs.fuzz-dirs-count }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + fetch-depth: 0 + - name: Get changed crates + if: ${{ github.event_name == 'pull_request' }} + id: changed-crates + uses: ./.github/actions/changed-crates + - name: Set fuzz directories + id: set-dirs + env: + CHANGED_CRATES: ${{ steps.changed-crates.outputs.crates }} + run: | + ALL_FUZZ='["libdd-alloc", "libdd-profiling", "libdd-common-ffi", "libdd-trace-utils"]' + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + FILTERED=$(echo "$CHANGED_CRATES" | jq --argjson fuzz "$ALL_FUZZ" \ + '[.[] | .path | split("/") | last | . as $dir | if ($fuzz | index($dir) != null) then $dir else empty end]') + COUNT=$(echo "$FILTERED" | jq 'length') + else + FILTERED="$ALL_FUZZ" + COUNT=$(echo "$ALL_FUZZ" | jq 'length') + fi + echo "fuzz-dirs=$FILTERED" >> $GITHUB_OUTPUT + echo "fuzz-dirs-count=$COUNT" >> $GITHUB_OUTPUT + run-fuzz: + needs: setup + if: needs.setup.outputs.fuzz-dirs-count != '0' runs-on: ubuntu-latest strategy: matrix: - directory: [libdd-alloc, libdd-profiling, libdd-common-ffi, libdd-trace-utils] + directory: ${{ fromJson(needs.setup.outputs.fuzz-dirs) }} env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 From a20def1ae7c37c1258cc18f8fbb3b9f51220c497 Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 5 Mar 2026 16:01:42 +0100 Subject: [PATCH 08/26] Modify lint workflow --- .github/workflows/lint.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b33af83d94..709984a629 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,11 +1,37 @@ name: Lint on: push: + pull_request: env: CARGO_TERM_COLOR: always jobs: + setup: + runs-on: ubuntu-latest + outputs: + crates-count: ${{ steps.set-count.outputs.crates-count }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + fetch-depth: 0 + - name: Get changed crates + if: ${{ github.event_name == 'pull_request' }} + id: changed-crates + uses: ./.github/actions/changed-crates + - name: Set crates count + id: set-count + env: + CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "crates-count=$CRATES_COUNT" >> $GITHUB_OUTPUT + else + echo "crates-count=1" >> $GITHUB_OUTPUT + fi + actionlint: + needs: setup + if: needs.setup.outputs.crates-count != '0' runs-on: ubuntu-latest steps: - name: Checkout sources @@ -15,6 +41,8 @@ jobs: with: shellcheck_opts: '-e SC2086' rustfmt: + needs: setup + if: needs.setup.outputs.crates-count != '0' runs-on: ubuntu-latest env: CARGO_TERM_COLOR: always @@ -31,6 +59,8 @@ jobs: cache-bin: true # cache the ~/.cargo/bin directory - run: cargo fmt --all -- --check clippy: + needs: setup + if: needs.setup.outputs.crates-count != '0' name: "clippy #${{ matrix.platform }} ${{ matrix.rust_version }}" runs-on: ${{ matrix.platform }} strategy: @@ -58,6 +88,8 @@ jobs: cargo clippy --workspace --all-targets --all-features -- -D warnings licensecheck: + needs: setup + if: needs.setup.outputs.crates-count != '0' runs-on: ubuntu-latest name: "Presence of licence headers" steps: @@ -79,6 +111,8 @@ jobs: # have diverged in more than a few words. You should verify that the licence # text is in fact correct in these cases. license-3rdparty: + needs: setup + if: needs.setup.outputs.crates-count != '0' runs-on: ubuntu-latest name: "Valid LICENSE-3rdparty.yml" steps: From 76262ad192d9a85600fa09c088a909d95983c18a Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 5 Mar 2026 16:20:47 +0100 Subject: [PATCH 09/26] restore id --- .github/actions/changed-crates/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/changed-crates/action.yml index 988e61ac4f..4977a30f8f 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/changed-crates/action.yml @@ -42,6 +42,7 @@ runs: cargo build --release -p ci-crates - name: Run change reporter + id: detect shell: bash env: EVENT_NAME: ${{ github.event_name }} From b0ec864cd8cc8ed4585aafb6df63b220d1b1f5cb Mon Sep 17 00:00:00 2001 From: Igor Unanua Date: Thu, 5 Mar 2026 16:41:22 +0100 Subject: [PATCH 10/26] remove if --- .github/workflows/fuzz.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 1154c27db4..aef69bc829 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -13,7 +13,6 @@ jobs: with: fetch-depth: 0 - name: Get changed crates - if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - name: Set fuzz directories From 847325bfc7e560af7675941b1418d21f878f3999 Mon Sep 17 00:00:00 2001 From: Igor Unanua Date: Thu, 5 Mar 2026 17:15:03 +0100 Subject: [PATCH 11/26] triggers and log --- .github/actions/changed-crates/action.yml | 2 +- .github/workflows/fuzz.yml | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/changed-crates/action.yml index 4977a30f8f..d91f1dcd16 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/changed-crates/action.yml @@ -48,4 +48,4 @@ runs: EVENT_NAME: ${{ github.event_name }} PR_BASE_REF: ${{ github.base_ref }} run: | - ${{ github.action_path }}/../target/release/changed-crates $PR_BASE_REF + RUST_LOG=debug ${{ github.action_path }}/../target/release/changed-crates $PR_BASE_REF diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index aef69bc829..5dd933f778 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,7 +1,9 @@ name: Fuzz test on: - push: pull_request: + push: + branches: + - main jobs: setup: runs-on: ubuntu-latest @@ -13,6 +15,7 @@ jobs: with: fetch-depth: 0 - name: Get changed crates + if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - name: Set fuzz directories From 150a5bf8edab35c12bb7310cca41d1a863f30b33 Mon Sep 17 00:00:00 2001 From: Igor Unanua Date: Thu, 5 Mar 2026 17:25:16 +0100 Subject: [PATCH 12/26] call fetch_base --- .../ci-crates/src/bin/changed_crates.rs | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/.github/actions/ci-crates/src/bin/changed_crates.rs b/.github/actions/ci-crates/src/bin/changed_crates.rs index 1fbd6a66ef..098a729c39 100644 --- a/.github/actions/ci-crates/src/bin/changed_crates.rs +++ b/.github/actions/ci-crates/src/bin/changed_crates.rs @@ -24,11 +24,13 @@ fn main() -> Result<()> { // Parse args let args: Vec = std::env::args().collect(); if args.len() < 2 { - return Err(anyhow!("A reference base needs to be passed")) + return Err(anyhow!("A reference base needs to be passed")); } let base_ref = &args[1]; - + + git::fetch_base(&base_ref)?; + let changed_files = git::changed_files(&base_ref)?; log::info!("Changed files: {:?}", changed_files); @@ -42,23 +44,23 @@ fn main() -> Result<()> { let workspace = workspace::load()?; let changed_crates = collect_changed_crates(&changed_files, workspace.members()); - if changed_crates.is_empty() { log::info!("Changed crates is empty"); - return build_output(None, None, base_ref) + return build_output(None, None, base_ref); } let seeds: Vec = changed_crates.iter().map(|c| c.name.clone()).collect(); let result = workspace.affected_from(&seeds); - build_output(Some(changed_crates), Some(result.into_iter().collect()), base_ref) + build_output( + Some(changed_crates), + Some(result.into_iter().collect()), + base_ref, + ) } -fn collect_changed_crates( - changed_files: &[String], - members: &[Package], -) -> Vec { +fn collect_changed_crates(changed_files: &[String], members: &[Package]) -> Vec { let mut crates: Vec = Vec::new(); let mut crate_inventory: HashSet = HashSet::new(); @@ -66,16 +68,19 @@ fn collect_changed_crates( for member in members { if file.contains(member.name.as_str()) { if crate_inventory.insert(member.name.to_string()) { - crates.push(CrateInfo { + crates.push(CrateInfo { name: member.name.as_str().to_string(), - version: format!("{}.{}.{}", member.version.major, member.version.minor, member.version.patch), + version: format!( + "{}.{}.{}", + member.version.major, member.version.minor, member.version.patch + ), manifest: member.manifest_path.clone().into(), path: member.manifest_path.parent().unwrap().into(), publish: if let Some(publishable) = &member.publish { !publishable.is_empty() } else { true - } + }, }); } } @@ -85,16 +90,25 @@ fn collect_changed_crates( crates } -fn build_output(changed_crates: Option>, affected_crates: Option>, base_ref: &str) -> Result<()> { - +fn build_output( + changed_crates: Option>, + affected_crates: Option>, + base_ref: &str, +) -> Result<()> { let (changed, changed_len): (String, String) = if let Some(crates) = changed_crates { - (serde_json::to_string(&crates).unwrap_or("[]".to_string()), crates.len().to_string()) + ( + serde_json::to_string(&crates).unwrap_or("[]".to_string()), + crates.len().to_string(), + ) } else { ("[]".to_string(), "0".to_string()) }; let (affected, affected_len): (String, String) = if let Some(crates) = affected_crates { - (serde_json::to_string(&crates).unwrap_or("[]".to_string()), crates.len().to_string()) + ( + serde_json::to_string(&crates).unwrap_or("[]".to_string()), + crates.len().to_string(), + ) } else { ("[]".to_string(), "0".to_string()) }; From b0048f8f26979f1acdf78f4e7069808014187d60 Mon Sep 17 00:00:00 2001 From: Igor Unanua Date: Thu, 5 Mar 2026 17:55:23 +0100 Subject: [PATCH 13/26] Change workflow triggers --- .github/workflows/lint.yml | 4 +++- .github/workflows/miri.yml | 4 +++- .github/workflows/test.yml | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 709984a629..de2e5d0a5b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,7 +1,9 @@ name: Lint on: - push: pull_request: + push: + branches: + - main env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml index ddb8bdbe69..5c631d23fe 100644 --- a/.github/workflows/miri.yml +++ b/.github/workflows/miri.yml @@ -1,7 +1,9 @@ name: Miri test on: + pull_request: push: - + branches: + - main jobs: run-miri: runs-on: ubuntu-latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 258cefff39..3dd6f23e3c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,9 @@ name: Test -on: [push] +on: + pull_request: + push: + branches: + - main env: CARGO_TERM_COLOR: always RUST_VERSION: 1.84.1 From e784a9b2d97faff7e65aed6aef07a5f30bf4873b Mon Sep 17 00:00:00 2001 From: Julio Date: Fri, 6 Mar 2026 09:35:08 +0100 Subject: [PATCH 14/26] Fix base reference name --- .../actions/ci-crates/src/bin/changed_crates.rs | 6 +++--- .github/actions/ci-crates/src/git.rs | 14 ++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/actions/ci-crates/src/bin/changed_crates.rs b/.github/actions/ci-crates/src/bin/changed_crates.rs index 098a729c39..0e82e85f00 100644 --- a/.github/actions/ci-crates/src/bin/changed_crates.rs +++ b/.github/actions/ci-crates/src/bin/changed_crates.rs @@ -27,7 +27,7 @@ fn main() -> Result<()> { return Err(anyhow!("A reference base needs to be passed")); } - let base_ref = &args[1]; + let base_ref = args[1].strip_prefix("origin/").unwrap_or(&args[1]).to_string(); git::fetch_base(&base_ref)?; @@ -46,7 +46,7 @@ fn main() -> Result<()> { if changed_crates.is_empty() { log::info!("Changed crates is empty"); - return build_output(None, None, base_ref); + return build_output(None, None, &base_ref); } let seeds: Vec = changed_crates.iter().map(|c| c.name.clone()).collect(); @@ -56,7 +56,7 @@ fn main() -> Result<()> { build_output( Some(changed_crates), Some(result.into_iter().collect()), - base_ref, + &base_ref, ) } diff --git a/.github/actions/ci-crates/src/git.rs b/.github/actions/ci-crates/src/git.rs index 205b0f3d72..2642dcc416 100644 --- a/.github/actions/ci-crates/src/git.rs +++ b/.github/actions/ci-crates/src/git.rs @@ -6,15 +6,13 @@ use std::process::Command; /// Run `git fetch --depth=1 origin ` to ensure the base ref is available locally. pub fn fetch_base(base_ref: &str) -> Result<()> { - // Strip "origin/" prefix if present — we pass it to `git fetch origin ` - let branch = base_ref.strip_prefix("origin/").unwrap_or(base_ref); - log::info!("Fetching base branch: {branch}"); + log::info!("Fetching base branch: {base_ref}"); let status = Command::new("git") .args([ "fetch", "origin", - &format!("{branch}:refs/remotes/origin/{branch}"), + &format!("{base_ref}:refs/remotes/origin/{base_ref}"), ]) .status() .context("Failed to run git fetch")?; @@ -27,18 +25,18 @@ pub fn fetch_base(base_ref: &str) -> Result<()> { Ok(()) } -/// Return the list of files changed between `...HEAD` (three-dot diff). +/// Return the list of files changed between `origin/...HEAD` (three-dot diff). /// -/// Uses `git diff --name-only ...HEAD`. +/// Uses `git diff --name-only origin/...HEAD`. pub fn changed_files(base_ref: &str) -> Result> { let output = Command::new("git") - .args(["diff", "--name-only", &format!("{base_ref}...HEAD")]) + .args(["diff", "--name-only", &format!("origin/{base_ref}...HEAD")]) .output() .context("Failed to run git diff")?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - bail!("git diff failed against {base_ref}: {stderr}"); + bail!("git diff failed against origin/{base_ref}: {stderr}"); } let stdout = String::from_utf8_lossy(&output.stdout); From 97e6af2912ec11964bafd6ca4e7ac16f17f4e830 Mon Sep 17 00:00:00 2001 From: Julio Date: Fri, 6 Mar 2026 15:07:35 +0100 Subject: [PATCH 15/26] split test and make ffi dynamic --- .github/workflows/test-ffi.yml | 229 +++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 176 +------------------------ 2 files changed, 233 insertions(+), 172 deletions(-) create mode 100644 .github/workflows/test-ffi.yml diff --git a/.github/workflows/test-ffi.yml b/.github/workflows/test-ffi.yml new file mode 100644 index 0000000000..1c53574004 --- /dev/null +++ b/.github/workflows/test-ffi.yml @@ -0,0 +1,229 @@ +name: Test FFI +on: + pull_request: + push: + branches: + - main +env: + CARGO_TERM_COLOR: always + RUST_VERSION: 1.84.1 + +jobs: + setup: + runs-on: ubuntu-latest + outputs: + packages: ${{ steps.set-packages.outputs.packages }} + packages-count: ${{ steps.set-packages.outputs.packages-count }} + crates-json: ${{ steps.set-packages.outputs.crates-json }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + fetch-depth: 0 + - name: Get changed crates + if: ${{ github.event_name == 'pull_request' }} + id: changed-crates + uses: ./.github/actions/changed-crates + - name: Set FFI packages + id: set-packages + env: + CHANGED_CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} + AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + COUNT="1" + PACKAGES="" + CRATES_JSON="" + elif [[ "$CHANGED_CRATES_COUNT" == "0" ]]; then + COUNT="0" + PACKAGES="" + CRATES_JSON="" + else + FFI_CRATES=$(echo "$AFFECTED_CRATES" | jq '[.[] | select(endswith("-ffi"))]') + COUNT=$(echo "$FFI_CRATES" | jq 'length') + PACKAGES=$(echo "$FFI_CRATES" | jq -r 'map("-p " + .) | join(" ")') + CRATES_JSON="$FFI_CRATES" + fi + echo "packages-count=$COUNT" >> $GITHUB_OUTPUT + echo "packages=$PACKAGES" >> $GITHUB_OUTPUT + { + echo "crates-json<> $GITHUB_OUTPUT + + ffi: + name: "FFI #${{ matrix.platform }} ${{ matrix.rust_version }}" + needs: setup + if: needs.setup.outputs.packages-count != '0' + runs-on: ${{ matrix.platform }} + env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + strategy: + matrix: + platform: [windows-latest, ubuntu-latest, macos-15] + rust_version: [""] + include: + - platform: "ubuntu-latest" + rust_version: "${RUST_VERSION}" + - platform: "ubuntu-latest" + flags: "-C relocation-model=pic" + - platform: "macos-15" + flags: "-C relocation-model=pic" + - platform: "windows-latest" + flags: "-C target-feature=+crt-static" + steps: + - name: Checkout sources + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + - name: Setup output dir + shell: bash + run: | + WORKSPACE_PATH=${{ github.workspace }} + if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then + WORKSPACE_PATH=$(cygpath -ua '${{ github.workspace }}') + fi + echo "LIBDD_OUTPUT_FOLDER=$WORKSPACE_PATH/artifacts" >> $GITHUB_ENV + - name: Free Disk Space (Ubuntu only) + if: runner.os == 'Linux' && matrix.platform == 'ubuntu-latest' + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 1.3.1 + with: + tool-cache: false + android: true + dotnet: true + haskell: true + large-packages: false + docker-images: false + swap-storage: true + - name: Install Rust ${{ matrix.rust_version }} + if: matrix.rust_version != '' + run: rustup install ${{ matrix.rust_version }} && rustup default ${{ matrix.rust_version }} + + - id: rust-version + # On Windows run happens in a PowerShell, so start bash explicitly + run: bash -c 'echo "version=$(rustc --version)" >> $GITHUB_OUTPUT' + + - name: Cache [rust] + uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # 2.8.1 + env: + RUSTFLAGS: "${{ matrix.flags }}" + with: + cache-targets: true # cache build artifacts + cache-bin: true # cache the ~/.cargo/bin directory + - name: "Generate profiling FFI" + shell: bash + env: + RUSTFLAGS: "${{ matrix.flags }}" + run: | + cargo run --bin release --release -- --out $LIBDD_OUTPUT_FOLDER + - name: 'Publish libdatadog' + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # 4.6.1 + # Only upload the artifacts built with the default Rust version + if: (success() || failure()) && matrix.rust_version == '' + with: + if-no-files-found: error + name: libdatadog.${{ matrix.platform }} + path: ${{ github.workspace }}/artifacts + retention-days: 1 + - name: "(Windows) Test building Profiling C bindings - dynamic link vc runtime" + if: matrix.platform == 'windows-latest' + shell: bash + run: | + set -e + rm -rf examples/ffi/build_dll + mkdir examples/ffi/build_dll + cd examples/ffi/build_dll + cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER -DVCRUNTIME_LINK_TYPE=DLL + cmake --build . + - name: "(Windows) Test building Profiling C bindings - static link vc runtime" + if: matrix.platform == 'windows-latest' + shell: bash + run: | + set -e + rm -rf examples/ffi/build_static + mkdir examples/ffi/build_static + cd examples/ffi/build_static + cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER -DVCRUNTIME_LINK_TYPE=STATIC + cmake --build . + - name: "Test building Profiling C bindings" + shell: bash + if: matrix.platform != 'windows-latest' + run: | + set -e + mkdir examples/ffi/build + cd examples/ffi/build + # Add BUILD_SYMBOLIZER variable only for Linux platforms + if [[ "${{ matrix.platform }}" == "ubuntu-latest" ]]; then + cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER -DBUILD_SYMBOLIZER=true + else + cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER + fi + cmake --build . + - name: "Run FFI examples" + shell: bash + if: matrix.platform != 'windows-latest' + run: | + cargo ffi-test --skip-build + - name: "(Windows) Run FFI examples" + shell: bash + if: matrix.platform == 'windows-latest' + run: | + cargo ffi-test + - name: "Test building CXX bindings - Crashinfo (Unix)" + shell: bash + if: matrix.platform != 'windows-latest' + run: | + set -e + cd examples/cxx + ./build-and-run-crashinfo.sh + - name: "Test building CXX bindings - Profiling (Unix)" + shell: bash + if: matrix.platform != 'windows-latest' + run: | + set -e + cd examples/cxx + ./build-profiling.sh + - name: "Setup MSVC (Windows)" + if: matrix.platform == 'windows-latest' + uses: ilammy/msvc-dev-cmd@v1 + - name: "Test building CXX bindings - Crashinfo (Windows)" + shell: pwsh + if: matrix.platform == 'windows-latest' + run: | + cd examples/cxx + .\build-and-run-crashinfo.ps1 + - name: "Test building CXX bindings - Profiling (Windows)" + shell: pwsh + if: matrix.platform == 'windows-latest' + run: | + cd examples/cxx + .\build-profiling.ps1 + + ffi_bake: + strategy: + matrix: + target: [alpine-build] # debian-build-aarch64 is oom killed at the moment + name: "FFI ${{ matrix.target }} via docker bake" + needs: setup + if: needs.setup.outputs.packages-count != '0' + concurrency: + group: ci-${{ github.ref }}-${{ matrix.target }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + runs-on: + labels: ubuntu-latest-16-cores + group: APM Larger Runners + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # 3.10.0 + with: + buildkitd-config: .github/buildkitd-16-cores.toml + - name: Build and Generate FFI + uses: docker/bake-action@4ba453fbc2db7735392b93edf935aaf9b1e8f747 # 6.5.0 + with: + targets: ${{ matrix.target }} + # Caching is useful, when it works. We are routinely hanging, maybe this: + # https://github.com/docker/buildx/issues/537 + #set: | + # *.cache-from=type=gha,scope=${{ matrix.target }} + # *.cache-to=type=gha,mode=max,scope=${{ matrix.target }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3dd6f23e3c..b953ad9b37 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,10 @@ name: Test on: pull_request: + types: ['opened', 'edited', 'reopened', 'synchronize'] + branches-ignore: + - "v[0-9]+.[0-9]+.[0-9]+.[0-9]+" + - release push: branches: - main @@ -137,151 +141,6 @@ jobs: env: DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} - ffi: - name: "FFI #${{ matrix.platform }} ${{ matrix.rust_version }}" - runs-on: ${{ matrix.platform }} - env: - CARGO_TERM_COLOR: always - CARGO_INCREMENTAL: 0 - strategy: - matrix: - platform: [windows-latest, ubuntu-latest, macos-15] - rust_version: [""] - include: - - platform: "ubuntu-latest" - rust_version: "${RUST_VERSION}" - - platform: "ubuntu-latest" - flags: "-C relocation-model=pic" - - platform: "macos-15" - flags: "-C relocation-model=pic" - - platform: "windows-latest" - flags: "-C target-feature=+crt-static" - steps: - - name: Checkout sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 - - name: Setup output dir - shell: bash - run: | - WORKSPACE_PATH=${{ github.workspace }} - if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then - WORKSPACE_PATH=$(cygpath -ua '${{ github.workspace }}') - fi - echo "LIBDD_OUTPUT_FOLDER=$WORKSPACE_PATH/artifacts" >> $GITHUB_ENV - - name: Free Disk Space (Ubuntu only) - if: runner.os == 'Linux' && matrix.platform == 'ubuntu-latest' - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 1.3.1 - with: - tool-cache: false - android: true - dotnet: true - haskell: true - large-packages: false - docker-images: false - swap-storage: true - - name: Install Rust ${{ matrix.rust_version }} - if: matrix.rust_version != '' - run: rustup install ${{ matrix.rust_version }} && rustup default ${{ matrix.rust_version }} - - - id: rust-version - # On Windows run happens in a PowerShell, so start bash explicitly - run: bash -c 'echo "version=$(rustc --version)" >> $GITHUB_OUTPUT' - - - name: Cache [rust] - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # 2.8.1 - env: - RUSTFLAGS: "${{ matrix.flags }}" - with: - cache-targets: true # cache build artifacts - cache-bin: true # cache the ~/.cargo/bin directory - - name: "Generate profiling FFI" - shell: bash - env: - RUSTFLAGS: "${{ matrix.flags }}" - run: | - cargo run --bin release --release -- --out $LIBDD_OUTPUT_FOLDER - - name: 'Publish libdatadog' - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # 4.6.1 - # Only upload the artifacts built with the default Rust version - if: (success() || failure()) && matrix.rust_version == '' - with: - if-no-files-found: error - name: libdatadog.${{ matrix.platform }} - path: ${{ github.workspace }}/artifacts - retention-days: 1 - - name: "(Windows) Test building Profiling C bindings - dynamic link vc runtime" - if: matrix.platform == 'windows-latest' - shell: bash - run: | - set -e - rm -rf examples/ffi/build_dll - mkdir examples/ffi/build_dll - cd examples/ffi/build_dll - cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER -DVCRUNTIME_LINK_TYPE=DLL - cmake --build . - - name: "(Windows) Test building Profiling C bindings - static link vc runtime" - if: matrix.platform == 'windows-latest' - shell: bash - run: | - set -e - rm -rf examples/ffi/build_static - mkdir examples/ffi/build_static - cd examples/ffi/build_static - cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER -DVCRUNTIME_LINK_TYPE=STATIC - cmake --build . - - name: "Test building Profiling C bindings" - shell: bash - if: matrix.platform != 'windows-latest' - run: | - set -e - mkdir examples/ffi/build - cd examples/ffi/build - # Add BUILD_SYMBOLIZER variable only for Linux platforms - if [[ "${{ matrix.platform }}" == "ubuntu-latest" ]]; then - cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER -DBUILD_SYMBOLIZER=true - else - cmake -S .. -DDatadog_ROOT=$LIBDD_OUTPUT_FOLDER - fi - cmake --build . - - name: "Run FFI examples" - shell: bash - if: matrix.platform != 'windows-latest' - run: | - cargo ffi-test --skip-build - - name: "(Windows) Run FFI examples" - shell: bash - if: matrix.platform == 'windows-latest' - run: | - cargo ffi-test - - name: "Test building CXX bindings - Crashinfo (Unix)" - shell: bash - if: matrix.platform != 'windows-latest' - run: | - set -e - cd examples/cxx - ./build-and-run-crashinfo.sh - - name: "Test building CXX bindings - Profiling (Unix)" - shell: bash - if: matrix.platform != 'windows-latest' - run: | - set -e - cd examples/cxx - ./build-profiling.sh - - name: "Setup MSVC (Windows)" - if: matrix.platform == 'windows-latest' - uses: ilammy/msvc-dev-cmd@v1 - - name: "Test building CXX bindings - Crashinfo (Windows)" - shell: pwsh - if: matrix.platform == 'windows-latest' - run: | - cd examples/cxx - .\build-and-run-crashinfo.ps1 - - name: "Test building CXX bindings - Profiling (Windows)" - shell: pwsh - if: matrix.platform == 'windows-latest' - run: | - cd examples/cxx - .\build-profiling.ps1 - cross-centos7: name: build and test using cross - on centos7 runs-on: ubuntu-latest @@ -311,30 +170,3 @@ jobs: - run: cross test --workspace --features libdd-crashtracker/generate-unit-test-files --target x86_64-unknown-linux-gnu --exclude builder -- --skip "::single_threaded_tests::" --skip "tracing_integration_tests::" - run: cross test --workspace --features libdd-crashtracker/generate-unit-test-files --target x86_64-unknown-linux-gnu --exclude builder --exclude bin_tests -- --skip "::tests::" --skip "::api_tests::" --test-threads 1 --skip "tracing_integration_tests::" - ffi_bake: - strategy: - matrix: - target: [alpine-build] # debian-build-aarch64 is oom killed at the moment - name: "FFI ${{ matrix.target }} via docker bake" - concurrency: - group: ci-${{ github.ref }}-${{ matrix.target }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - runs-on: - labels: ubuntu-latest-16-cores - group: APM Larger Runners - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # 3.10.0 - with: - buildkitd-config: .github/buildkitd-16-cores.toml - - name: Build and Generate FFI - uses: docker/bake-action@4ba453fbc2db7735392b93edf935aaf9b1e8f747 # 6.5.0 - with: - targets: ${{ matrix.target }} - # Caching is useful, when it works. We are routinely hanging, maybe this: - # https://github.com/docker/buildx/issues/537 - #set: | - # *.cache-from=type=gha,scope=${{ matrix.target }} - # *.cache-to=type=gha,mode=max,scope=${{ matrix.target }} From 8610e98b7318316f0d9eb3ef0a17038d76736e00 Mon Sep 17 00:00:00 2001 From: Julio Date: Fri, 6 Mar 2026 16:44:45 +0100 Subject: [PATCH 16/26] make unit test workflow dynamic --- .github/workflows/test.yml | 131 ++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b953ad9b37..897ba3331b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,8 +13,61 @@ env: RUST_VERSION: 1.84.1 jobs: + setup: + runs-on: ubuntu-latest + outputs: + packages-count: ${{ steps.set-packages.outputs.packages-count }} + packages: ${{ steps.set-packages.outputs.packages }} + crashtracker-feature: ${{ steps.set-packages.outputs.crashtracker-feature }} + run-test-spawn: ${{ steps.set-packages.outputs.run-test-spawn }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + fetch-depth: 0 + - name: Get changed crates + if: ${{ github.event_name == 'pull_request' }} + id: changed-crates + uses: ./.github/actions/changed-crates + - name: Set unit test packages + id: set-packages + env: + CHANGED_CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} + AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + COUNT="1" + PACKAGES="" + CRASHTRACKER_FEATURE="--features libdd-crashtracker/generate-unit-test-files" + RUN_TEST_SPAWN="true" + elif [[ "$CHANGED_CRATES_COUNT" == "0" ]]; then + COUNT="0" + PACKAGES="" + CRASHTRACKER_FEATURE="" + RUN_TEST_SPAWN="false" + else + UNIT_CRATES=$(echo "$AFFECTED_CRATES" | jq '[.[] | select(. != "builder")]') + COUNT=$(echo "$UNIT_CRATES" | jq 'length') + PACKAGES=$(echo "$UNIT_CRATES" | jq -r 'map("-p " + .) | join(" ")') + if echo "$UNIT_CRATES" | jq -e 'any(. == "libdd-crashtracker")' > /dev/null; then + CRASHTRACKER_FEATURE="--features libdd-crashtracker/generate-unit-test-files" + else + CRASHTRACKER_FEATURE="" + fi + if echo "$UNIT_CRATES" | jq -e 'any(. == "test_spawn_from_lib")' > /dev/null; then + RUN_TEST_SPAWN="true" + else + RUN_TEST_SPAWN="false" + fi + fi + echo "packages-count=$COUNT" >> $GITHUB_OUTPUT + echo "packages=$PACKAGES" >> $GITHUB_OUTPUT + echo "crashtracker-feature=$CRASHTRACKER_FEATURE" >> $GITHUB_OUTPUT + echo "run-test-spawn=$RUN_TEST_SPAWN" >> $GITHUB_OUTPUT + test: - name: "cargo test --workspace #${{ matrix.platform }} ${{ matrix.rust_version }}" + name: "cargo test #${{ matrix.platform }} ${{ matrix.rust_version }}" + needs: setup + if: needs.setup.outputs.packages-count != '0' runs-on: ${{ matrix.platform }} permissions: checks: write @@ -22,6 +75,8 @@ jobs: env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 + PACKAGES: ${{ needs.setup.outputs.packages }} + CRASHTRACKER_FEATURE: ${{ needs.setup.outputs.crashtracker-feature }} strategy: matrix: platform: [windows-latest, ubuntu-latest, macos-15] @@ -62,22 +117,47 @@ jobs: - name: "Remove nextest CI report" shell: bash run: rm -rf target/nextest/ci/junit.xml - - name: "[${{ steps.rust-version.outputs.version}}] cargo build --workspace --exclude builder --verbose" + - name: "[${{ steps.rust-version.outputs.version}}] cargo build" shell: bash - run: cargo build --workspace --exclude builder --verbose - - name: "[${{ steps.rust-version.outputs.version}}] cargo nextest run --workspace --features libdd-crashtracker/generate-unit-test-files --exclude builder --profile ci --verbose -E '!test(tracing_integration_tests::)'" + run: | + if [[ -z "$PACKAGES" ]]; then + cargo build --workspace --exclude builder --verbose + else + # shellcheck disable=SC2086 - word splitting on $PACKAGES is intentional + cargo build $PACKAGES --verbose + fi + - name: "[${{ steps.rust-version.outputs.version}}] cargo test (doc) and cargo nextest run" shell: bash # Run doc tests with cargo test and run tests with nextest and generate junit.xml - run: cargo test --workspace --features libdd-crashtracker/generate-unit-test-files --exclude builder --doc --verbose && cargo nextest run --workspace --features libdd-crashtracker/generate-unit-test-files --exclude builder --profile ci --verbose -E '!test(tracing_integration_tests::)' + run: | + if [[ -z "$PACKAGES" ]]; then + # shellcheck disable=SC2086 + cargo test --workspace $CRASHTRACKER_FEATURE --exclude builder --doc --verbose + # shellcheck disable=SC2086 + cargo nextest run --workspace $CRASHTRACKER_FEATURE --exclude builder --profile ci --verbose -E '!test(tracing_integration_tests::)' + else + # shellcheck disable=SC2086 + cargo test $PACKAGES $CRASHTRACKER_FEATURE --doc --verbose + # shellcheck disable=SC2086 + cargo nextest run $PACKAGES $CRASHTRACKER_FEATURE --profile ci --verbose -E '!test(tracing_integration_tests::)' + fi env: RUST_BACKTRACE: full - - name: "[${{ steps.rust-version.outputs.version}}] Tracing integration tests: cargo nextest run --workspace --features libdd-crashtracker/generate-unit-test-files --exclude builder --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)'" + - name: "[${{ steps.rust-version.outputs.version}}] Tracing integration tests" if: runner.os == 'Linux' shell: bash - run: cargo nextest run --workspace --features libdd-crashtracker/generate-unit-test-files --exclude builder --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)' + run: | + if [[ -z "$PACKAGES" ]]; then + # shellcheck disable=SC2086 + cargo nextest run --workspace $CRASHTRACKER_FEATURE --exclude builder --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)' + else + # shellcheck disable=SC2086 + cargo nextest run $PACKAGES $CRASHTRACKER_FEATURE --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)' + fi env: RUST_BACKTRACE: full - - name: "[${{ steps.rust-version.outputs.version}}] RUSTFLAGS=\"-C prefer-dynamic\" cargo nextest run --package test_spawn_from_lib --features prefer-dynamic -E '!test(tracing_integration_tests::)'" + - name: "[${{ steps.rust-version.outputs.version}}] RUSTFLAGS=\"-C prefer-dynamic\" cargo nextest run --package test_spawn_from_lib" + if: needs.setup.outputs.run-test-spawn == 'true' shell: bash run: cargo nextest run --package test_spawn_from_lib --features prefer-dynamic -E '!test(tracing_integration_tests::)' env: @@ -115,22 +195,22 @@ jobs: CHECKSUM_CMD="shasum -a 256" EXPECTED_CHECKSUM="071a6140b17438b3f9dd6c65da48b48ea03fc310034fa624ce874fdb6c325da4" fi - + echo "Downloading datadog-ci from $URL" curl -L --fail --retry 3 -o "$OUTPUT" "$URL" chmod +x "$OUTPUT" - + # Verify checksum ACTUAL_CHECKSUM=$($CHECKSUM_CMD "$OUTPUT" | cut -d' ' -f1) echo "Expected checksum: $EXPECTED_CHECKSUM" echo "Actual checksum: $ACTUAL_CHECKSUM" - + if [ "$ACTUAL_CHECKSUM" != "$EXPECTED_CHECKSUM" ]; then echo "Checksum verification failed!" exit 1 fi echo "Checksum verification passed" - + # Upload test results ./"$OUTPUT" junit upload \ --service libdatadog \ @@ -143,7 +223,12 @@ jobs: cross-centos7: name: build and test using cross - on centos7 + needs: setup + if: needs.setup.outputs.packages-count != '0' runs-on: ubuntu-latest + env: + PACKAGES: ${{ needs.setup.outputs.packages }} + CRASHTRACKER_FEATURE: ${{ needs.setup.outputs.crashtracker-feature }} concurrency: group: ci-${{ github.ref }}-cross-centos7 cancel-in-progress: true @@ -166,7 +251,21 @@ jobs: cache-targets: true # cache build artifacts cache-bin: true # cache the ~/.cargo/bin directory - run: cargo install cross || true - - run: cross build --workspace --target x86_64-unknown-linux-gnu --exclude builder - - run: cross test --workspace --features libdd-crashtracker/generate-unit-test-files --target x86_64-unknown-linux-gnu --exclude builder -- --skip "::single_threaded_tests::" --skip "tracing_integration_tests::" - - run: cross test --workspace --features libdd-crashtracker/generate-unit-test-files --target x86_64-unknown-linux-gnu --exclude builder --exclude bin_tests -- --skip "::tests::" --skip "::api_tests::" --test-threads 1 --skip "tracing_integration_tests::" - + - name: cross build and test + run: | + if [[ -z "$PACKAGES" ]]; then + cross build --workspace --target x86_64-unknown-linux-gnu --exclude builder + # shellcheck disable=SC2086 + cross test --workspace $CRASHTRACKER_FEATURE --target x86_64-unknown-linux-gnu --exclude builder -- --skip "::single_threaded_tests::" --skip "tracing_integration_tests::" + # shellcheck disable=SC2086 + cross test --workspace $CRASHTRACKER_FEATURE --target x86_64-unknown-linux-gnu --exclude builder --exclude bin_tests -- --skip "::tests::" --skip "::api_tests::" --test-threads 1 --skip "tracing_integration_tests::" + else + # shellcheck disable=SC2086 + cross build $PACKAGES --target x86_64-unknown-linux-gnu + # shellcheck disable=SC2086 + cross test $PACKAGES $CRASHTRACKER_FEATURE --target x86_64-unknown-linux-gnu -- --skip "::single_threaded_tests::" --skip "tracing_integration_tests::" + # Remove bin_tests from packages for the second test run, as it is excluded in workspace mode too + PACKAGES_NO_BIN_TESTS=$(echo "$PACKAGES" | sed 's/-p bin_tests//g' | xargs) + # shellcheck disable=SC2086 + cross test $PACKAGES_NO_BIN_TESTS $CRASHTRACKER_FEATURE --target x86_64-unknown-linux-gnu -- --skip "::tests::" --skip "::api_tests::" --test-threads 1 --skip "tracing_integration_tests::" + fi From 026698c1132910b75f3c956323cdc6222e35c914 Mon Sep 17 00:00:00 2001 From: Igor Unanua Date: Fri, 6 Mar 2026 17:31:41 +0100 Subject: [PATCH 17/26] chore(ci): setup miri crates before running (#1679) # What does this PR do? A brief description of the change being made with this pull request. # Motivation What inspired you to submit this pull request? # Additional Notes Anything else we should know when reviewing? # How to test the change? Describe here in detail how the change can be validated. --- .github/workflows/miri.yml | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml index 5c631d23fe..3104fd476b 100644 --- a/.github/workflows/miri.yml +++ b/.github/workflows/miri.yml @@ -1,15 +1,53 @@ name: Miri test on: pull_request: + branches-ignore: + - release push: branches: - main + jobs: + setup: + runs-on: ubuntu-latest + outputs: + crates: ${{ steps.set-crates.outputs.crates }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + fetch-depth: 0 + - name: Get changed crates + if: ${{ github.event_name == 'pull_request' }} + id: changed-crates + uses: ./.github/actions/changed-crates + - name: Set crates to run Miri on + id: set-crates + env: + CHANGED_CRATES: ${{ steps.changed-crates.outputs.crates }} + AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "This is a pull request event, running Miri on changed and affected crates" + echo "Changed crates: $CHANGED_CRATES" + echo "Affected crates: $AFFECTED_CRATES" + + # create a list of crates from the affected crates + CRATES=$(echo "$AFFECTED_CRATES" | jq -r 'map("-p " + .) | join(" ")') + [[ -z "$CRATES" || "$CRATES" == '""' ]] && CRATES="" + else + echo "This is a push event, running Miri on all crates" + CRATES="--workspace" + fi + echo "Crates: $CRATES" + echo "crates=$CRATES" >> $GITHUB_OUTPUT + run-miri: runs-on: ubuntu-latest strategy: matrix: partition: [1, 2, 3, 4, 5] + needs: setup + if: ${{ needs.setup.outputs.crates != '' }} env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 @@ -30,6 +68,6 @@ jobs: with: cache-targets: true # cache build artifacts cache-bin: true # cache the ~/.cargo/bin directory - - run: MIRIFLAGS="-Zmiri-disable-isolation" cargo miri nextest run --partition count:${{ matrix.partition }}/5 + - run: MIRIFLAGS="-Zmiri-disable-isolation" cargo miri nextest run ${{ needs.setup.outputs.crates }} --partition count:${{ matrix.partition }}/5 # We need to disable isolation because # "unsupported operation: `clock_gettime` with `REALTIME` clocks not available when isolation is enabled" From c8cd45f2b9b4f14f787763e780f2c3e045d3049c Mon Sep 17 00:00:00 2001 From: Julio Date: Fri, 6 Mar 2026 18:16:01 +0100 Subject: [PATCH 18/26] fix spellcheck --- .github/workflows/test-ffi.yml | 4 ++-- .github/workflows/test.yml | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-ffi.yml b/.github/workflows/test-ffi.yml index 1c53574004..a0a88122f9 100644 --- a/.github/workflows/test-ffi.yml +++ b/.github/workflows/test-ffi.yml @@ -43,9 +43,9 @@ jobs: PACKAGES=$(echo "$FFI_CRATES" | jq -r 'map("-p " + .) | join(" ")') CRATES_JSON="$FFI_CRATES" fi - echo "packages-count=$COUNT" >> $GITHUB_OUTPUT - echo "packages=$PACKAGES" >> $GITHUB_OUTPUT { + echo "packages-count=$COUNT" + echo "packages=$PACKAGES" echo "crates-json<> $GITHUB_OUTPUT - echo "packages=$PACKAGES" >> $GITHUB_OUTPUT - echo "crashtracker-feature=$CRASHTRACKER_FEATURE" >> $GITHUB_OUTPUT - echo "run-test-spawn=$RUN_TEST_SPAWN" >> $GITHUB_OUTPUT + { + echo "packages-count=$COUNT" + echo "packages=$PACKAGES" + echo "crashtracker-feature=$CRASHTRACKER_FEATURE" + echo "run-test-spawn=$RUN_TEST_SPAWN" + } >> $GITHUB_OUTPUT test: name: "cargo test #${{ matrix.platform }} ${{ matrix.rust_version }}" @@ -123,7 +125,8 @@ jobs: if [[ -z "$PACKAGES" ]]; then cargo build --workspace --exclude builder --verbose else - # shellcheck disable=SC2086 - word splitting on $PACKAGES is intentional + # word splitting on $PACKAGES is intentional + # shellcheck disable=SC2086 cargo build $PACKAGES --verbose fi - name: "[${{ steps.rust-version.outputs.version}}] cargo test (doc) and cargo nextest run" From 63c03498f5939775277a3710562f36fcbe147f44 Mon Sep 17 00:00:00 2001 From: Julio Date: Sat, 7 Mar 2026 08:34:36 +0100 Subject: [PATCH 19/26] make clippy and rustfmt dynamic --- .github/workflows/lint.yml | 52 ++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index de2e5d0a5b..4bfe1bd90e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,7 +11,9 @@ jobs: setup: runs-on: ubuntu-latest outputs: - crates-count: ${{ steps.set-count.outputs.crates-count }} + crates-count: ${{ steps.set-packages.outputs.crates-count }} + fmt-packages: ${{ steps.set-packages.outputs.fmt-packages }} + clippy-packages: ${{ steps.set-packages.outputs.clippy-packages }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: @@ -20,16 +22,31 @@ jobs: if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - - name: Set crates count - id: set-count + - name: Set lint packages + id: set-packages env: - CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} + CHANGED_CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} + CHANGED_CRATES: ${{ steps.changed-crates.outputs.crates }} + AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} run: | - if [[ "${{ github.event_name }}" == "pull_request" ]]; then - echo "crates-count=$CRATES_COUNT" >> $GITHUB_OUTPUT + if [[ "${{ github.event_name }}" == "push" ]]; then + COUNT="1" + FMT_PACKAGES="" + CLIPPY_PACKAGES="" + elif [[ "$CHANGED_CRATES_COUNT" == "0" ]]; then + COUNT="0" + FMT_PACKAGES="" + CLIPPY_PACKAGES="" else - echo "crates-count=1" >> $GITHUB_OUTPUT + COUNT="$CHANGED_CRATES_COUNT" + # rustfmt: only directly changed crates — dependants were not modified by this PR + FMT_PACKAGES=$(echo "$CHANGED_CRATES" | jq -r '[.[].name] | map("-p " + .) | join(" ")') + # clippy: affected crates — a change can introduce warnings in dependants + CLIPPY_PACKAGES=$(echo "$AFFECTED_CRATES" | jq -r 'map("-p " + .) | join(" ")') fi + echo "crates-count=$COUNT" >> $GITHUB_OUTPUT + echo "fmt-packages=$FMT_PACKAGES" >> $GITHUB_OUTPUT + echo "clippy-packages=$CLIPPY_PACKAGES" >> $GITHUB_OUTPUT actionlint: needs: setup @@ -59,7 +76,16 @@ jobs: with: cache-targets: true # cache build artifacts cache-bin: true # cache the ~/.cargo/bin directory - - run: cargo fmt --all -- --check + - name: Run rustfmt + env: + FMT_PACKAGES: ${{ needs.setup.outputs.fmt-packages }} + run: | + if [[ -z "$FMT_PACKAGES" ]]; then + cargo fmt --all -- --check + else + # shellcheck disable=SC2086 - word splitting on $FMT_PACKAGES is intentional + cargo fmt $FMT_PACKAGES -- --check + fi clippy: needs: setup if: needs.setup.outputs.crates-count != '0' @@ -82,12 +108,18 @@ jobs: cache-bin: true # cache the ~/.cargo/bin directory - name: Run clippy on ${{ matrix.platform }} ${{ matrix.rust_version }} shell: bash + env: + CLIPPY_PACKAGES: ${{ needs.setup.outputs.clippy-packages }} run: | if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then export AWS_LC_FIPS_SYS_NO_ASM=1 fi - # shellcheck disable=SC2046 - cargo clippy --workspace --all-targets --all-features -- -D warnings + if [[ -z "$CLIPPY_PACKAGES" ]]; then + cargo clippy --workspace --all-targets --all-features -- -D warnings + else + # shellcheck disable=SC2086 - word splitting on $CLIPPY_PACKAGES is intentional + cargo clippy $CLIPPY_PACKAGES --all-targets --all-features -- -D warnings + fi licensecheck: needs: setup From 36fe200b4c1b130da76c951fba5b13aba24e6821 Mon Sep 17 00:00:00 2001 From: Julio Date: Sat, 7 Mar 2026 08:40:05 +0100 Subject: [PATCH 20/26] fix shellcheck --- .github/workflows/lint.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4bfe1bd90e..d0f52bcd29 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -44,9 +44,11 @@ jobs: # clippy: affected crates — a change can introduce warnings in dependants CLIPPY_PACKAGES=$(echo "$AFFECTED_CRATES" | jq -r 'map("-p " + .) | join(" ")') fi - echo "crates-count=$COUNT" >> $GITHUB_OUTPUT - echo "fmt-packages=$FMT_PACKAGES" >> $GITHUB_OUTPUT - echo "clippy-packages=$CLIPPY_PACKAGES" >> $GITHUB_OUTPUT + { + echo "crates-count=$COUNT" + echo "fmt-packages=$FMT_PACKAGES" + echo "clippy-packages=$CLIPPY_PACKAGES" + } >> $GITHUB_OUTPUT actionlint: needs: setup @@ -83,7 +85,7 @@ jobs: if [[ -z "$FMT_PACKAGES" ]]; then cargo fmt --all -- --check else - # shellcheck disable=SC2086 - word splitting on $FMT_PACKAGES is intentional + # shellcheck disable=SC2086 cargo fmt $FMT_PACKAGES -- --check fi clippy: @@ -117,7 +119,7 @@ jobs: if [[ -z "$CLIPPY_PACKAGES" ]]; then cargo clippy --workspace --all-targets --all-features -- -D warnings else - # shellcheck disable=SC2086 - word splitting on $CLIPPY_PACKAGES is intentional + # shellcheck disable=SC2086 cargo clippy $CLIPPY_PACKAGES --all-targets --all-features -- -D warnings fi From ada2860b23d76e522d74551d8550c2954dae83c8 Mon Sep 17 00:00:00 2001 From: Julio Date: Sat, 7 Mar 2026 09:14:52 +0100 Subject: [PATCH 21/26] fix: search crates by exact name rather than substring --- .../actions/ci-crates/src/bin/changed_crates.rs | 14 +++++++++++--- .github/actions/ci-crates/src/workspace.rs | 9 +++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/actions/ci-crates/src/bin/changed_crates.rs b/.github/actions/ci-crates/src/bin/changed_crates.rs index 0e82e85f00..3fc317307f 100644 --- a/.github/actions/ci-crates/src/bin/changed_crates.rs +++ b/.github/actions/ci-crates/src/bin/changed_crates.rs @@ -12,6 +12,7 @@ //! affected_crates_count – integer use anyhow::{anyhow, Result}; +use cargo_metadata::camino::Utf8Path; use cargo_metadata::Package; use ci_crates::git; use ci_crates::workspace; @@ -42,7 +43,7 @@ fn main() -> Result<()> { // * Compilation flags. let workspace = workspace::load()?; - let changed_crates = collect_changed_crates(&changed_files, workspace.members()); + let changed_crates = collect_changed_crates(&changed_files, workspace.members(), workspace.workspace_root()); if changed_crates.is_empty() { log::info!("Changed crates is empty"); @@ -60,13 +61,20 @@ fn main() -> Result<()> { ) } -fn collect_changed_crates(changed_files: &[String], members: &[Package]) -> Vec { +fn collect_changed_crates(changed_files: &[String], members: &[Package], workspace_root: &Utf8Path) -> Vec { let mut crates: Vec = Vec::new(); let mut crate_inventory: HashSet = HashSet::new(); for file in changed_files { for member in members { - if file.contains(member.name.as_str()) { + let Some(crate_dir) = member.manifest_path.parent() else { + continue; + }; + let Ok(relative_dir) = crate_dir.strip_prefix(workspace_root) else { + continue; + }; + let relative_dir_str = relative_dir.as_str(); + if file == relative_dir_str || file.starts_with(&format!("{relative_dir_str}/")) { if crate_inventory.insert(member.name.to_string()) { crates.push(CrateInfo { name: member.name.as_str().to_string(), diff --git a/.github/actions/ci-crates/src/workspace.rs b/.github/actions/ci-crates/src/workspace.rs index 0a125637ef..f11a386ec3 100644 --- a/.github/actions/ci-crates/src/workspace.rs +++ b/.github/actions/ci-crates/src/workspace.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use anyhow::Result; +use cargo_metadata::camino::{Utf8Path, Utf8PathBuf}; use cargo_metadata::{MetadataCommand, Package}; use std::collections::{HashMap, HashSet, VecDeque}; @@ -10,6 +11,7 @@ pub struct WorkspaceMetadata { packages: Vec, /// Maps each crate name to the list of workspace crates that depend on it. reverse_deps: HashMap>, + workspace_root: Utf8PathBuf, } impl WorkspaceMetadata { @@ -17,6 +19,10 @@ impl WorkspaceMetadata { &self.packages } + pub fn workspace_root(&self) -> &Utf8Path { + &self.workspace_root + } + pub fn affected_from(&self, seeds: &[String]) -> HashSet { let mut visited: HashSet = HashSet::new(); let mut queue: VecDeque = VecDeque::new(); @@ -44,6 +50,7 @@ impl WorkspaceMetadata { pub fn load() -> Result { let metadata = MetadataCommand::new().exec()?; + let workspace_root = metadata.workspace_root.clone(); let packages: Vec = metadata.workspace_packages().into_iter().cloned().collect(); let member_names: HashSet = packages.iter().map(|p| p.name.as_str().to_string()).collect(); @@ -63,6 +70,7 @@ pub fn load() -> Result { Ok(WorkspaceMetadata { packages, reverse_deps, + workspace_root, }) } @@ -85,6 +93,7 @@ mod tests { WorkspaceMetadata { packages: vec![], reverse_deps, + workspace_root: Utf8PathBuf::new(), } } From 9c957d3e19b2f0e1dcd75399c218774c132b96f5 Mon Sep 17 00:00:00 2001 From: Julio Date: Sat, 7 Mar 2026 10:00:30 +0100 Subject: [PATCH 22/26] fix: only run tests on crates containing tracing integration tests --- .github/workflows/test.yml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b1d342ed1b..fe600c0f3a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,6 +79,7 @@ jobs: CARGO_INCREMENTAL: 0 PACKAGES: ${{ needs.setup.outputs.packages }} CRASHTRACKER_FEATURE: ${{ needs.setup.outputs.crashtracker-feature }} + TRACING_CRATES: "libdd-data-pipeline libdd-trace-utils datadog-tracer-flare" strategy: matrix: platform: [windows-latest, ubuntu-latest, macos-15] @@ -152,10 +153,23 @@ jobs: run: | if [[ -z "$PACKAGES" ]]; then # shellcheck disable=SC2086 - cargo nextest run --workspace $CRASHTRACKER_FEATURE --exclude builder --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)' + for crate in $TRACING_CRATES; do + PACKAGES="$PACKAGES -p $crate" + done + cargo nextest run $PACKAGES --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)' else - # shellcheck disable=SC2086 - cargo nextest run $PACKAGES $CRASHTRACKER_FEATURE --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)' + TRACING_PACKAGES="" + for crate in $TRACING_CRATES; do + if echo "$PACKAGES" | grep -qw -- "-p $crate"; then + TRACING_PACKAGES="$TRACING_PACKAGES -p $crate" + fi + done + if [[ -z "$TRACING_PACKAGES" ]]; then + echo "No tracing integration test crates found in PACKAGES, skipping." + else + # shellcheck disable=SC2086 + cargo nextest run $TRACING_PACKAGES --profile ci --test-threads=1 --verbose -E 'test(tracing_integration_tests::)' + fi fi env: RUST_BACKTRACE: full From cb5bf5f1bd5598053c9561a38be43c815f6ff9f9 Mon Sep 17 00:00:00 2001 From: Igor Unanua Date: Mon, 9 Mar 2026 11:56:31 +0100 Subject: [PATCH 23/26] ci: changed-crates refactor (#1691) # What does this PR do? Remove the `github.event_name == 'pull_request'` checks # Motivation What inspired you to submit this pull request? # Additional Notes Anything else we should know when reviewing? # How to test the change? Describe here in detail how the change can be validated. --- .github/actions/changed-crates/action.yml | 17 ++++++++++++++++- .github/workflows/fuzz.yml | 4 ++-- .github/workflows/lint.yml | 4 ++-- .github/workflows/miri.yml | 4 ++-- .github/workflows/test-ffi.yml | 4 ++-- .github/workflows/test.yml | 4 ++-- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/changed-crates/action.yml index d91f1dcd16..27351ad2e1 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/changed-crates/action.yml @@ -5,6 +5,9 @@ name: 'Get Changed Crates' description: 'Detects which Rust crates have changed files in a PR or push' outputs: + status: + description: 'Exit status of the action (e.g. success, skipped)' + value: ${{ steps.detect.outputs.status }} crates: description: 'JSON array of changed crates with name, version, path and manifest' value: ${{ steps.detect.outputs.crates }} @@ -25,10 +28,12 @@ runs: using: 'composite' steps: - name: Set up Rust + if: ${{ github.event_name == 'pull_request' }} shell: bash run: rustup install stable && rustup default stable - name: Fetch all branches + if: ${{ github.event_name == 'pull_request' }} shell: bash run: | git fetch --all @@ -36,6 +41,7 @@ runs: git branch -a - name: Build change reporter + if: ${{ github.event_name == 'pull_request' }} shell: bash run: | cd ${{ github.action_path }}/.. @@ -48,4 +54,13 @@ runs: EVENT_NAME: ${{ github.event_name }} PR_BASE_REF: ${{ github.base_ref }} run: | - RUST_LOG=debug ${{ github.action_path }}/../target/release/changed-crates $PR_BASE_REF + if [[ "$EVENT_NAME" != "pull_request" ]]; then + echo "status=skipped" >> $GITHUB_OUTPUT + exit 0 + fi + + if RUST_LOG=debug ${{ github.action_path }}/../target/release/changed-crates $PR_BASE_REF; then + echo "status=success" >> $GITHUB_OUTPUT + else + echo "status=skipped" >> $GITHUB_OUTPUT + fi diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 5dd933f778..217eecf6ab 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -15,16 +15,16 @@ jobs: with: fetch-depth: 0 - name: Get changed crates - if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - name: Set fuzz directories id: set-dirs env: + CHANGED_CRATES_STATUS: ${{ steps.changed-crates.outputs.status }} CHANGED_CRATES: ${{ steps.changed-crates.outputs.crates }} run: | ALL_FUZZ='["libdd-alloc", "libdd-profiling", "libdd-common-ffi", "libdd-trace-utils"]' - if [[ "${{ github.event_name }}" == "pull_request" ]]; then + if [[ "$CHANGED_CRATES_STATUS" == "success" ]]; then FILTERED=$(echo "$CHANGED_CRATES" | jq --argjson fuzz "$ALL_FUZZ" \ '[.[] | .path | split("/") | last | . as $dir | if ($fuzz | index($dir) != null) then $dir else empty end]') COUNT=$(echo "$FILTERED" | jq 'length') diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d0f52bcd29..bfe82d8b14 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,17 +19,17 @@ jobs: with: fetch-depth: 0 - name: Get changed crates - if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - name: Set lint packages id: set-packages env: + CHANGED_CRATES_STATUS: ${{ steps.changed-crates.outputs.status }} CHANGED_CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} CHANGED_CRATES: ${{ steps.changed-crates.outputs.crates }} AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} run: | - if [[ "${{ github.event_name }}" == "push" ]]; then + if [[ "$CHANGED_CRATES_STATUS" == "skipped" ]]; then COUNT="1" FMT_PACKAGES="" CLIPPY_PACKAGES="" diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml index 3104fd476b..f5a86e8da3 100644 --- a/.github/workflows/miri.yml +++ b/.github/workflows/miri.yml @@ -17,16 +17,16 @@ jobs: with: fetch-depth: 0 - name: Get changed crates - if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - name: Set crates to run Miri on id: set-crates env: + CHANGED_CRATES_STATUS: ${{ steps.changed-crates.outputs.status }} CHANGED_CRATES: ${{ steps.changed-crates.outputs.crates }} AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} run: | - if [[ "${{ github.event_name }}" == "pull_request" ]]; then + if [[ "$CHANGED_CRATES_STATUS" == "success" ]]; then echo "This is a pull request event, running Miri on changed and affected crates" echo "Changed crates: $CHANGED_CRATES" echo "Affected crates: $AFFECTED_CRATES" diff --git a/.github/workflows/test-ffi.yml b/.github/workflows/test-ffi.yml index a0a88122f9..ce66a775f9 100644 --- a/.github/workflows/test-ffi.yml +++ b/.github/workflows/test-ffi.yml @@ -20,16 +20,16 @@ jobs: with: fetch-depth: 0 - name: Get changed crates - if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - name: Set FFI packages id: set-packages env: + CHANGED_CRATES_STATUS: ${{ steps.changed-crates.outputs.status }} CHANGED_CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} run: | - if [[ "${{ github.event_name }}" == "push" ]]; then + if [[ "$CHANGED_CRATES_STATUS" == "skipped" ]]; then COUNT="1" PACKAGES="" CRATES_JSON="" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fe600c0f3a..da75df1aaf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,16 +25,16 @@ jobs: with: fetch-depth: 0 - name: Get changed crates - if: ${{ github.event_name == 'pull_request' }} id: changed-crates uses: ./.github/actions/changed-crates - name: Set unit test packages id: set-packages env: + CHANGED_CRATES_STATUS: ${{ steps.changed-crates.outputs.status }} CHANGED_CRATES_COUNT: ${{ steps.changed-crates.outputs.crates_count }} AFFECTED_CRATES: ${{ steps.changed-crates.outputs.affected_crates }} run: | - if [[ "${{ github.event_name }}" == "push" ]]; then + if [[ "$CHANGED_CRATES_STATUS" == "skipped" ]]; then COUNT="1" PACKAGES="" CRASHTRACKER_FEATURE="--features libdd-crashtracker/generate-unit-test-files" From a434e4783860bbf625438d875c3433683bcb7dbd Mon Sep 17 00:00:00 2001 From: Julio Date: Fri, 13 Mar 2026 13:59:58 +0100 Subject: [PATCH 24/26] chore: clean up actions --- .github/actions/Cargo.lock | 29 ++++++++++--------- .github/actions/Cargo.toml | 2 +- .github/actions/ci-crates/src/lib.rs | 5 ---- .github/actions/ci-shared/Cargo.toml | 1 + .../{ci-crates => ci-shared}/src/git.rs | 5 ---- .github/actions/ci-shared/src/lib.rs | 2 ++ .../{ci-crates => ci-shared}/src/workspace.rs | 5 ---- .../src/commenter.rs | 2 +- .../{ci-crates => crates-reporter}/Cargo.toml | 9 +++--- .../action.yml | 4 +-- .../src/main.rs} | 12 ++------ .github/workflows/fuzz.yml | 4 +-- .github/workflows/lint.yml | 4 +-- .github/workflows/miri.yml | 4 +-- .../workflows/pr-metadata-docs-and-deps.yml | 4 +-- .github/workflows/test-ffi.yml | 4 +-- .github/workflows/test.yml | 4 +-- 17 files changed, 40 insertions(+), 60 deletions(-) delete mode 100644 .github/actions/ci-crates/src/lib.rs rename .github/actions/{ci-crates => ci-shared}/src/git.rs (80%) rename .github/actions/{ci-crates => ci-shared}/src/workspace.rs (97%) rename .github/actions/{ci-crates => crates-reporter}/Cargo.toml (59%) rename .github/actions/{changed-crates => crates-reporter}/action.yml (95%) rename .github/actions/{ci-crates/src/bin/changed_crates.rs => crates-reporter/src/main.rs} (94%) diff --git a/.github/actions/Cargo.lock b/.github/actions/Cargo.lock index f89dda4a45..cd4743a5cc 100644 --- a/.github/actions/Cargo.lock +++ b/.github/actions/Cargo.lock @@ -430,25 +430,12 @@ dependencies = [ "windows-link", ] -[[package]] -name = "ci-crates" -version = "0.1.0" -dependencies = [ - "anyhow", - "cargo_metadata", - "ci-shared", - "clap", - "env_logger 0.11.9", - "log", - "serde", - "serde_json", -] - [[package]] name = "ci-shared" version = "0.1.0" dependencies = [ "anyhow", + "cargo_metadata", "log", "serde", "serde_json", @@ -547,6 +534,20 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "crates-reporter" +version = "0.1.0" +dependencies = [ + "anyhow", + "cargo_metadata", + "ci-shared", + "clap", + "env_logger 0.11.9", + "log", + "serde", + "serde_json", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" diff --git a/.github/actions/Cargo.toml b/.github/actions/Cargo.toml index 3c798000f7..cdfde15441 100644 --- a/.github/actions/Cargo.toml +++ b/.github/actions/Cargo.toml @@ -4,7 +4,7 @@ [workspace] members = [ "ci-shared", - "ci-crates", + "crates-reporter", "clippy-annotation-reporter", ] resolver = "2" diff --git a/.github/actions/ci-crates/src/lib.rs b/.github/actions/ci-crates/src/lib.rs deleted file mode 100644 index a85f13e761..0000000000 --- a/.github/actions/ci-crates/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ -// SPDX-License-Identifier: Apache-2.0 - -pub mod git; -pub mod workspace; diff --git a/.github/actions/ci-shared/Cargo.toml b/.github/actions/ci-shared/Cargo.toml index 265f227d28..f7ec22b9fb 100644 --- a/.github/actions/ci-shared/Cargo.toml +++ b/.github/actions/ci-shared/Cargo.toml @@ -10,6 +10,7 @@ publish = false [dependencies] anyhow = "1.0" +cargo_metadata = "0.23.1" log = "0.4" toml = "0.8" serde = { version = "1", features = ["derive"] } diff --git a/.github/actions/ci-crates/src/git.rs b/.github/actions/ci-shared/src/git.rs similarity index 80% rename from .github/actions/ci-crates/src/git.rs rename to .github/actions/ci-shared/src/git.rs index 2642dcc416..1732468b6a 100644 --- a/.github/actions/ci-crates/src/git.rs +++ b/.github/actions/ci-shared/src/git.rs @@ -4,7 +4,6 @@ use anyhow::{bail, Context, Result}; use std::process::Command; -/// Run `git fetch --depth=1 origin ` to ensure the base ref is available locally. pub fn fetch_base(base_ref: &str) -> Result<()> { log::info!("Fetching base branch: {base_ref}"); @@ -18,16 +17,12 @@ pub fn fetch_base(base_ref: &str) -> Result<()> { .context("Failed to run git fetch")?; if !status.success() { - // Non-fatal: warn but do not abort (mirrors `|| true` in the bash version) log::warn!("git fetch for {base_ref} returned non-zero exit code; continuing"); } Ok(()) } -/// Return the list of files changed between `origin/...HEAD` (three-dot diff). -/// -/// Uses `git diff --name-only origin/...HEAD`. pub fn changed_files(base_ref: &str) -> Result> { let output = Command::new("git") .args(["diff", "--name-only", &format!("origin/{base_ref}...HEAD")]) diff --git a/.github/actions/ci-shared/src/lib.rs b/.github/actions/ci-shared/src/lib.rs index ac3c51bfb1..b9d6fc68c2 100644 --- a/.github/actions/ci-shared/src/lib.rs +++ b/.github/actions/ci-shared/src/lib.rs @@ -3,3 +3,5 @@ pub mod crate_detection; pub mod github_output; +pub mod git; +pub mod workspace; diff --git a/.github/actions/ci-crates/src/workspace.rs b/.github/actions/ci-shared/src/workspace.rs similarity index 97% rename from .github/actions/ci-crates/src/workspace.rs rename to .github/actions/ci-shared/src/workspace.rs index f11a386ec3..67dda95990 100644 --- a/.github/actions/ci-crates/src/workspace.rs +++ b/.github/actions/ci-shared/src/workspace.rs @@ -9,7 +9,6 @@ use std::collections::{HashMap, HashSet, VecDeque}; /// Parsed workspace metadata with reverse-dependency index. pub struct WorkspaceMetadata { packages: Vec, - /// Maps each crate name to the list of workspace crates that depend on it. reverse_deps: HashMap>, workspace_root: Utf8PathBuf, } @@ -105,8 +104,6 @@ mod tests { s.iter().map(|s| s.to_string()).collect() } - // --- affected_from --- - #[test] fn affected_from_empty_seeds_returns_empty() { let meta = make_meta(&[]); @@ -171,8 +168,6 @@ mod tests { ); } - // --- load() integration --- - #[test] fn load_returns_non_empty_workspace() { let meta = load().expect("load() should succeed against the real workspace"); diff --git a/.github/actions/clippy-annotation-reporter/src/commenter.rs b/.github/actions/clippy-annotation-reporter/src/commenter.rs index 536f229f98..abb271b703 100644 --- a/.github/actions/clippy-annotation-reporter/src/commenter.rs +++ b/.github/actions/clippy-annotation-reporter/src/commenter.rs @@ -7,7 +7,7 @@ //! including finding existing comments and updating or creating comments. use anyhow::{Context as _, Result}; -use log::{error, info}; +use log::info; use octocrab::Octocrab; /// Post or update a comment on a PR with the given report diff --git a/.github/actions/ci-crates/Cargo.toml b/.github/actions/crates-reporter/Cargo.toml similarity index 59% rename from .github/actions/ci-crates/Cargo.toml rename to .github/actions/crates-reporter/Cargo.toml index f188a22ef2..f3d16c2a01 100644 --- a/.github/actions/ci-crates/Cargo.toml +++ b/.github/actions/crates-reporter/Cargo.toml @@ -2,16 +2,15 @@ # SPDX-License-Identifier: Apache-2.0 [package] -name = "ci-crates" +name = "crates-reporter" version = "0.1.0" edition = "2021" rust-version = "1.84.1" +description = "GitHub Action for reporting modified crates and transitive dependencies" +homepage = "https://github.com/DataDog/libdatadog/tree/main/.github/actions/changed-crates" +repository = "https://github.com/DataDog/libdatadog/tree/main/.github/actions/changed-crates" publish = false -[[bin]] -name = "changed-crates" -path = "src/bin/changed_crates.rs" - [dependencies] ci-shared = { path = "../ci-shared" } anyhow = "1.0" diff --git a/.github/actions/changed-crates/action.yml b/.github/actions/crates-reporter/action.yml similarity index 95% rename from .github/actions/changed-crates/action.yml rename to .github/actions/crates-reporter/action.yml index 02436b269e..d914b5ee3c 100644 --- a/.github/actions/changed-crates/action.yml +++ b/.github/actions/crates-reporter/action.yml @@ -45,7 +45,7 @@ runs: shell: bash run: | cd ${{ github.action_path }}/.. - cargo build --release -p ci-crates + cargo build --release -p crates-reporter - name: Run change reporter id: detect @@ -58,7 +58,7 @@ runs: echo "status=skipped" >> $GITHUB_OUTPUT exit 0 fi - if RUST_LOG=debug ${{ github.action_path }}/../target/release/changed-crates $PR_BASE_REF; then + if RUST_LOG=debug ${{ github.action_path }}/../target/release/crates-reporter $PR_BASE_REF; then echo "status=success" >> $GITHUB_OUTPUT else echo "status=skipped" >> $GITHUB_OUTPUT diff --git a/.github/actions/ci-crates/src/bin/changed_crates.rs b/.github/actions/crates-reporter/src/main.rs similarity index 94% rename from .github/actions/ci-crates/src/bin/changed_crates.rs rename to .github/actions/crates-reporter/src/main.rs index 3fc317307f..711f3474e1 100644 --- a/.github/actions/ci-crates/src/bin/changed_crates.rs +++ b/.github/actions/crates-reporter/src/main.rs @@ -14,15 +14,14 @@ use anyhow::{anyhow, Result}; use cargo_metadata::camino::Utf8Path; use cargo_metadata::Package; -use ci_crates::git; -use ci_crates::workspace; +use ci_shared::git; +use ci_shared::workspace; use ci_shared::crate_detection::CrateInfo; use ci_shared::github_output::set_output; use std::collections::HashSet; fn main() -> Result<()> { env_logger::init(); - // Parse args let args: Vec = std::env::args().collect(); if args.len() < 2 { return Err(anyhow!("A reference base needs to be passed")); @@ -35,13 +34,6 @@ fn main() -> Result<()> { let changed_files = git::changed_files(&base_ref)?; log::info!("Changed files: {:?}", changed_files); - // TODO: Check heuristics when workspace manifest (Cargo.toml) or config.toml changed. This could indicate a - // change in: - // * Rust version. - // * Edition. - // * Profile. - // * Compilation flags. - let workspace = workspace::load()?; let changed_crates = collect_changed_crates(&changed_files, workspace.members(), workspace.workspace_root()); diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 217eecf6ab..4e8618c60a 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -14,9 +14,9 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: fetch-depth: 0 - - name: Get changed crates + - name: Get crates report id: changed-crates - uses: ./.github/actions/changed-crates + uses: ./.github/actions/crates-reporter - name: Set fuzz directories id: set-dirs env: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ad2d9e2147..11f9f63c7a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,9 +18,9 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: fetch-depth: 0 - - name: Get changed crates + - name: Get crate report id: changed-crates - uses: ./.github/actions/changed-crates + uses: ./.github/actions/crates-reporter - name: Set lint packages id: set-packages env: diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml index 5d065830b5..16a9264a60 100644 --- a/.github/workflows/miri.yml +++ b/.github/workflows/miri.yml @@ -16,9 +16,9 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: fetch-depth: 0 - - name: Get changed crates + - name: Get crates report id: changed-crates - uses: ./.github/actions/changed-crates + uses: ./.github/actions/crates-reporter - name: Set crates to run Miri on id: set-crates env: diff --git a/.github/workflows/pr-metadata-docs-and-deps.yml b/.github/workflows/pr-metadata-docs-and-deps.yml index 0406c8658c..3bbb3ee992 100644 --- a/.github/workflows/pr-metadata-docs-and-deps.yml +++ b/.github/workflows/pr-metadata-docs-and-deps.yml @@ -26,7 +26,7 @@ jobs: with: fetch-depth: 0 # Need full history for git diff - id: changed-crates - uses: ./.github/actions/changed-crates + uses: ./.github/actions/crates-reporter # Check cargo metadata for crates that are not flagged as publish = false cargo-metadata: @@ -387,4 +387,4 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, comment_id: ${{ steps.find-comment.outputs.comment-id }}, - }) \ No newline at end of file + }) diff --git a/.github/workflows/test-ffi.yml b/.github/workflows/test-ffi.yml index ce66a775f9..d350e28132 100644 --- a/.github/workflows/test-ffi.yml +++ b/.github/workflows/test-ffi.yml @@ -19,9 +19,9 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: fetch-depth: 0 - - name: Get changed crates + - name: Get crates report id: changed-crates - uses: ./.github/actions/changed-crates + uses: ./.github/actions/crates-reporter - name: Set FFI packages id: set-packages env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 98a8d3c743..87ccdc8d25 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,9 +24,9 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: fetch-depth: 0 - - name: Get changed crates + - name: Get crates report id: changed-crates - uses: ./.github/actions/changed-crates + uses: ./.github/actions/crates-reporter - name: Set unit test packages id: set-packages env: From 0e12df01b1274dfcec04a774e2d1c3d03961213c Mon Sep 17 00:00:00 2001 From: Julio Date: Fri, 13 Mar 2026 15:59:15 +0100 Subject: [PATCH 25/26] fix centos job --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 87ccdc8d25..311fc84935 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -257,6 +257,8 @@ jobs: cross-centos7: name: Test x86_64-unknown-linux-gnu on centOS7 docker image + needs: setup + if: needs.setup.outputs.packages-count != '0' runs-on: ubuntu-latest env: PACKAGES: ${{ needs.setup.outputs.packages }} From f131d99d3a1a96824434caf328e4464cc25e5dee Mon Sep 17 00:00:00 2001 From: Julio Date: Fri, 13 Mar 2026 16:43:24 +0100 Subject: [PATCH 26/26] make centos test dynamic --- .github/workflows/test.yml | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 311fc84935..86fe1d540d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -292,20 +292,26 @@ jobs: # Run docker as a user, not the default root # Mount and use the runner's toolchain as it's the same arch # exclude tracing integration tests since they require docker in docker to run a test-agent - run: >- - docker run --rm - --user "$(id -u):$(id -g)" - -v "${{ github.workspace }}:/workspace" - -v "${CARGO_HOME:-$HOME/.cargo}:/usr/local/cargo" - -v "${RUSTUP_HOME:-$HOME/.rustup}:/usr/local/rustup" - -e CARGO_HOME=/usr/local/cargo - -e RUSTUP_HOME=/usr/local/rustup - -e PATH=/usr/local/cargo/bin:/usr/local/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin:/opt/rh/devtoolset-11/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - -w /workspace - libdatadog-centos7 - cargo nextest run --workspace --features libdd-crashtracker/generate-unit-test-files - --exclude builder --profile ci - -E '!test(tracing_integration_tests::)' + shell: bash + run: | + if [[ -z "$PACKAGES" ]]; then + # shellcheck disable=SC2086 + NEXTEST_CMD="cargo nextest run --workspace $CRASHTRACKER_FEATURE --exclude builder --profile ci -E '!test(tracing_integration_tests::)'" + else + # shellcheck disable=SC2086 + NEXTEST_CMD="cargo nextest run $PACKAGES $CRASHTRACKER_FEATURE --profile ci -E '!test(tracing_integration_tests::)'" + fi + docker run --rm \ + --user "$(id -u):$(id -g)" \ + -v "${{ github.workspace }}:/workspace" \ + -v "${CARGO_HOME:-$HOME/.cargo}:/usr/local/cargo" \ + -v "${RUSTUP_HOME:-$HOME/.rustup}:/usr/local/rustup" \ + -e CARGO_HOME=/usr/local/cargo \ + -e RUSTUP_HOME=/usr/local/rustup \ + -e PATH=/usr/local/cargo/bin:/usr/local/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin:/opt/rh/devtoolset-11/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ + -w /workspace \ + libdatadog-centos7 \ + sh -c "$NEXTEST_CMD" - name: Add file attributes to JUnit XML if: success() || failure() run: cargo run --bin add_junit_file_attributes -- target/nextest/ci/junit.xml