diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3ea0d30..e48018e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -36,6 +36,21 @@ jobs: - name: cargo test run: nix develop -c cargo test + check-flake-cel-condition: + name: Check flake.lock test (CEL condition) + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + - name: Check flake.lock + run: | + nix develop -c \ + cargo run -- \ + --condition "supportedRefs.contains(gitRef) && numDaysOld < 30 && owner == 'NixOS'" \ + ./tests/flake.cel.0.lock + check-flake-dirty: name: Check flake.lock test (dirty 😈) runs-on: ubuntu-22.04 diff --git a/Cargo.lock b/Cargo.lock index 65ac158..2540604 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -34,21 +43,30 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -61,9 +79,24 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" @@ -73,9 +106,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -88,23 +121,45 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" + +[[package]] +name = "cel-interpreter" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9695f9bcc9ec195e0c35f2b9283adae5cef85cc41534a420216c8a12a323172" dependencies = [ - "libc", + "cel-parser", + "chrono", + "nom", + "paste", + "serde", + "thiserror", +] + +[[package]] +name = "cel-parser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a85ba148abbc551f1c32c8c0cff279dba234f6d38324bf372ba2395690879e" +dependencies = [ + "lalrpop", + "lalrpop-util", + "regex", ] [[package]] @@ -115,21 +170,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", - "windows-targets", + "wasm-bindgen", + "windows-targets 0.52.5", ] [[package]] name = "clap" -version = "4.4.8" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -137,9 +194,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstyle", "clap_lex", @@ -148,9 +205,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck", "proc-macro2", @@ -160,15 +217,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -176,19 +233,25 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -199,6 +262,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.10.7" @@ -210,10 +279,46 @@ dependencies = [ ] [[package]] -name = "encoding_rs" -version = "0.8.33" +name = "dirs-next" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -226,23 +331,29 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flake-checker" -version = "0.1.20" +version = "0.2.0" dependencies = [ + "cel-interpreter", "chrono", "clap", "handlebars", "is_ci", - "once_cell", "parse-flake-lock", "reqwest", "serde", @@ -268,42 +379,42 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-io", @@ -326,9 +437,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -337,9 +448,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "h2" @@ -376,27 +487,27 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -405,9 +516,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -416,9 +527,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -428,9 +539,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -443,7 +554,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -466,9 +577,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -499,9 +610,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -514,49 +625,120 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] -name = "is_ci" -version = "1.1.1" +name = "is-terminal" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] -name = "libc" -version = "0.2.150" +name = "lalrpop" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +dependencies = [ + "ascii-canvas", + "bit-set", + "diff", + "ena", + "is-terminal", + "itertools", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax 0.6.29", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +dependencies = [ + "regex", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -565,10 +747,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -581,33 +769,39 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" -version = "0.32.1" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] @@ -624,15 +818,44 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + [[package]] name = "parse-flake-lock" -version = "0.1.0" +version = "0.1.1" dependencies = [ "serde", "serde_json", "thiserror", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -641,9 +864,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -652,9 +875,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -662,9 +885,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", @@ -675,9 +898,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -685,10 +908,29 @@ dependencies = [ ] [[package]] -name = "pin-project-lite" -version = "0.2.13" +name = "petgraph" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -697,10 +939,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "proc-macro2" -version = "1.0.81" +name = "precomputed-hash" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -715,10 +963,65 @@ dependencies = [ ] [[package]] -name = "reqwest" -version = "0.11.22" +name = "redox_syscall" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64", "bytes", @@ -743,6 +1046,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-rustls", @@ -756,42 +1060,43 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.5" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.11" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", @@ -831,20 +1136,32 @@ dependencies = [ ] [[package]] -name = "ryu" -version = "1.0.15" +name = "rustversion" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sct" version = "0.7.1" @@ -857,11 +1174,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -870,9 +1187,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -880,18 +1197,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.199" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -900,9 +1217,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -932,6 +1249,12 @@ dependencies = [ "digest", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -942,23 +1265,19 @@ dependencies = [ ] [[package]] -name = "socket2" -version = "0.4.10" +name = "smallvec" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -968,16 +1287,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "syn" -version = "2.0.60" +name = "string_cache" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "syn" +version = "2.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -999,6 +1337,17 @@ dependencies = [ "libc", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "terminal_size" version = "0.3.0" @@ -1006,23 +1355,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -1030,10 +1379,19 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tiny-keccak" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" dependencies = [ "tinyvec_macros", ] @@ -1046,18 +1404,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", - "socket2 0.5.5", - "windows-sys", + "socket2", + "windows-sys 0.48.0", ] [[package]] @@ -1072,16 +1429,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -1111,9 +1467,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -1129,9 +1485,9 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1141,13 +1497,19 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "untrusted" version = "0.9.0" @@ -1156,9 +1518,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -1188,9 +1550,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1198,9 +1560,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -1213,9 +1575,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.38" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1225,9 +1587,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1235,9 +1597,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -1248,15 +1610,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -1286,11 +1648,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", ] [[package]] @@ -1299,7 +1661,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", ] [[package]] @@ -1308,13 +1679,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -1323,42 +1710,90 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "winreg" version = "0.50.0" @@ -1366,5 +1801,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] diff --git a/Cargo.toml b/Cargo.toml index f5abc4d..e12a6fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "flake-checker" -version = "0.1.20" +version = "0.2.0" edition = "2021" [workspace] +resolver = "2" members = [".", "parse-flake-lock"] [workspace.dependencies] @@ -13,11 +14,8 @@ serde_json = { version = "1.0.100", default-features = false, features = [ ] } thiserror = { version = "1.0.40", default-features = false } -[features] -default = [] -allowed-refs = [] - [dependencies] +cel-interpreter = { version = "0.7.1", default-features = false } chrono = { version = "0.4.25", default-features = false, features = ["clock"] } clap = { version = "4.3.0", default-features = false, features = [ "derive", @@ -27,8 +25,7 @@ clap = { version = "4.3.0", default-features = false, features = [ ] } handlebars = { version = "4.3.7", default-features = false } is_ci = "1.1.1" -once_cell = { version = "1.19.0", default-features = false } -parse-flake-lock = { path = "parse-flake-lock" } +parse-flake-lock = { path = "./parse-flake-lock" } reqwest = { version = "0.11.18", default-features = false, features = [ "blocking", "json", @@ -38,3 +35,7 @@ serde = { workspace = true } serde_json = { workspace = true } sha2 = { version = "0.10.6", default-features = false } thiserror = { workspace = true } + +[features] +default = [] +allowed-refs = [] diff --git a/README.md b/README.md index 33344dc..b0f836e 100644 --- a/README.md +++ b/README.md @@ -14,21 +14,83 @@ nix run github:DeterminateSystems/flake-checker nix run github:DeterminateSystems/flake-checker /path/to/flake.lock ``` -Nix Flake Checker looks at your `flake.lock`'s root-level [Nixpkgs] inputs and checks that: +Nix Flake Checker looks at your `flake.lock`'s root-level [Nixpkgs] inputs. +There are two ways to express flake policies: -- Any explicit Nixpkgs Git refs are in this list: - - `nixos-23.11` - - `nixos-23.11-small` - - `nixos-unstable` - - `nixos-unstable-small` - - `nixpkgs-23.11-darwin` - - `nixpkgs-unstable` -- Any Nixpkgs dependencies are less than 30 days old -- Any Nixpkgs dependencies have the [`NixOS`][nixos-org] org as the GitHub owner (and thus that the dependency isn't a fork or non-upstream variant) +* Via [config parameters](#parameters). +* Via [policy conditions](#policy-conditions) using [Common Expression Language][cel] (CEL). If you're running it locally, Nix Flake Checker reports any issues via text output in your terminal. But you can also use Nix Flake Checker [in CI](#the-flake-checker-action). +## Supported branches + +At any given time, [Nixpkgs] has a bounded set of branches that are considered *supported*. +The current list: + + * `nixos-23.11` + * `nixos-23.11-small` + * `nixos-24.05` + * `nixos-24.05-small` + * `nixos-unstable` + * `nixos-unstable-small` + * `nixpkgs-23.11-darwin` + * `nixpkgs-24.05-darwin` + * `nixpkgs-unstable` + +## Parameters + +By default, Flake Checker verifies that: + +- Any explicit Nixpkgs Git refs are in the [supported list](#supported-branches). +- Any Nixpkgs dependencies are less than 30 days old. +- Any Nixpkgs dependencies have the [`NixOS`][nixos-org] org as the GitHub owner (and thus that the dependency isn't a fork or non-upstream variant). + +You can adjust this behavior via configuration (all are enabled by default but you can disable them): + +Flag | Environment variable | Action | Default +:----|:---------------------|:-------|:------- +`--check-outdated` | `NIX_FLAKE_CHECKER_CHECK_OUTDATED` | Check for outdated Nixpkgs inputs | `true` +`--check-owner` | `NIX_FLAKE_CHECKER_CHECK_OWNER` | Check that Nixpkgs inputs have `NixOS` as the GitHub owner | `true` +`--check-supported` | `NIX_FLAKE_CHECKER_CHECK_SUPPORTED` | Check that Git refs for Nixpkgs inputs are supported | `true` + +## Policy conditions + +You can apply a CEL condition to your flake using the `--condition` flag. +Here's an example: + +```shell +flake-checker --condition "has(numDaysOld) && numDaysOld < 365" +``` + +This would check that each Nixpkgs input in your `flake.lock` is less than 365 days old. +These variables are available in each condition: + +Variable | Description +:--------|:----------- +`gitRef` | The Git reference of the input. +`numDaysOld` | The number of days old the input is. +`owner` | The input's owner (if a GitHub input). +`supportedRefs` | A list of [supported Git refs](#supported-branches) (all are branch names). + +We recommend a condition *at least* this stringent: + +```ruby +supportedRefs.contains(gitRef) && (has(numDaysOld) && numDaysOld < 30) && owner == 'NixOS' +``` + +Note that not all Nixpkgs inputs have a `numDaysOld` field, so make sure to ensure that that field exists when checking for the number of days. + +Here are some other example conditions: + +```ruby +# Updated in the last two weeks +supportedRefs.contains(gitRef) && (has(numDaysOld) && numDaysOld < 14) && owner == 'NixOS' + +# Check for most recent stable Nixpkgs +gitRef.contains("24.05") +``` + ## The Nix Flake Checker Action You can automate Nix Flake Checker by adding Determinate Systems' [Nix Flake Checker Action][action] to your GitHub Actions workflows: @@ -96,6 +158,7 @@ The `parse-flake-lock` crate doesn't yet exhaustively parse all input node types If you'd like to help make the parser more exhaustive, [pull requests][prs] are quite welcome. [action]: https://github.com/DeterminateSystems/flake-checker-action +[cel]: https://cel.dev [detsys]: https://determinate.systems [flakes]: https://zero-to-nix.com/concepts/flakes [install]: https://zero-to-nix.com/start/install diff --git a/crane.nix b/crane.nix index 26ee0b9..97636a0 100644 --- a/crane.nix +++ b/crane.nix @@ -12,7 +12,7 @@ let inherit (stdenv.hostPlatform) system; - nightlyVersion = "2023-05-01"; + nightlyVersion = "2024-06-13"; rustNightly = pkgs.rust-bin.nightly.${nightlyVersion}.default.override { extensions = [ "rust-src" "rust-analyzer-preview" ]; targets = cargoTargets; @@ -80,7 +80,7 @@ let # The Rust toolchain from rust-overlay has a dynamic libiconv in depsTargetTargetPropagated # Our static libiconv needs to take precedence ++ lib.optionals pkgs.stdenv.isDarwin [ - (libiconv.override { enableStatic = true; enableShared = false; }) + libiconv ]; cargoExtraArgs = "--target ${crossPlatform.rustTargetSpec}"; diff --git a/flake.lock b/flake.lock index 6bacff9..3c096d3 100644 --- a/flake.lock +++ b/flake.lock @@ -2,31 +2,26 @@ "nodes": { "crane": { "inputs": { - "flake-compat": [ - "flake-compat" - ], - "flake-utils": [ - "flake-utils" - ], "nixpkgs": [ "nixpkgs" - ], - "rust-overlay": "rust-overlay" + ] }, "locked": { - "narHash": "sha256-ASliYUzlN/aTGDZ2d0FIqxq5fiz+Cwk0q2rYXgy4pB0=", - "rev": "8cb0282cb7c7b5ad7ce1c47d48f647836f8924a0", - "revCount": 432, + "lastModified": 1717383740, + "narHash": "sha256-559HbY4uhNeoYvK3H6AMZAtVfmR3y8plXZ1x6ON/cWU=", + "rev": "b65673fce97d277934488a451724be94cc62499a", + "revCount": 580, "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/ipetkov/crane/0.14.2/018b3503-625a-71c8-96ff-c86e61bd12f7/source.tar.gz" + "url": "https://api.flakehub.com/f/pinned/ipetkov/crane/0.17.3/018fdc0e-176b-7a0f-92ce-cc2d0db7b735/source.tar.gz" }, "original": { "type": "tarball", - "url": "https://flakehub.com/f/ipetkov/crane/0.14.%2A.tar.gz" + "url": "https://flakehub.com/f/ipetkov/crane/0.17.%2A" } }, "flake-compat": { "locked": { + "lastModified": 1696426674, "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "revCount": 57, @@ -35,89 +30,43 @@ }, "original": { "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.0.1.tar.gz" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", - "type": "github" - }, - "original": { - "id": "flake-utils", - "type": "indirect" + "url": "https://flakehub.com/f/edolstra/flake-compat/1.0.1" } }, "nixpkgs": { "locked": { - "lastModified": 1704290814, - "narHash": "sha256-LWvKHp7kGxk/GEtlrGYV68qIvPHkU9iToomNFGagixU=", - "rev": "70bdadeb94ffc8806c0570eb5c2695ad29f0e421", - "revCount": 492897, + "lastModified": 1717952948, + "narHash": "sha256-mJi4/gjiwQlSaxjA6AusXBN/6rQRaPCycR7bd8fydnQ=", + "rev": "2819fffa7fa42156680f0d282c60d81e8fb185b7", + "revCount": 631440, "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2305.492897%2Brev-70bdadeb94ffc8806c0570eb5c2695ad29f0e421/018ce318-b896-7d27-b495-cc2cdb39d680/source.tar.gz" + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2405.631440%2Brev-2819fffa7fa42156680f0d282c60d81e8fb185b7/0190034c-678d-7039-b45c-fa38168f2500/source.tar.gz" }, "original": { "type": "tarball", - "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2305.%2A.tar.gz" + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2405.%2A" } }, "root": { "inputs": { "crane": "crane", "flake-compat": "flake-compat", - "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay_2" + "rust-overlay": "rust-overlay" } }, "rust-overlay": { "inputs": { - "flake-utils": [ - "crane", - "flake-utils" - ], - "nixpkgs": [ - "crane", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1696299134, - "narHash": "sha256-RS77cAa0N+Sfj5EmKbm5IdncNXaBCE1BSSQvUE8exvo=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "611ccdceed92b4d94ae75328148d84ee4a5b462d", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "rust-overlay_2": { - "inputs": { - "flake-utils": [ - "flake-utils" - ], "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1697422411, - "narHash": "sha256-eCj20wEwATLm7Bd/+/wOIdbqq9jgvS6ZxMrxujX2DxU=", + "lastModified": 1719800573, + "narHash": "sha256-9DLgG4T6l7cc4pJNOCcXGUwHsFfUp8KLsiwed65MdHk=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "056256f2fcf3c5a652dbc3edba9ec1a956d41f56", + "rev": "648b25dd9c3acd255dc50c1eb3ca8b987856f675", "type": "github" }, "original": { @@ -125,21 +74,6 @@ "repo": "rust-overlay", "type": "github" } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index f8deb12..69629cd 100644 --- a/flake.nix +++ b/flake.nix @@ -1,25 +1,21 @@ { inputs = { - nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2305.*.tar.gz"; - + nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2405.*"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-utils.follows = "flake-utils"; }; crane = { - url = "https://flakehub.com/f/ipetkov/crane/0.14.*.tar.gz"; + url = "https://flakehub.com/f/ipetkov/crane/0.17.*"; inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-compat.follows = "flake-compat"; - inputs.flake-utils.follows = "flake-utils"; }; - flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.0.1.tar.gz"; + flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.0.1"; }; - outputs = { self, nixpkgs, flake-utils, rust-overlay, crane, ... }: + outputs = { self, nixpkgs, rust-overlay, crane, ... }: let supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f rec { diff --git a/parse-flake-lock/Cargo.toml b/parse-flake-lock/Cargo.toml index 9b81bdb..a0bcb51 100644 --- a/parse-flake-lock/Cargo.toml +++ b/parse-flake-lock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "parse-flake-lock" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] diff --git a/parse-flake-lock/src/lib.rs b/parse-flake-lock/src/lib.rs index 4ad1001..5dc8905 100644 --- a/parse-flake-lock/src/lib.rs +++ b/parse-flake-lock/src/lib.rs @@ -107,7 +107,10 @@ impl<'de> Deserialize<'de> for FlakeLock { let mut root_nodes = HashMap::new(); let root_node = &nodes[&root]; let Node::Root(root_node) = root_node else { - return Err(de::Error::custom(format!("root node was not a Root node, but was a {} node", root_node.variant()))); + return Err(de::Error::custom(format!( + "root node was not a Root node, but was a {} node", + root_node.variant() + ))); }; for (root_name, root_input) in root_node.inputs.iter() { @@ -204,7 +207,7 @@ pub enum Node { Indirect(IndirectNode), /// A [PathNode] flake input stemming from a filesystem path. Path(PathNode), - /// TODO + /// Nodes that point to tarball paths. Tarball(TarballNode), /// A "catch-all" variant for node types that don't (yet) have explicit struct definitions in /// this crate. @@ -372,6 +375,9 @@ pub struct TarballNode { /// Information about the tarball input that's "locked" because it's supplied by Nix. #[derive(Clone, Debug, Deserialize)] pub struct TarballLocked { + /// The timestamp for when the input was last modified. + #[serde(alias = "lastModified")] + pub last_modified: Option, /// The NAR hash of the input. #[serde(alias = "narHash")] pub nar_hash: String, diff --git a/src/condition.rs b/src/condition.rs new file mode 100644 index 0000000..5f2924d --- /dev/null +++ b/src/condition.rs @@ -0,0 +1,82 @@ +use cel_interpreter::{Context, Program, Value}; +use parse_flake_lock::{FlakeLock, Node}; + +use crate::{ + error::FlakeCheckerError, + flake::{nixpkgs_deps, num_days_old}, + issue::{Issue, IssueKind}, +}; + +const KEY_GIT_REF: &str = "gitRef"; +const KEY_NUM_DAYS_OLD: &str = "numDaysOld"; +const KEY_OWNER: &str = "owner"; +const KEY_SUPPORTED_REFS: &str = "supportedRefs"; + +pub(super) fn evaluate_condition( + flake_lock: &FlakeLock, + nixpkgs_keys: &[String], + condition: &str, + supported_refs: Vec, +) -> Result, FlakeCheckerError> { + let mut issues: Vec = vec![]; + let mut ctx = Context::default(); + ctx.add_variable_from_value(KEY_SUPPORTED_REFS, supported_refs); + + let deps = nixpkgs_deps(flake_lock, nixpkgs_keys)?; + + for (name, node) in deps { + let (git_ref, last_modified, owner) = match node { + Node::Repo(repo) => ( + repo.original.git_ref, + Some(repo.locked.last_modified), + Some(repo.original.owner), + ), + Node::Tarball(tarball) => (None, tarball.locked.last_modified, None), + _ => (None, None, None), + }; + + add_cel_variables(&mut ctx, git_ref, last_modified, owner); + + match Program::compile(condition)?.execute(&ctx) { + Ok(result) => match result { + Value::Bool(b) if !b => { + issues.push(Issue { + input: name.clone(), + kind: IssueKind::Violation, + }); + } + Value::Bool(b) if b => continue, + result => { + return Err(FlakeCheckerError::NonBooleanCondition( + result.type_of().to_string(), + )) + } + }, + Err(e) => return Err(FlakeCheckerError::CelExecution(e)), + } + } + + Ok(issues) +} + +fn add_cel_variables( + ctx: &mut Context, + git_ref: Option, + last_modified: Option, + owner: Option, +) { + ctx.add_variable_from_value(KEY_GIT_REF, value_or_empty_string(git_ref)); + ctx.add_variable_from_value( + KEY_NUM_DAYS_OLD, + value_or_zero(last_modified.map(num_days_old)), + ); + ctx.add_variable_from_value(KEY_OWNER, value_or_empty_string(owner)); +} + +fn value_or_empty_string(value: Option) -> Value { + Value::from(value.unwrap_or(String::from(""))) +} + +fn value_or_zero(value: Option) -> Value { + Value::from(value.unwrap_or(0)) +} diff --git a/src/error.rs b/src/error.rs index 377d1f5..a22ef8a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,11 +1,17 @@ #[derive(Debug, thiserror::Error)] pub enum FlakeCheckerError { + #[error("CEL execution error: {0}")] + CelExecution(#[from] cel_interpreter::ExecutionError), + #[error("CEL parsing error: {0}")] + CelParse(#[from] cel_interpreter::ParseError), #[error("env var error: {0}")] EnvVar(#[from] std::env::VarError), #[error("couldn't parse flake.lock: {0}")] FlakeLock(#[from] parse_flake_lock::FlakeLockParseError), #[error("http client error: {0}")] Http(#[from] reqwest::Error), + #[error("CEL conditions must return a Boolean but returned {0} instead")] + NonBooleanCondition(String), #[error("couldn't access flake.lock: {0}")] Io(#[from] std::io::Error), #[error("couldn't parse flake.lock: {0}")] diff --git a/src/flake.rs b/src/flake.rs index b1e9f30..84ebd93 100644 --- a/src/flake.rs +++ b/src/flake.rs @@ -30,9 +30,9 @@ impl Default for FlakeCheckConfig { } } -fn nixpkgs_deps( +pub(super) fn nixpkgs_deps( flake_lock: &FlakeLock, - keys: Vec, + keys: &[String], ) -> Result, FlakeCheckerError> { let mut deps: HashMap = HashMap::new(); @@ -49,7 +49,7 @@ fn nixpkgs_deps( } } Node::Indirect(indirect_node) => { - if &indirect_node.original.id == key { + if keys.contains(key) && &indirect_node.original.id == key { deps.insert(key.to_string(), node); } } @@ -83,29 +83,36 @@ pub(crate) fn check_flake_lock( ) -> Result, FlakeCheckerError> { let mut issues = vec![]; - let deps = nixpkgs_deps(flake_lock, config.nixpkgs_keys.clone())?; + let deps = nixpkgs_deps(flake_lock, &config.nixpkgs_keys)?; - for (name, dep) in deps { - if let Node::Repo(repo) = dep { + for (name, node) in deps { + let (git_ref, last_modified, owner) = match node { + Node::Repo(repo) => ( + repo.original.git_ref, + Some(repo.locked.last_modified), + Some(repo.original.owner), + ), + Node::Tarball(tarball) => (None, tarball.locked.last_modified, None), + _ => (None, None, None), + }; + + // Check if not explicitly supported + if let Some(git_ref) = git_ref { // Check if not explicitly supported - if config.check_supported { - if let Some(ref git_ref) = repo.original.git_ref { - if !allowed_refs.contains(git_ref) { - issues.push(Issue { - input: name.clone(), - kind: IssueKind::Disallowed(Disallowed { - reference: git_ref.to_string(), - }), - }); - } - } + if config.check_supported && !allowed_refs.contains(&git_ref) { + issues.push(Issue { + input: name.clone(), + kind: IssueKind::Disallowed(Disallowed { + reference: git_ref.to_string(), + }), + }); } + } + if let Some(last_modified) = last_modified { // Check if outdated if config.check_outdated { - let now_timestamp = Utc::now().timestamp(); - let diff = now_timestamp - repo.locked.last_modified; - let num_days_old = Duration::seconds(diff).num_days(); + let num_days_old = num_days_old(last_modified); if num_days_old > MAX_DAYS { issues.push(Issue { @@ -114,39 +121,89 @@ pub(crate) fn check_flake_lock( }); } } + } + if let Some(owner) = owner { // Check that the GitHub owner is NixOS - if config.check_owner { - let owner = repo.original.owner; - if owner.to_lowercase() != "nixos" { - issues.push(Issue { - input: name.clone(), - kind: IssueKind::NonUpstream(NonUpstream { owner }), - }); - } + if config.check_owner && owner.to_lowercase() != "nixos" { + issues.push(Issue { + input: name.clone(), + kind: IssueKind::NonUpstream(NonUpstream { owner }), + }); } } } Ok(issues) } +pub(super) fn num_days_old(timestamp: i64) -> i64 { + let now_timestamp = Utc::now().timestamp(); + let diff = now_timestamp - timestamp; + Duration::seconds(diff).num_days() +} + #[cfg(test)] mod test { use std::path::PathBuf; use crate::{ check_flake_lock, + condition::evaluate_condition, issue::{Disallowed, Issue, IssueKind, NonUpstream}, FlakeCheckConfig, FlakeLock, }; #[test] - fn test_clean_flake_locks() { - let allowed_refs: Vec = serde_json::from_str(include_str!("../allowed-refs.json")) - .expect("couldn't deserialize allowed-refs.json file"); + fn cel_conditions() { + // (condition, expected) + let cases: Vec<(&str, bool)> = vec![ + (include_str!("../tests/cel-condition.txt"), true), + ( + + "has(gitRef) && has(numDaysOld) && has(owner) && has(supportedRefs) && supportedRefs.contains(gitRef) && owner != 'NixOS'", + false, + ), + ( + + "has(gitRef) && has(numDaysOld) && has(owner) && has(supportedRefs) && supportedRefs.contains(gitRef) && owner != 'NixOS'", + false, + ), + ]; + + let supported_refs: Vec = + serde_json::from_str(include_str!("../allowed-refs.json")).unwrap(); + let path = PathBuf::from("tests/flake.cel.0.lock"); + + for (condition, expected) in cases { + let flake_lock = FlakeLock::new(&path).unwrap(); + let config = FlakeCheckConfig { + nixpkgs_keys: vec![String::from("nixpkgs")], + ..Default::default() + }; + + let result = evaluate_condition( + &flake_lock, + &config.nixpkgs_keys, + condition, + supported_refs.clone(), + ); + + if expected { + assert!(result.is_ok()); + assert!(result.unwrap().is_empty()); + } else { + assert!(!result.unwrap().is_empty()); + } + } + } + + #[test] + fn clean_flake_locks() { + let allowed_refs: Vec = + serde_json::from_str(include_str!("../allowed-refs.json")).unwrap(); for n in 0..=7 { let path = PathBuf::from(format!("tests/flake.clean.{n}.lock")); - let flake_lock = FlakeLock::new(&path).expect("couldn't create flake.lock"); + let flake_lock = FlakeLock::new(&path).unwrap(); let config = FlakeCheckConfig { check_outdated: false, ..Default::default() @@ -161,9 +218,9 @@ mod test { } #[test] - fn test_dirty_flake_locks() { - let allowed_refs: Vec = serde_json::from_str(include_str!("../allowed-refs.json")) - .expect("couldn't deserialize allowed-refs.json file"); + fn dirty_flake_locks() { + let allowed_refs: Vec = + serde_json::from_str(include_str!("../allowed-refs.json")).unwrap(); let cases: Vec<(&str, Vec)> = vec![ ( "flake.dirty.0.lock", @@ -203,22 +260,21 @@ mod test { for (file, expected_issues) in cases { let path = PathBuf::from(format!("tests/{file}")); - let flake_lock = FlakeLock::new(&path).expect("couldn't create flake.lock"); + let flake_lock = FlakeLock::new(&path).unwrap(); let config = FlakeCheckConfig { check_outdated: false, ..Default::default() }; - let issues = check_flake_lock(&flake_lock, &config, allowed_refs.clone()) - .expect("couldn't run check_flake_lock function"); + let issues = check_flake_lock(&flake_lock, &config, allowed_refs.clone()).unwrap(); dbg!(&path); assert_eq!(issues, expected_issues); } } #[test] - fn test_explicit_nixpkgs_keys() { - let allowed_refs: Vec = serde_json::from_str(include_str!("../allowed-refs.json")) - .expect("couldn't deserialize allowed-refs.json file"); + fn explicit_nixpkgs_keys() { + let allowed_refs: Vec = + serde_json::from_str(include_str!("../allowed-refs.json")).unwrap(); let cases: Vec<(&str, Vec, Vec)> = vec![( "flake.explicit-keys.0.lock", vec![String::from("nixpkgs"), String::from("nixpkgs-alt")], @@ -232,22 +288,21 @@ mod test { for (file, nixpkgs_keys, expected_issues) in cases { let path = PathBuf::from(format!("tests/{file}")); - let flake_lock = FlakeLock::new(&path).expect("couldn't create flake.lock"); + let flake_lock = FlakeLock::new(&path).unwrap(); let config = FlakeCheckConfig { check_outdated: false, nixpkgs_keys, ..Default::default() }; - let issues = check_flake_lock(&flake_lock, &config, allowed_refs.clone()) - .expect("couldn't run check_flake_lock function"); + let issues = check_flake_lock(&flake_lock, &config, allowed_refs.clone()).unwrap(); assert_eq!(issues, expected_issues); } } #[test] - fn test_missing_nixpkgs_keys() { - let allowed_refs: Vec = serde_json::from_str(include_str!("../allowed-refs.json")) - .expect("couldn't deserialize allowed-refs.json file"); + fn missing_nixpkgs_keys() { + let allowed_refs: Vec = + serde_json::from_str(include_str!("../allowed-refs.json")).unwrap(); let cases: Vec<(&str, Vec, String)> = vec![( "flake.clean.0.lock", vec![String::from("nixpkgs"), String::from("foo"), String::from("bar")], @@ -260,7 +315,7 @@ mod test { )]; for (file, nixpkgs_keys, expected_err) in cases { let path = PathBuf::from(format!("tests/{file}")); - let flake_lock = FlakeLock::new(&path).expect("couldn't create flake.lock"); + let flake_lock = FlakeLock::new(&path).unwrap(); let config = FlakeCheckConfig { check_outdated: false, nixpkgs_keys, diff --git a/src/issue.rs b/src/issue.rs index f0ccb6c..28e0657 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -12,6 +12,7 @@ pub(crate) enum IssueKind { Disallowed(Disallowed), Outdated(Outdated), NonUpstream(NonUpstream), + Violation, } #[derive(Clone, Debug, PartialEq, Serialize)] @@ -41,4 +42,8 @@ impl IssueKind { pub(crate) fn is_non_upstream(&self) -> bool { matches!(self, Self::NonUpstream(_)) } + + pub(crate) fn is_violation(&self) -> bool { + matches!(self, Self::Violation) + } } diff --git a/src/main.rs b/src/main.rs index a3704c3..a029aa2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #[cfg(feature = "allowed-refs")] mod allowed_refs; +mod condition; mod error; mod flake; mod issue; @@ -16,6 +17,8 @@ use std::process::ExitCode; use clap::Parser; use parse_flake_lock::FlakeLock; +use crate::condition::evaluate_condition; + /// A flake.lock checker for Nix projects. #[derive(Parser)] #[command(author, version, about, long_about = None)] @@ -86,6 +89,10 @@ struct Cli { )] markdown_summary: bool, + /// The Common Expression Language (CEL) policy to apply to each Nixpkgs input. + #[arg(long, short, env = "NIX_FLAKE_CHECKER_CONDITION")] + condition: Option, + #[cfg(feature = "allowed-refs")] // Check to make sure that Flake Checker is aware of the current supported branches. #[arg(long, hide = true)] @@ -98,8 +105,8 @@ struct Cli { } fn main() -> Result { - let allowed_refs: Vec = serde_json::from_str(include_str!("../allowed-refs.json")) - .expect("couldn't deserialize allowed-refs.json file"); + let allowed_refs: Vec = + serde_json::from_str(include_str!("../allowed-refs.json")).unwrap(); let Cli { no_telemetry, @@ -111,6 +118,7 @@ fn main() -> Result { fail_mode, nixpkgs_keys, markdown_summary, + condition, #[cfg(feature = "allowed-refs")] check_allowed_refs, #[cfg(feature = "allowed-refs")] @@ -166,17 +174,27 @@ fn main() -> Result { check_supported, check_outdated, check_owner, - nixpkgs_keys, + nixpkgs_keys: nixpkgs_keys.clone(), fail_mode, }; - let issues = check_flake_lock(&flake_lock, &flake_check_config, allowed_refs.clone())?; + let issues = if let Some(condition) = &condition { + evaluate_condition(&flake_lock, &nixpkgs_keys, condition, allowed_refs.clone())? + } else { + check_flake_lock(&flake_lock, &flake_check_config, allowed_refs.clone())? + }; if !no_telemetry { telemetry::TelemetryReport::make_and_send(&issues); } - let summary = Summary::new(&issues, flake_lock_path, flake_check_config, allowed_refs); + let summary = Summary::new( + &issues, + flake_lock_path, + flake_check_config, + allowed_refs, + condition, + ); if std::env::var("GITHUB_ACTIONS").is_ok() { if markdown_summary { diff --git a/src/summary.rs b/src/summary.rs index 63d9371..83d6a2d 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -10,14 +10,24 @@ use std::path::PathBuf; use handlebars::Handlebars; use serde_json::json; -static MARKDOWN_TEMPLATE: &str = include_str!(concat!( +static CEL_MARKDOWN_TEMPLATE: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/src/templates/summary_md.hbs" + "/src/templates/summary.cel.md.hbs" )); -static TEXT_TEMPLATE: &str = include_str!(concat!( +static CEL_TEXT_TEMPLATE: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/src/templates/summary_txt.hbs" + "/src/templates/summary.cel.txt.hbs" +)); + +static STANDARD_MARKDOWN_TEMPLATE: &str = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/src/templates/summary.standard.md.hbs" +)); + +static STANDARD_TEXT_TEMPLATE: &str = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/src/templates/summary.standard.txt.hbs" )); pub(crate) struct Summary { @@ -25,6 +35,7 @@ pub(crate) struct Summary { data: serde_json::Value, flake_lock_path: PathBuf, flake_check_config: FlakeCheckConfig, + condition: Option, } impl Summary { @@ -33,37 +44,62 @@ impl Summary { flake_lock_path: PathBuf, flake_check_config: FlakeCheckConfig, allowed_refs: Vec, + condition: Option, ) -> Self { - let disallowed: Vec<&Issue> = issues.iter().filter(|i| i.kind.is_disallowed()).collect(); - let outdated: Vec<&Issue> = issues.iter().filter(|i| i.kind.is_outdated()).collect(); - let non_upstream: Vec<&Issue> = - issues.iter().filter(|i| i.kind.is_non_upstream()).collect(); + let num_issues = issues.len(); + let clean = issues.is_empty(); + let issue_word = if issues.len() == 1 { "issue" } else { "issues" }; - let data = json!({ - "issues": issues, - "num_issues": issues.len(), - "clean": issues.is_empty(), - "dirty": !issues.is_empty(), - "issue_word": if issues.len() == 1 { "issue" } else { "issues" }, - // Disallowed refs - "has_disallowed": !disallowed.is_empty(), - "disallowed": disallowed, - // Outdated refs - "has_outdated": !outdated.is_empty(), - "outdated": outdated, - // Non-upstream refs - "has_non_upstream": !non_upstream.is_empty(), - "non_upstream": non_upstream, - // Constants - "max_days": MAX_DAYS, - "supported_ref_names": allowed_refs, - }); + let data = if let Some(condition) = &condition { + let inputs_with_violations: Vec = issues + .iter() + .filter(|i| i.kind.is_violation()) + .map(|i| i.input.to_owned()) + .collect(); + + json!({ + "issues": issues, + "num_issues": num_issues, + "clean": clean, + "dirty": !clean, + "issue_word": issue_word, + "condition": condition, + "inputs_with_violations": inputs_with_violations, + }) + } else { + let disallowed: Vec<&Issue> = + issues.iter().filter(|i| i.kind.is_disallowed()).collect(); + let outdated: Vec<&Issue> = issues.iter().filter(|i| i.kind.is_outdated()).collect(); + let non_upstream: Vec<&Issue> = + issues.iter().filter(|i| i.kind.is_non_upstream()).collect(); + + json!({ + "issues": issues, + "num_issues": num_issues, + "clean": clean, + "dirty": !clean, + "issue_word": issue_word, + // Disallowed refs + "has_disallowed": !disallowed.is_empty(), + "disallowed": disallowed, + // Outdated refs + "has_outdated": !outdated.is_empty(), + "outdated": outdated, + // Non-upstream refs + "has_non_upstream": !non_upstream.is_empty(), + "non_upstream": non_upstream, + // Constants + "max_days": MAX_DAYS, + "supported_ref_names": allowed_refs, + }) + }; Self { issues: issues.to_vec(), data, flake_lock_path, flake_check_config, + condition, } } @@ -72,6 +108,18 @@ impl Summary { if self.issues.is_empty() { println!("The Determinate Nix Flake Checker scanned {file} and found no issues"); + return Ok(()); + } + + if let Some(condition) = &self.condition { + println!( + "You supplied this CEL condition for your flake:\n\n{}", + condition + ); + println!("The following inputs violate that condition:\n"); + for issue in self.issues.iter() { + println!("* {}", issue.input); + } } else { let level = if self.flake_check_config.fail_mode { "error" @@ -113,6 +161,7 @@ impl Summary { None } } + IssueKind::Violation => Some(String::from("policy violation")), }; if let Some(message) = message { @@ -124,10 +173,16 @@ impl Summary { } pub fn generate_markdown(&self) -> Result<(), FlakeCheckerError> { + let template = if self.condition.is_some() { + CEL_MARKDOWN_TEMPLATE + } else { + STANDARD_MARKDOWN_TEMPLATE + }; + let mut handlebars = Handlebars::new(); handlebars - .register_template_string("summary.md", MARKDOWN_TEMPLATE) + .register_template_string("summary.md", template) .map_err(Box::new)?; let summary_md = handlebars.render("summary.md", &self.data)?; @@ -142,9 +197,15 @@ impl Summary { } pub fn generate_text(&self) -> Result<(), FlakeCheckerError> { + let template = if self.condition.is_some() { + CEL_TEXT_TEMPLATE + } else { + STANDARD_TEXT_TEMPLATE + }; + let mut handlebars = Handlebars::new(); handlebars - .register_template_string("summary.txt", TEXT_TEMPLATE) + .register_template_string("summary.txt", template) .map_err(Box::new)?; let summary_txt = handlebars.render("summary.txt", &self.data)?; diff --git a/src/templates/summary.cel.md.hbs b/src/templates/summary.cel.md.hbs new file mode 100644 index 0000000..86edcca --- /dev/null +++ b/src/templates/summary.cel.md.hbs @@ -0,0 +1,23 @@ +# ![](https://avatars.githubusercontent.com/u/80991770?s=30) Flake checkup + +{{#if clean}} +The Determinate Flake Checker Action scanned your `flake.lock` and didn't identify any issues. +All Nixpkgs inputs conform to the flake policy expressed in your supplied [Common Expression Language](https://cel.dev) condition. +{{/if}} + +{{#if dirty}} +⚠️ The Determinate Nix Installer Action scanned your `flake.lock` and discovered {{num_issues}} {{issue_word}} that we recommend looking into. +You supplied this CEL condition: + +```ruby +{{condition}} +``` + +The following inputs violate that condition: + +{{#each inputs_with_violations}} +* `{{this}}` +{{/each}} +{{/if}} + +

Feedback? Let us know at DeterminateSystems/flake-checker.

diff --git a/src/templates/summary.cel.txt.hbs b/src/templates/summary.cel.txt.hbs new file mode 100644 index 0000000..2596e27 --- /dev/null +++ b/src/templates/summary.cel.txt.hbs @@ -0,0 +1,19 @@ +Flake checker results: + +{{#if clean}} +The flake checker scanned your flake.lock and didn't identify any issues. You specified this CEL +condition: + +{{{condition}}} + +All Nixpkgs inputs satisfy this condition. +{{/if}} +{{#if dirty}} +The flake checker scanned your flake.lock and discovered {{num_issues}} {{issue_word}} +that we recommend looking into. Here are the inputs that violate your supplied +condition: + +{{#each inputs_with_violations}} +* {{this}} +{{/each}} +{{/if}} \ No newline at end of file diff --git a/src/templates/summary_md.hbs b/src/templates/summary.standard.md.hbs similarity index 99% rename from src/templates/summary_md.hbs rename to src/templates/summary.standard.md.hbs index 27afa50..e59e3be 100644 --- a/src/templates/summary_md.hbs +++ b/src/templates/summary.standard.md.hbs @@ -110,4 +110,4 @@ While upstream Nixpkgs isn't bull {{/if}} {{/if}} -

Feedback? Let us know at DeterminateSystems/flake-checker.

\ No newline at end of file +

Feedback? Let us know at DeterminateSystems/flake-checker.

diff --git a/src/templates/summary_txt.hbs b/src/templates/summary.standard.txt.hbs similarity index 100% rename from src/templates/summary_txt.hbs rename to src/templates/summary.standard.txt.hbs diff --git a/tests/cel-condition.txt b/tests/cel-condition.txt new file mode 100644 index 0000000..7231db3 --- /dev/null +++ b/tests/cel-condition.txt @@ -0,0 +1,6 @@ +supportedRefs == ['nixos-24.05', 'nixos-24.05-small', 'nixos-unstable', 'nixos-unstable-small', 'nixpkgs-24.05-darwin', 'nixpkgs-unstable'] + && owner == 'NixOS' + && gitRef == 'nixos-unstable' + && supportedRefs.contains(gitRef) + && has(numDaysOld) + && numDaysOld > 0 diff --git a/tests/flake.cel.0.lock b/tests/flake.cel.0.lock new file mode 100644 index 0000000..c2d0d5f --- /dev/null +++ b/tests/flake.cel.0.lock @@ -0,0 +1,154 @@ +{ + "nodes": { + "crane": { + "inputs": { + "flake-compat": [ + "flake-compat" + ], + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1684468982, + "narHash": "sha256-EoC1N5sFdmjuAP3UOkyQujSOT6EdcXTnRw8hPjJkEgc=", + "owner": "ipetkov", + "repo": "crane", + "rev": "99de890b6ef4b4aab031582125b6056b792a4a30", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1686960236, + "narHash": "sha256-AYCC9rXNLpUWzD9hm+askOfpliLEC9kwAo7ITJc4HIw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "04af42f3b31dba0ef742d254456dc4c14eedac86", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay_2" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": [ + "crane", + "flake-utils" + ], + "nixpkgs": [ + "crane", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1683080331, + "narHash": "sha256-nGDvJ1DAxZIwdn6ww8IFwzoHb2rqBP4wv/65Wt5vflk=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "d59c3fa0cba8336e115b376c2d9e91053aa59e56", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1684808436, + "narHash": "sha256-WG5LgB1+Oguj4H4Bpqr5GoLSc382LyGlaToiOw5xhwA=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "a227d4571dd1f948138a40ea8b0d0c413eefb44b", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +}