diff --git a/.gitignore b/.gitignore index 4e4bf76..9fd298b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ pulumi-state/.pulumi/history pulumi-state/.pulumi/backups .pre-commit-config.yaml +**target/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9b22392 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,879 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "config" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" +dependencies = [ + "async-trait", + "convert_case", + "json5", + "lazy_static", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", + "yaml-rust", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[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 = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "ordered-multimap" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" +dependencies = [ + "dlv-list", + "hashbrown 0.13.2", +] + +[[package]] +name = "pathdiff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" + +[[package]] +name = "pcre2" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be55c43ac18044541d58d897e8f4c55157218428953ebd39d86df3ba0286b2b" +dependencies = [ + "libc", + "log", + "pcre2-sys", +] + +[[package]] +name = "pcre2-sys" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "550f5d18fb1b90c20b87e161852c10cde77858c3900c5059b5ad2a1449f11d8a" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "pest" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "postbuildstepper" +version = "0.1.0" +dependencies = [ + "anyhow", + "config", + "env_logger", + "log", + "pcre2", + "serde_json", + "tempfile", +] + +[[package]] +name = "proc-macro2" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64", + "bitflags", + "serde", + "serde_derive", +] + +[[package]] +name = "rust-ini" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e185e337f816bc8da115b8afcb3324006ccc82eeaddf35113888d3bd8e44ac" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[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_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5af4709 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,4 @@ +[workspace] +resolver = "2" + +members = ["applications/postbuildstepper"] diff --git a/applications/postbuildstepper/Cargo.lock b/applications/postbuildstepper/Cargo.lock deleted file mode 100644 index 0027257..0000000 --- a/applications/postbuildstepper/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "postbuildstepper" -version = "0.1.0" diff --git a/applications/postbuildstepper/Cargo.toml b/applications/postbuildstepper/Cargo.toml index 13aaabf..e6422a5 100644 --- a/applications/postbuildstepper/Cargo.toml +++ b/applications/postbuildstepper/Cargo.toml @@ -6,3 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0.90" +config = { version = "0.14.0", features = ["json", "json5", "toml"] } +env_logger = "0.11.5" +log = "0.4.22" +pcre2 = "0.2.9" +serde_json = "1.0.132" +tempfile = "3.13.0" diff --git a/applications/postbuildstepper/src/main.rs b/applications/postbuildstepper/src/main.rs index e7a11a9..943a311 100644 --- a/applications/postbuildstepper/src/main.rs +++ b/applications/postbuildstepper/src/main.rs @@ -1,3 +1,333 @@ -fn main() { - println!("Hello, world!"); +/// This application is designed to be executed from within buildbot-nix in a postBuildStep. +/// It currently hardcodes assumptions that are specific to Holo/Holochain's build environment. +/// +use anyhow::{Context, Ok}; +use business::SigningAndCopyInfo; +use log::{info, warn}; +use std::collections::HashMap; + +fn main() -> anyhow::Result<()> { + env_logger::builder() + .filter_level(log::LevelFilter::Debug) + .init(); + + let build_info = business::BuildInfo::from_env(); + + let _ = business::check_owners(build_info.try_owners()?); + + let SigningAndCopyInfo { + signing_key_file, + copy_envs, + copy_destination, + } = if let Some(info) = business::may_get_signing_key_and_copy_info(&build_info)? { + info + } else { + warn!("got no signing/uploading credentials, exiting."); + return Ok(()); + }; + + if !business::evaluate_filters(&build_info)? { + warn!("excluded by filters, exiting."); + return Ok(()); + } + + let signing_key_file_path = util::try_to_str(signing_key_file.path())?; + + let store_path = build_info.try_out_path()?; + + // sign the store path + util::nix_cmd_helper( + [ + "store", + "sign", + "--verbose", + "--recursive", + "--key-file", + signing_key_file_path, + &store_path, + ], + HashMap::<&&str, &str>::new(), + )?; + info!("successfully signed store path {store_path}"); + + // copy the store path + util::nix_cmd_helper( + ["copy", "--verbose", "--to", ©_destination, &store_path], + copy_envs.iter().map(|(k, v)| (k, v.path().as_os_str())), + ) + .context(format!("pushing {store_path} to {copy_destination}"))?; + info!("successfully pushed store path {store_path}"); + + Ok(()) +} + +mod util { + use std::{ffi::OsStr, path::Path, process::Stdio}; + + use anyhow::{bail, Context}; + + pub(crate) fn nix_cmd_helper(args: I, envs: J) -> anyhow::Result<()> + where + I: IntoIterator, + J: IntoIterator, + K: AsRef, + V: AsRef, + L: AsRef, + { + let mut cmd = std::process::Command::new("nix"); + cmd.args(args) + .envs(envs) + // pass stdio through so it becomes visible in the log + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()); + + let context = format!("running {cmd:#?}"); + + let mut spawned = cmd.spawn().context(context.clone())?; + let finished = spawned.wait().context(context.clone())?; + if !finished.success() { + bail!("{context} failed."); + } + + Ok(()) + } + + pub(crate) fn try_to_str(p: &Path) -> Result<&str, anyhow::Error> { + let signing_key_file_path = p.to_str().ok_or_else(|| { + anyhow::anyhow!( + "could not convert {} (lossy) to string", + p.to_string_lossy() + ) + })?; + + Ok(signing_key_file_path) + } +} + +mod business { + use std::{ + collections::{HashMap, HashSet}, + ffi::OsString, + io::Write, + rc::Rc, + }; + + use anyhow::{bail, Context, Result}; + use log::{debug, info, trace, warn}; + use tempfile::NamedTempFile; + + #[derive(Debug)] + pub(crate) struct BuildInfo(HashMap); + + // FIXME: is hardocing these in a type and functions sustainable, or is a config map appropriate? + impl BuildInfo { + // example var: 'PROP_project=holochain/holochain-infra + pub(crate) fn from_env() -> Self { + let env_vars = HashMap::::from_iter(std::env::vars()); + + let new_self = Self(env_vars); + trace!("env vars: {new_self:#?}"); + + new_self + } + fn get(&self, var: &str) -> Result<&String> { + self.0 + .get(var) + .ok_or_else(|| anyhow::anyhow!("looking up {var} in {self:#?}")) + } + + pub(crate) fn try_owners(&self) -> Result> { + let value = self.get("PROP_owners")?; + let vec: Vec = serde_json::from_str(&value.replace("\'", "\"")) + .context(format!("parsing {value:?} as JSON"))?; + + Ok(HashSet::from_iter(vec)) + } + pub(crate) fn try_org_repo(&self) -> Result<(&str, &str)> { + let value = self.get("PROP_project")?; + + if let Some(split) = value.split_once("/") { + Ok(split) + } else { + bail!("couldn't parse project {value}"); + } + } + + pub(crate) fn try_attr(&self) -> Result<&String> { + self.get("PROP_attr") + } + + pub(crate) fn try_out_path(&self) -> Result { + let var = "PROP_out_path"; + let from_env = self.get(var)?; + let canonical = std::fs::canonicalize(from_env) + .context(format!("canonicalizing value from {var}: '{from_env}'"))?; + let displayed = crate::util::try_to_str(&canonical)?; + + Ok(displayed.to_string()) + } + + /// Example: PROP_repository=https://github.com/holochain/holochain-infra + pub(crate) fn try_repository(&self) -> Result<&String> { + self.get("PROP_repository") + } + } + + /// Verifies that the build current owners are trusted. + // FIXME: make trusted owners configurable + pub(crate) fn check_owners(owners: HashSet) -> anyhow::Result<()> { + const TRUSTED_OWNERS: [&str; 1] = ["steveej"]; + let trusted_owners = HashSet::::from_iter(TRUSTED_OWNERS.map(ToString::to_string)); + let owner_is_trusted = owners.is_subset(&trusted_owners); + if !owner_is_trusted { + bail!("{owners:?} are *NOT* trusted!"); + } + info!("owners {owners:?} are trusted! proceeding."); + + Ok(()) + } + + /// Contains information to sign and upload the build results + pub(crate) struct SigningAndCopyInfo { + pub(crate) signing_key_file: NamedTempFile, + pub(crate) copy_envs: HashMap, + pub(crate) copy_destination: String, + } + + /// Evaluates the project org and accordingly returns a signing key. + pub(crate) fn may_get_signing_key_and_copy_info( + build_info: &BuildInfo, + ) -> anyhow::Result> { + let (org, _) = build_info.try_org_repo()?; + + let wrap_secret_in_tempfile = |s: &str| -> anyhow::Result<_> { + let mut tempfile = NamedTempFile::new()?; + tempfile.write_all(s.as_bytes())?; + Ok(tempfile) + }; + + if org == "Holo-Host" { + // FIXME: create a constant or config value for this + let signing_secret = build_info.get("SECRET_cacheHoloHost2secret")?; + let copy_envs = HashMap::from_iter([( + // FIXME: create a constant or config value for this + OsString::from("AWS_SHARED_CREDENTIALS_FILE"), + wrap_secret_in_tempfile(build_info.get("SECRET_awsSharedCredentialsFile")?)?, + )]); + + let copy_destination = { + // FIXME: create a config map for all the below + + let s3_bucket = "cache.holo.host"; + let s3_endpoint = "s3.wasabisys.com"; + let s3_profile = "cache-holo-host-s3-wasabi"; + + format!("s3://{s3_bucket}?") + + &[ + vec![ + format!("endpoint={s3_endpoint}"), + format!("profile={s3_profile}"), + ], + [ + "log-compression=br", + "ls-compression=br", + "parallel-compression=1", + "write-nar-listing=1", + ] + .into_iter() + .map(ToString::to_string) + .collect(), + ] + .concat() + .join("&") + }; + + Ok(Some(SigningAndCopyInfo { + signing_key_file: wrap_secret_in_tempfile(signing_secret)?, + copy_envs, + copy_destination, + })) + } else if org == "holochain" { + info!("{org} doesn't have any credentials for signing and copying builds."); + Ok(None) + } else { + bail!("unknown org: {org}") + } + } + + pub(crate) fn evaluate_filters(build_info: &BuildInfo) -> Result { + let is_match_lossy = |re: &str, attr: &str, prefix: &str| -> anyhow::Result { + let compiled_re = pcre2::bytes::Regex::new(re)?; + let is_match = compiled_re.is_match(attr.as_bytes())?; + + debug!("[{attr}/{prefix}]: '{re}' matched '{attr}': {is_match}"); + + Ok(is_match) + }; + + const HOLOCHAIN_INFRA_REPO: &str = "https://github.com/holochain/holochain-infra"; + const HOLO_NIXPKGS_REPO: &str = "https://github.com/Holo-Host/holo-nixpkgs"; + #[derive(Default)] + struct Filters { + include_filters_re: Rc<[Rc]>, + exclude_filters_re: Rc<[Rc]>, + } + + let filters_by_repo = HashMap::<_, _>::from_iter([ + ( + HOLOCHAIN_INFRA_REPO, + Filters { + include_filters_re: ["aarch64-[^.]+.postbuildstepper-testpkg"] + .map(Into::into) + .into(), + exclude_filters_re: [].into(), + }, + ), + ( + HOLO_NIXPKGS_REPO, + Filters { + include_filters_re: [ + "aarch64-[^.]+\\.postbuildstepper-testpkg", + ".*\\.holo-nixpkgs-release", + ] + .map(Into::into) + .into(), + exclude_filters_re: [".*tests.*".into()].into(), + }, + ), + ]); + let repo = build_info.try_repository()?; + let attr = build_info.try_attr()?; + + let conclusion = if let Some(filters) = filters_by_repo.get(repo.as_str()) { + let include = filters + .include_filters_re + .iter() + .try_fold(false, |prev, re| { + anyhow::Ok(prev || is_match_lossy(re, attr, "include")?) + })?; + + let exclude = filters + .exclude_filters_re + .iter() + .try_fold(false, |prev, re| { + anyhow::Ok(prev || is_match_lossy(re, attr, "include")?) + })?; + + let conclusion = include && !exclude; + + debug!("[{attr}]: include: {include}, exclude: {exclude}, conclusion: {conclusion}"); + conclusion + } else { + warn!("no filters found for {repo}"); + false + }; + + Ok(conclusion) + } +} + +#[cfg(test)] +mod tests { + // there's an integration test using nixos VM testing library. see `modules/flake-parts/packages.postbuildstepper/default.nix` } diff --git a/flake.lock b/flake.lock index 5e3d8ff..2c9aba4 100644 --- a/flake.lock +++ b/flake.lock @@ -996,6 +996,21 @@ "type": "github" } }, + "nix-filter_3": { + "locked": { + "lastModified": 1710156097, + "narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "3342559a24e85fc164b295c3444e8a139924675b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nix_2": { "inputs": { "lowdown-src": "lowdown-src_2", @@ -1406,6 +1421,7 @@ "keys_steveej": "keys_steveej", "keys_thetasinner": "keys_thetasinner", "microvm": "microvm", + "nix-filter": "nix-filter_3", "nixos-anywhere": "nixos-anywhere", "nixos-generators": "nixos-generators", "nixos-vscode-server": "nixos-vscode-server", diff --git a/flake.nix b/flake.nix index 6616656..b7c0174 100644 --- a/flake.nix +++ b/flake.nix @@ -3,6 +3,8 @@ flake-utils.url = "github:numtide/flake-utils"; flake-compat.url = "github:edolstra/flake-compat"; + nix-filter.url = "github:numtide/nix-filter"; + nixpkgs.follows = "nixpkgs-24-05"; nixpkgs-23-11 = { url = "github:nixos/nixpkgs/nixos-23.11"; @@ -250,6 +252,7 @@ ... }: let + # TODO(backlog): enable rust formatting treefmtConfig = { projectRootFile = "flake.nix"; programs = { @@ -299,8 +302,30 @@ nomadClientCert = ./secrets/nomad/cli/global-cli-nomad.pem; pkgsPulumi = inputs'.nixpkgsPulumi.legacyPackages; + cranePkgs = inputs.craneNixpkgs.legacyPackages.${system}; + craneLib = (inputs.crane.mkLib cranePkgs).overrideToolchain ( + p: + (inputs.rust-overlay.lib.mkRustBin { } p.buildPackages).stable.latest.default.override { + extensions = [ + "rust-src" + "rust-analyzer" + "clippy" + "rustfmt" + ]; + } + ); in inputs.devshell.legacyPackages.${system}.mkShell { + packagesFrom = [ + (craneLib.devShell { + # Automatically inherit any build inputs from `my-crate` + inputsFrom = [ ]; + + # Extra inputs (only used for interactive development) + # can be added here; cargo and rustc are provided by default. + packages = [ (cranePkgs.stdenvAdapters.useMoldLinker cranePkgs.stdenv).cc ]; + }) + ]; packages = [ treefmtWrapper diff --git a/modules/flake-parts/packages.default.nix b/modules/flake-parts/packages.default.nix index c381884..9015bb7 100644 --- a/modules/flake-parts/packages.default.nix +++ b/modules/flake-parts/packages.default.nix @@ -1,6 +1,8 @@ { # System independent arguments. self, + inputs, + lib, ... }: { diff --git a/modules/flake-parts/packages.postbuildstepper/default.nix b/modules/flake-parts/packages.postbuildstepper/default.nix new file mode 100644 index 0000000..2351f5e --- /dev/null +++ b/modules/flake-parts/packages.postbuildstepper/default.nix @@ -0,0 +1,249 @@ +{ + # System independent arguments. + self, + inputs, + ... +}: +{ + perSystem = + { + # Arguments specific to the `perSystem` context. + pkgs, + self', + system ? pkgs.system, + lib, + ... + }: + + { + # system specific outputs like, apps, checks, packages + + packages = + let + cranePkgs = inputs.craneNixpkgs.legacyPackages.${system}; + craneLib = inputs.crane.mkLib cranePkgs; + + postbuildstepperArgs = + let + pname = "postbuildstepper"; + in + { + inherit pname; + + src = self.inputs.nix-filter { + root = self; + # If no include is passed, it will include all the paths. + include = [ + # Include the "src" path relative to the root. + "applications/postbuildstepper" + # Include this specific path. The path must be under the root. + "Cargo.toml" + "Cargo.lock" + # Include all files with the .js extension + ]; + }; + + version = "alpha"; + + cargoExtraArgs = "--bins"; + + nativeBuildInputs = [ cranePkgs.pkg-config ]; + + doCheck = true; + }; + postbuildstepperDeps = lib.makeOverridable craneLib.buildDepsOnly postbuildstepperArgs; + in + { + postbuildstepper-testpkg = pkgs.runCommand "postbuildstepper-testpkg" { } '' + mkdir -p $out/bin + echo "echo hello postbuildstepper" > $out/bin/postbuildstepper-testpkg + ''; + + postbuildstepper = lib.makeOverridable craneLib.buildPackage ( + postbuildstepperArgs // { cargoArtifacts = postbuildstepperDeps; } + ); + + }; + + checks = + let + s3 = { + bucket = "cache.holo.host"; + endpoint = "s3.wasabisys.com"; + adminKey = "s3key"; + adminSecret = "s3secret"; + profile = "cache-holo-host-s3-wasabi"; + + userKey = "s3user"; + userSecret = "s3usersecret"; + + endpointCert = self.lib.makeCert { + inherit pkgs; + caName = "Example good CA"; + domain = "${s3.endpoint}"; + }; + + bucketCert = self.lib.makeCert { + inherit pkgs; + caName = "Example good CA"; + domain = "${s3.bucket}"; + }; + }; + + awsSharedCredentialsFile = pkgs.writeText "aws-shared-credentials" '' + [${s3.profile}] + aws_access_key_id = ${s3.userKey} + aws_secret_access_key = ${s3.userSecret}''; + + cacheSecretKey = "testing-2:CoS7sAPcH1M+LD+D/fg9sc1V3uKk88VMHZ/MvAJHsuMSasehxxlUKNa0LUedGgFfA1wlRYF74BNcAldRxX2g8A=="; + cachePublicKey = "testing-2:EmrHoccZVCjWtC1HnRoBXwNcJUWBe+ATXAJXUcV9oPA="; + in + lib.attrsets.optionalAttrs (pkgs.stdenv.isLinux && pkgs.stdenv.isx86_64) { + postbuildstepper-test = pkgs.writeShellScriptBin "test" '' + set -x + + export PROP_owners="['steveej']" + export PROP_repository="https://github.com/Holo-Host/holo-nixpkgs" + export PROP_project="Holo-Host/holo-nixpkgs" \ + export PROP_attr="aarch64-linux.${self'.packages.postbuildstepper-testpkg.name}" + export SECRET_cacheHoloHost2secret="${cacheSecretKey}" + export PROP_out_path="${self'.packages.postbuildstepper-testpkg}" + # this needs to be `cat`ed because the program expects this to contain the content of the file. + export SECRET_awsSharedCredentialsFile="$(cat ${awsSharedCredentialsFile})" + + exec ${pkgs.lib.getExe' self.packages.${system}.postbuildstepper "postbuildstepper"} + ''; + + tests-postbuildstepper-integration = inputs.nixpkgs.lib.nixos.runTest { + name = "postbuildstepper"; + + imports = [ ]; + hostPkgs = pkgs; # the Nixpkgs package set used outside the VMs + # defaults.services.foo.package = self'.packages.postbuildstepper; + + # One or more machines: + nodes = { + machine = + { config, pkgs, ... }: + + { + networking.hosts = { + "127.0.0.1" = [ + s3.bucket + s3.endpoint + ]; + }; + + security.pki.certificateFiles = [ + "${s3.endpointCert}/ca.crt" + "${s3.bucketCert}/ca.crt" + ]; + + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; + + # add the testpkg to the closure at buildtime. otherwise `nix sign/copy` will try to build or fetch it + environment.systemPackages = [ self'.packages.postbuildstepper-testpkg ]; + + services.minio = { + enable = true; + browser = false; + listenAddress = "127.0.0.1:9000"; + rootCredentialsFile = pkgs.writeText "creds" '' + MINIO_ROOT_USER=${s3.adminKey} + MINIO_ROOT_PASSWORD=${s3.adminSecret} + ''; + }; + + services.caddy = { + enable = true; + logFormat = '' + # if need be set to DEBUG + level INFO + ''; + globalConfig = '' + auto_https off + ''; + + virtualHosts.${s3.endpoint} = { + extraConfig = '' + tls ${s3.endpointCert}/server.crt ${s3.endpointCert}/server.key + reverse_proxy http://${config.services.minio.listenAddress} + ''; + }; + virtualHosts.${s3.bucket} = { + extraConfig = '' + tls ${s3.bucketCert}/server.crt ${s3.bucketCert}/server.key + rewrite * /${s3.bucket}{uri} + reverse_proxy http://${config.services.minio.listenAddress} + ''; + }; + }; + }; + }; + + testScript = '' + machine.start() + + machine.wait_for_unit("minio.service") + # uncomment this command get a minio trace log + # machine.execute( + # ${pkgs.writeShellScript "trace-minio" '' + # export PATH=${pkgs.minio-client}/bin:$PATH + # set -xe + # # background trace logging for minio + # mc admin trace --all localhost >&2 & + # ''}, + # timeout = None + # ) + + + machine.wait_for_unit("caddy.service") + + machine.succeed("${pkgs.writeShellScript "prepare-minio" '' + export PATH=${pkgs.minio-client}/bin:$PATH + + set -xe + + mc alias set localhost "https://${s3.endpoint}" "${s3.adminKey}" "${s3.adminSecret}" + mc mb localhost/${s3.bucket} + + # create a non-admin user with write permissions + mc admin user add localhost ${s3.userKey} ${s3.userSecret} + mc admin policy attach localhost readwrite --user ${s3.userKey} + mc alias set user "https://${s3.endpoint}" "${s3.userKey}" "${s3.userSecret}" + + # allow anonymous access to the "cache" + mc anonymous set --recursive download localhost/${s3.bucket} + + # this file is GET'ed by `nix copy` + echo "StoreDir: /nix/store" > nix-cache-info + mc cp nix-cache-info user/${s3.bucket}/nix-cache-info + # mc cp nix-cache-info localhost/${s3.bucket}/nix-cache-info + + for remote in \ + https://${s3.endpoint}/${s3.bucket}/nix-cache-info \ + https://${s3.bucket}/nix-cache-info \ + ; do + diff --report-identical-files <(curl ''${remote}) nix-cache-info + done + + + ''}", timeout = 10) + + machine.succeed("${lib.getExe self'.checks.postbuildstepper-test}", timeout = 30) + + machine.succeed("nix copy --trusted-public-keys ${cachePublicKey} --from https://cache.holo.host --to ./store ${self'.packages.postbuildstepper-testpkg}", timeout = 30) + ''; + }; + }; + }; + + flake = { + # system independent outputs like nixosModules, nixosConfigurations, etc. + + # nixosConfigurations.example-host = ... + }; +}