rebuilderd-0.22.1/.cargo_vcs_info.json0000644000000001440000000000100132360ustar { "git": { "sha1": "0df3e3f9cbdd02edd52d5a2bbde9e42718c2e268" }, "path_in_vcs": "daemon" }rebuilderd-0.22.1/.env000064400000000000000000000000331046102023000126140ustar 00000000000000DATABASE_URL=rebuilderd.db rebuilderd-0.22.1/.gitignore000064400000000000000000000000351046102023000140150ustar 00000000000000/rebuilderd.db* /auth-cookie rebuilderd-0.22.1/Cargo.lock0000644000002103760000000000100112230ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "actix-codec" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ "bitflags", "bytes", "futures-core", "futures-sink", "memchr", "pin-project-lite", "tokio", "tokio-util", "tracing", ] [[package]] name = "actix-http" version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", "ahash", "base64", "bitflags", "brotli", "bytes", "bytestring", "derive_more", "encoding_rs", "flate2", "futures-core", "h2", "http 0.2.12", "httparse", "httpdate", "itoa", "language-tags", "local-channel", "mime", "percent-encoding", "pin-project-lite", "rand 0.8.5", "sha1", "smallvec", "tokio", "tokio-util", "tracing", "zstd", ] [[package]] name = "actix-macros" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", "syn", ] [[package]] name = "actix-router" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", "cfg-if", "http 0.2.12", "regex", "regex-lite", "serde", "tracing", ] [[package]] name = "actix-rt" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" dependencies = [ "futures-core", "tokio", ] [[package]] name = "actix-server" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" dependencies = [ "actix-rt", "actix-service", "actix-utils", "futures-core", "futures-util", "mio", "socket2", "tokio", "tracing", ] [[package]] name = "actix-service" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" dependencies = [ "futures-core", "paste", "pin-project-lite", ] [[package]] name = "actix-utils" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" dependencies = [ "local-waker", "pin-project-lite", ] [[package]] name = "actix-web" version = "4.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" dependencies = [ "actix-codec", "actix-http", "actix-macros", "actix-router", "actix-rt", "actix-server", "actix-service", "actix-utils", "actix-web-codegen", "ahash", "bytes", "bytestring", "cfg-if", "cookie", "derive_more", "encoding_rs", "futures-core", "futures-util", "impl-more", "itoa", "language-tags", "log", "mime", "once_cell", "pin-project-lite", "regex", "regex-lite", "serde", "serde_json", "serde_urlencoded", "smallvec", "socket2", "time", "url", ] [[package]] name = "actix-web-codegen" version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" dependencies = [ "actix-router", "proc-macro2", "quote", "syn", ] [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom 0.2.15", "once_cell", "version_check", "zerocopy 0.7.35", ] [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "alloc-no-stdlib" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anstream" version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", "once_cell", "windows-sys 0.59.0", ] [[package]] name = "anyhow" version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets", ] [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[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 = "brotli" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", "brotli-decompressor", ] [[package]] name = "brotli-decompressor" version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", ] [[package]] name = "bumpalo" version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "bytestring" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" dependencies = [ "bytes", ] [[package]] name = "cc" version = "1.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" 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 = "cfg_aliases" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", "windows-link", ] [[package]] name = "clap" version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "clap_lex" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cookie" version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", "time", "version_check", ] [[package]] name = "core-foundation" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[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 = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", ] [[package]] name = "darling_core" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", "syn", ] [[package]] name = "darling_macro" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", "syn", ] [[package]] name = "deranged" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] [[package]] name = "derive_more" version = "0.99.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", "syn", ] [[package]] name = "diesel" version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04001f23ba8843dc315804fa324000376084dfb1c30794ff68dd279e6e5696d5" dependencies = [ "chrono", "diesel_derives", "libsqlite3-sys", "r2d2", "time", ] [[package]] name = "diesel_derives" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f2c3de51e2ba6bf2a648285696137aaf0f5f487bcbea93972fe8a364e131a4" dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", "proc-macro2", "quote", "syn", ] [[package]] name = "diesel_migrations" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a73ce704bad4231f001bff3314d91dce4aba0770cee8b233991859abc15c1f6" dependencies = [ "diesel", "migrations_internals", "migrations_macros", ] [[package]] name = "diesel_table_macro_syntax" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" dependencies = [ "syn", ] [[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 = "dirs-next" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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 = "displaydoc" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "dotenvy" version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "dsl_auto_type" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "139ae9aca7527f85f26dd76483eb38533fd84bd571065da1739656ef71c5ff5b" dependencies = [ "darling", "either", "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "either" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" [[package]] name = "encoding_rs" version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "env_filter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", ] [[package]] name = "env_logger" version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", "env_filter", "humantime", "log", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "flate2" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "futures-channel" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[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", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ "cfg-if", "libc", "wasi 0.13.3+wasi-0.2.2", "windows-targets", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", "http 0.2.12", "indexmap", "slab", "tokio", "tokio-util", "tracing", ] [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http-body" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.2.0", ] [[package]] name = "http-body-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", "http 1.2.0", "http-body", "pin-project-lite", ] [[package]] name = "httparse" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" [[package]] name = "httpdate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.2.0", "http-body", "httparse", "itoa", "pin-project-lite", "smallvec", "tokio", "want", ] [[package]] name = "hyper-rustls" version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http 1.2.0", "hyper", "hyper-util", "rustls", "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", ] [[package]] name = "hyper-util" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.2.0", "http-body", "hyper", "pin-project-lite", "socket2", "tokio", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "icu_collections" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ "displaydoc", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locid" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_locid_transform" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ "displaydoc", "icu_locid", "icu_locid_transform_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_locid_transform_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" [[package]] name = "icu_normalizer" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", "utf16_iter", "utf8_iter", "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] name = "icu_properties" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", "icu_collections", "icu_locid_transform", "icu_properties_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_properties_data" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] name = "icu_provider" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" dependencies = [ "displaydoc", "icu_locid", "icu_provider_macros", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_provider_macros" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", "utf8_iter", ] [[package]] name = "idna_adapter" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] name = "impl-more" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" [[package]] name = "indexmap" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "ipnet" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[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.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "language-tags" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" [[package]] name = "libc" version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libredox" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags", "libc", ] [[package]] name = "libsqlite3-sys" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad8935b44e7c13394a179a438e0cebba0fe08fe01b54f152e29a93b5cf993fd4" dependencies = [ "pkg-config", "vcpkg", ] [[package]] name = "litemap" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "local-channel" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" dependencies = [ "futures-core", "futures-sink", "local-waker", ] [[package]] name = "local-waker" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[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.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "migrations_internals" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd01039851e82f8799046eabbb354056283fb265c8ec0996af940f4e85a380ff" dependencies = [ "serde", "toml", ] [[package]] name = "migrations_macros" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb161cc72176cb37aa47f1fc520d3ef02263d67d661f44f05d05a079e1237fd" dependencies = [ "migrations_internals", "proc-macro2", "quote", ] [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] [[package]] name = "mio" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[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", ] [[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ "zerocopy 0.7.35", ] [[package]] name = "proc-macro2" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quinn" version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", "rustls", "socket2", "thiserror 2.0.11", "tokio", "tracing", ] [[package]] name = "quinn-proto" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", "getrandom 0.2.15", "rand 0.8.5", "ring", "rustc-hash", "rustls", "rustls-pki-types", "slab", "thiserror 2.0.11", "tinyvec", "tracing", "web-time", ] [[package]] name = "quinn-udp" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2", "tracing", "windows-sys 0.59.0", ] [[package]] name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "r2d2" version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" dependencies = [ "log", "parking_lot", "scheduled-thread-pool", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] [[package]] name = "rand" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.2", "zerocopy 0.8.20", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core 0.6.4", ] [[package]] name = "rand_chacha" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core 0.9.2", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.15", ] [[package]] name = "rand_core" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a509b1a2ffbe92afab0e55c8fd99dea1c280e8171bd2d88682bb20bc41cbc2c" dependencies = [ "getrandom 0.3.1", "zerocopy 0.8.20", ] [[package]] name = "rebuilderd" version = "0.22.1" dependencies = [ "actix-web", "chrono", "clap", "diesel", "diesel_migrations", "dirs-next", "dotenvy", "env_logger", "log", "rand 0.9.0", "rebuilderd-common", "serde", "serde_json", "toml", ] [[package]] name = "rebuilderd-common" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72e2f25b43fdcf1503b9cfb52019598f8aa1ef49d318147f3c14aaa801601c69" dependencies = [ "anyhow", "chrono", "clap", "colored", "dirs-next", "log", "reqwest", "serde", "toml", "url", ] [[package]] name = "redox_syscall" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" dependencies = [ "bitflags", ] [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", "libredox", "thiserror 1.0.69", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-lite" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64", "bytes", "futures-channel", "futures-core", "futures-util", "http 1.2.0", "http-body", "http-body-util", "hyper", "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", "once_cell", "percent-encoding", "pin-project-lite", "quinn", "rustls", "rustls-native-certs", "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", "tokio-util", "tower", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", "windows-registry", ] [[package]] name = "ring" version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da5349ae27d3887ca812fb375b45a4fbb36d8d12d2df394968cd86e35683fe73" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", "untrusted", "windows-sys 0.52.0", ] [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustls" version = "0.23.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ "once_cell", "ring", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", "security-framework", ] [[package]] name = "rustls-pemfile" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ "rustls-pki-types", ] [[package]] name = "rustls-pki-types" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" dependencies = [ "web-time", ] [[package]] name = "rustls-webpki" version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "schannel" version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "scheduled-thread-pool" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" dependencies = [ "parking_lot", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "semver" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" 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 = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "sha1" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 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 = "signal-hook-registry" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "socket2" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] [[package]] name = "synstructure" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ "thiserror-impl 2.0.11", ] [[package]] name = "thiserror-impl" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "thiserror-impl" version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "time" version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", "serde", "time-core", "time-macros", ] [[package]] name = "time-core" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", ] [[package]] name = "tinystr" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", "zerovec", ] [[package]] name = "tinyvec" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "windows-sys 0.52.0", ] [[package]] name = "tokio-rustls" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls", "tokio", ] [[package]] name = "tokio-util" version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", ] [[package]] name = "toml" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" 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.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "winnow", ] [[package]] name = "tower" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", "sync_wrapper", "tokio", "tower-layer", "tower-service", ] [[package]] name = "tower-layer" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] [[package]] name = "utf16_iter" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ "try-lock", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" version = "0.13.3+wasi-0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "wasm-bindgen" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-streams" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", ] [[package]] name = "web-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "web-time" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets", ] [[package]] name = "windows-link" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" [[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result", "windows-strings", "windows-targets", ] [[package]] name = "windows-result" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ "windows-targets", ] [[package]] name = "windows-strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", "windows-targets", ] [[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.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen-rt" version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ "bitflags", ] [[package]] name = "write16" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" [[package]] name = "writeable" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zerocopy" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", "zerocopy-derive 0.7.35", ] [[package]] name = "zerocopy" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c" dependencies = [ "zerocopy-derive 0.8.20", ] [[package]] name = "zerocopy-derive" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerocopy-derive" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerofrom" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zerovec" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zstd" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" version = "7.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" version = "2.0.14+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5" dependencies = [ "cc", "pkg-config", ] rebuilderd-0.22.1/Cargo.toml0000644000000044000000000000100112330ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "rebuilderd" version = "0.22.1" authors = ["kpcyrd "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "rebuilderd - independent build verification daemon" readme = false license = "GPL-3.0-or-later" repository = "https://github.com/kpcyrd/rebuilderd" [package.metadata.deb] assets = [ [ "target/release/rebuilderd", "usr/bin/", "755", ], [ "../contrib/confs/rebuilderd.conf", "etc/", "600", ], [ "../contrib/systemd/rebuilderd.service", "usr/lib/systemd/system/", "640", ], [ "../contrib/systemd/rebuilderd.sysusers", "usr/lib/sysusers.d/rebuilderd.conf", "644", ], [ "../contrib/systemd/rebuilderd.tmpfiles", "usr/lib/tmpfiles.d/rebuilderd.conf", "644", ], ] depends = "$auto, systemd, rebuildctl" maintainer-scripts = "daemon/debian" [lib] name = "rebuilderd" path = "src/lib.rs" [[bin]] name = "rebuilderd" path = "src/main.rs" [dependencies.actix-web] version = "4.1.0" [dependencies.chrono] version = "0.4.19" features = ["serde"] [dependencies.clap] version = "4" features = ["derive"] [dependencies.diesel] version = "2" features = [ "sqlite", "r2d2", "chrono", "i-implement-a-third-party-backend-and-opt-into-breaking-changes", ] [dependencies.diesel_migrations] version = "2" features = ["sqlite"] [dependencies.dirs-next] version = "2.0.0" [dependencies.dotenvy] version = "0.15.0" [dependencies.env_logger] version = "0.11" [dependencies.log] version = "0.4.17" [dependencies.rand] version = "0.9" [dependencies.rebuilderd-common] version = "=0.22.1" [dependencies.serde] version = "1.0.137" features = ["derive"] [dependencies.serde_json] version = "1.0.81" [dependencies.toml] version = "0.8" rebuilderd-0.22.1/Cargo.toml.orig0000644000000025010000000000100121720ustar [package] name = "rebuilderd" version = "0.22.1" description = "rebuilderd - independent build verification daemon" authors = ["kpcyrd "] license = "GPL-3.0-or-later" repository = "https://github.com/kpcyrd/rebuilderd" edition = "2021" [package.metadata.deb] maintainer-scripts = "daemon/debian" depends = "$auto, systemd, rebuildctl" assets = [ ["target/release/rebuilderd", "usr/bin/", "755"], ["../contrib/confs/rebuilderd.conf", "etc/", "600"], ["../contrib/systemd/rebuilderd.service", "usr/lib/systemd/system/", "640"], ["../contrib/systemd/rebuilderd.sysusers", "usr/lib/sysusers.d/rebuilderd.conf", "644"], ["../contrib/systemd/rebuilderd.tmpfiles", "usr/lib/tmpfiles.d/rebuilderd.conf", "644"], ] [dependencies] actix-web = "4.1.0" chrono = { version = "0.4.19", features=["serde"] } clap = { version = "4", features = ["derive"] } diesel = { version = "2", features = ["sqlite", "r2d2", "chrono", "i-implement-a-third-party-backend-and-opt-into-breaking-changes"] } diesel_migrations = { version = "2", features = ["sqlite"] } dirs-next = "2.0.0" dotenvy = "0.15.0" env_logger = "0.11" log = "0.4.17" rand = "0.9" rebuilderd-common = { version= "=0.22.1", path="../common" } serde = { version="1.0.137", features=["derive"] } serde_json = "1.0.81" toml = "0.8" # https://crates.io/crates/deb-version rebuilderd-0.22.1/Cargo.toml.orig000064400000000000000000000025011046102023000147140ustar 00000000000000[package] name = "rebuilderd" version = "0.22.1" description = "rebuilderd - independent build verification daemon" authors = ["kpcyrd "] license = "GPL-3.0-or-later" repository = "https://github.com/kpcyrd/rebuilderd" edition = "2021" [package.metadata.deb] maintainer-scripts = "daemon/debian" depends = "$auto, systemd, rebuildctl" assets = [ ["target/release/rebuilderd", "usr/bin/", "755"], ["../contrib/confs/rebuilderd.conf", "etc/", "600"], ["../contrib/systemd/rebuilderd.service", "usr/lib/systemd/system/", "640"], ["../contrib/systemd/rebuilderd.sysusers", "usr/lib/sysusers.d/rebuilderd.conf", "644"], ["../contrib/systemd/rebuilderd.tmpfiles", "usr/lib/tmpfiles.d/rebuilderd.conf", "644"], ] [dependencies] actix-web = "4.1.0" chrono = { version = "0.4.19", features=["serde"] } clap = { version = "4", features = ["derive"] } diesel = { version = "2", features = ["sqlite", "r2d2", "chrono", "i-implement-a-third-party-backend-and-opt-into-breaking-changes"] } diesel_migrations = { version = "2", features = ["sqlite"] } dirs-next = "2.0.0" dotenvy = "0.15.0" env_logger = "0.11" log = "0.4.17" rand = "0.9" rebuilderd-common = { version= "=0.22.1", path="../common" } serde = { version="1.0.137", features=["derive"] } serde_json = "1.0.81" toml = "0.8" # https://crates.io/crates/deb-version rebuilderd-0.22.1/diesel.toml000064400000000000000000000002101046102023000141620ustar 00000000000000# For documentation on how to configure this file, # see diesel.rs/guides/configuring-diesel-cli [print_schema] file = "src/schema.rs" rebuilderd-0.22.1/migrations/.gitkeep000064400000000000000000000000001046102023000156220ustar 00000000000000rebuilderd-0.22.1/migrations/2019-12-05-202101_setup/down.sql000064400000000000000000000000731046102023000206730ustar 00000000000000DROP TABLE workers; DROP TABLE queue; DROP TABLE packages; rebuilderd-0.22.1/migrations/2019-12-05-202101_setup/up.sql000064400000000000000000000020371046102023000203520ustar 00000000000000CREATE TABLE packages ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture) ); CREATE TABLE queue ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, package_id INTEGER NOT NULL, version VARCHAR NOT NULL, queued_at DATETIME NOT NULL, worker_id INTEGER, started_at DATETIME, last_ping DATETIME, FOREIGN KEY(package_id) REFERENCES packages(id) ON DELETE CASCADE, FOREIGN KEY(worker_id) REFERENCES workers(id) ON DELETE SET NULL, CONSTRAINT queue_unique UNIQUE (package_id, version) ); CREATE TABLE workers ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, key VARCHAR NOT NULL, addr VARCHAR NOT NULL, status VARCHAR, last_ping TIMESTAMP NOT NULL, online BOOLEAN NOT NULL, CONSTRAINT workers_unique UNIQUE (key) ); rebuilderd-0.22.1/migrations/2020-05-27-160242_retries/down.sql000064400000000000000000000012231046102023000212150ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture) ); INSERT INTO _packages_new (id, name, version, status, distro, suite, architecture, url) SELECT id, name, version, status, distro, suite, architecture, url FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2020-05-27-160242_retries/up.sql000064400000000000000000000015441046102023000207000ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, built_at DATETIME, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture) ); INSERT INTO _packages_new (id, name, version, status, distro, suite, architecture, url, retries) SELECT id, name, version, status, distro, suite, architecture, url, 0 FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; UPDATE packages SET next_retry = datetime('now') WHERE status = 'BAD'; rebuilderd-0.22.1/migrations/2020-05-27-190113_priorities/down.sql000064400000000000000000000013531046102023000217350ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _queue_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, package_id INTEGER NOT NULL, version VARCHAR NOT NULL, queued_at DATETIME NOT NULL, worker_id INTEGER, started_at DATETIME, last_ping DATETIME, FOREIGN KEY(package_id) REFERENCES packages(id) ON DELETE CASCADE, FOREIGN KEY(worker_id) REFERENCES workers(id) ON DELETE SET NULL, CONSTRAINT queue_unique UNIQUE (package_id, version) ); INSERT INTO _queue_new (id, package_id, version, queued_at, worker_id, started_at, last_ping) SELECT id, package_id, version, queued_at, worker_id, started_at, last_ping FROM queue; DROP TABLE queue; ALTER TABLE _queue_new RENAME TO queue; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2020-05-27-190113_priorities/up.sql000064400000000000000000000014271046102023000214140ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _queue_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, package_id INTEGER NOT NULL, version VARCHAR NOT NULL, priority INTEGER NOT NULL, queued_at DATETIME NOT NULL, worker_id INTEGER, started_at DATETIME, last_ping DATETIME, FOREIGN KEY(package_id) REFERENCES packages(id) ON DELETE CASCADE, FOREIGN KEY(worker_id) REFERENCES workers(id) ON DELETE SET NULL, CONSTRAINT queue_unique UNIQUE (package_id, version) ); INSERT INTO _queue_new (id, package_id, version, priority, queued_at, worker_id, started_at, last_ping) SELECT id, package_id, version, 0, queued_at, worker_id, started_at, last_ping FROM queue; DROP TABLE queue; ALTER TABLE _queue_new RENAME TO queue; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2020-11-07-135105_track-builds/down.sql000064400000000000000000000016201046102023000221200ustar 00000000000000DROP TABLE builds; PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, built_at DATETIME, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture) ); INSERT INTO _packages_new (id, name, version, status, distro, suite, architecture, url, built_at, attestation, checksum, retries, next_retry) SELECT id, name, version, status, distro, suite, architecture, url, built_at, attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2020-11-07-135105_track-builds/up.sql000064400000000000000000000021011046102023000215700ustar 00000000000000CREATE TABLE builds ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, diffoscope TEXT, build_log BLOB NOT NULL ); PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, name, version, status, distro, suite, architecture, url, built_at, attestation, checksum, retries, next_retry) SELECT id, name, version, status, distro, suite, architecture, url, built_at, attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2020-12-23-025138_pkgbase/down.sql000064400000000000000000000017551046102023000211640ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, name, version, status, distro, suite, architecture, url, build_id, built_at, attestation, checksum, retries, next_retry) SELECT id, name, version, status, distro, suite, architecture, url, build_id, built_at, attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; DROP TABLE pkgbases; rebuilderd-0.22.1/migrations/2020-12-23-025138_pkgbase/up.sql000064400000000000000000000026321046102023000206340ustar 00000000000000CREATE TABLE pkgbases ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT pkgbase_unique UNIQUE (name, version, distro, suite, architecture) ); PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, attestation, checksum, retries, next_retry) SELECT id, NULL, name, version, status, distro, suite, architecture, url, build_id, built_at, attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-07-22-093726_has_diffoscope/down.sql000064400000000000000000000020601046102023000225260ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, attestation, checksum, retries, next_retry) SELECT id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-07-22-093726_has_diffoscope/up.sql000064400000000000000000000024041046102023000222050ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, has_diffoscope, attestation, checksum, retries, next_retry) SELECT id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, false, attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; -- initialize new has_diffoscope field update packages set has_diffoscope=true where build_id in (select id from builds where diffoscope is not null); rebuilderd-0.22.1/migrations/2021-08-04-171946_queue-per-distro/down.sql000064400000000000000000000014361046102023000227740ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _queue_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, package_id INTEGER NOT NULL, version VARCHAR NOT NULL, priority INTEGER NOT NULL, queued_at DATETIME NOT NULL, worker_id INTEGER, started_at DATETIME, last_ping DATETIME, FOREIGN KEY(package_id) REFERENCES packages(id) ON DELETE CASCADE, FOREIGN KEY(worker_id) REFERENCES workers(id) ON DELETE SET NULL, CONSTRAINT queue_unique UNIQUE (package_id, version) ); INSERT INTO _queue_new (id, package_id, version, priority, queued_at, worker_id, started_at, last_ping) SELECT id, package_id, version, priority, queued_at, worker_id, started_at, last_ping FROM queue; DROP TABLE queue; ALTER TABLE _queue_new RENAME TO queue; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-08-04-171946_queue-per-distro/up.sql000064400000000000000000000016631046102023000224530ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _queue_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, package_id INTEGER NOT NULL, version VARCHAR NOT NULL, required_backend VARCHAR NOT NULL, priority INTEGER NOT NULL, queued_at DATETIME NOT NULL, worker_id INTEGER, started_at DATETIME, last_ping DATETIME, FOREIGN KEY(package_id) REFERENCES packages(id) ON DELETE CASCADE, FOREIGN KEY(worker_id) REFERENCES workers(id) ON DELETE SET NULL, CONSTRAINT queue_unique UNIQUE (package_id, version) ); INSERT INTO _queue_new (id, package_id, version, required_backend, priority, queued_at, worker_id, started_at, last_ping) SELECT id, package_id, version, "", priority, queued_at, worker_id, started_at, last_ping FROM queue; DROP TABLE queue; ALTER TABLE _queue_new RENAME TO queue; CREATE UNIQUE INDEX queue_pop_idx ON queue(required_backend, priority, queued_at, id); PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-08-06-184605_add_attestation/down.sql000064400000000000000000000033731046102023000227310ustar 00000000000000-- add attestation & drop has_attestation column in "packages" PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, attestation VARCHAR, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, has_diffoscope, attestation, checksum, retries, next_retry) SELECT id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, false, NULL, checksum, retries, next_retry FROM packages; -- copy all attestations values from "build" to "packages" table UPDATE _packages_new SET attestation=( SELECT attestation FROM builds WHERE builds.id = _packages_new.build_id ); DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; -- drop attestation column in "build" PRAGMA foreign_keys=off; CREATE TABLE _builds_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, diffoscope TEXT, build_log BLOB NOT NULL ); INSERT INTO _builds_new (id, diffoscope, build_log) SELECT id, diffoscope, build_log FROM builds; DROP TABLE builds; ALTER TABLE _builds_new RENAME TO builds; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-08-06-184605_add_attestation/up.sql000064400000000000000000000026631046102023000224070ustar 00000000000000-- add attestation field to "build" table ALTER TABLE builds ADD attestation VARCHAR; -- drop attestation column, add has_attestation field to "packages" table PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, has_attestation BOOLEAN NOT NULL, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, has_diffoscope, has_attestation, checksum, retries, next_retry) SELECT id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, false, false, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; -- initialize new has_attestation field update packages set has_attestation=true where build_id in (select id from builds where attestation is not null); rebuilderd-0.22.1/migrations/2021-10-06-132128_input-url/down.sql000064400000000000000000000022231046102023000214740ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, has_attestation BOOLEAN NOT NULL, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, has_diffoscope, has_attestation, checksum, retries, next_retry) SELECT id, base_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-10-06-132128_input-url/up.sql000064400000000000000000000022631046102023000211550ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, artifact_url VARCHAR NOT NULL, input_url VARCHAR, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, has_attestation BOOLEAN NOT NULL, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum, retries, next_retry) SELECT id, base_id, name, version, status, distro, suite, architecture, url, build_id, built_at, has_diffoscope, has_attestation, checksum, retries, next_retry FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-11-21-134730_build-groups/down.sql000064400000000000000000000024261046102023000221550ustar 00000000000000DROP TABLE queue; CREATE TABLE queue ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, package_id INTEGER NOT NULL, version VARCHAR NOT NULL, required_backend VARCHAR NOT NULL, priority INTEGER NOT NULL, queued_at DATETIME NOT NULL, worker_id INTEGER, started_at DATETIME, last_ping DATETIME, FOREIGN KEY(package_id) REFERENCES packages(id) ON DELETE CASCADE, FOREIGN KEY(worker_id) REFERENCES workers(id) ON DELETE SET NULL, CONSTRAINT queue_unique UNIQUE (package_id, version) ); CREATE UNIQUE INDEX queue_pop_idx ON queue(required_backend, priority, queued_at, id); PRAGMA foreign_keys=off; CREATE TABLE _pkgbases_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT pkgbase_unique UNIQUE (name, version, distro, suite, architecture) ); INSERT INTO _pkgbases_new (id, name, version, distro, suite, architecture, retries, next_retry) SELECT id, name, version, distro, suite, architecture, retries, next_retry FROM pkgbases; DROP TABLE pkgbases; ALTER TABLE _pkgbases_new RENAME TO pkgbases; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-11-21-134730_build-groups/up.sql000064400000000000000000000025361046102023000216340ustar 00000000000000DROP TABLE queue; CREATE TABLE queue ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, pkgbase_id INTEGER NOT NULL, version VARCHAR NOT NULL, required_backend VARCHAR NOT NULL, priority INTEGER NOT NULL, queued_at DATETIME NOT NULL, worker_id INTEGER, started_at DATETIME, last_ping DATETIME, FOREIGN KEY(pkgbase_id) REFERENCES pkgbases(id) ON DELETE CASCADE, FOREIGN KEY(worker_id) REFERENCES workers(id) ON DELETE SET NULL, CONSTRAINT queue_unique UNIQUE (pkgbase_id, version) ); CREATE UNIQUE INDEX queue_pop_idx ON queue(required_backend, priority, queued_at, id); PRAGMA foreign_keys=off; CREATE TABLE _pkgbases_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, input_url VARCHAR, artifacts VARCHAR NOT NULL, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT pkgbase_unique UNIQUE (name, version, distro, suite, architecture) ); INSERT INTO _pkgbases_new (id, name, version, distro, suite, architecture, artifacts, retries, next_retry) SELECT id, name, version, distro, suite, architecture, "[]", retries, next_retry FROM pkgbases; DROP TABLE pkgbases; ALTER TABLE _pkgbases_new RENAME TO pkgbases; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-11-22-110050_cleanup-pkgs-table/down.sql000064400000000000000000000022411046102023000232000ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, base_id INTEGER, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, artifact_url VARCHAR NOT NULL, input_url VARCHAR, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, has_attestation BOOLEAN NOT NULL, checksum VARCHAR, retries INTEGER NOT NULL, next_retry DATETIME, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(base_id) REFERENCES pkgbases(id), FOREIGN KEY(build_id) REFERENCES builds(id) ); INSERT INTO _packages_new (id, base_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum, retries) SELECT id, pkgbase_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum, 0 FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-11-22-110050_cleanup-pkgs-table/up.sql000064400000000000000000000025471046102023000226660ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, pkgbase_id INTEGER NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, artifact_url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, has_attestation BOOLEAN NOT NULL, checksum VARCHAR, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(pkgbase_id) REFERENCES pkgbases(id) ON DELETE CASCADE, FOREIGN KEY(build_id) REFERENCES builds(id) ON DELETE SET NULL ); INSERT INTO _packages_new (id, pkgbase_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum) SELECT id, base_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum FROM packages WHERE base_id IS NOT NULL; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; -- drop all packages that we still need to build so they get properly re-initialized next sync delete from pkgbases where id in (select pkgbase_id from packages where status != 'GOOD') and artifacts='[]'; rebuilderd-0.22.1/migrations/2021-11-25-002754_pkgs-table-uniq/down.sql000064400000000000000000000022761046102023000225530ustar 00000000000000DROP INDEX packages_pkgbase_idx; DROP INDEX queue_pkgbase_idx; PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, pkgbase_id INTEGER NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, artifact_url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, has_attestation BOOLEAN NOT NULL, checksum VARCHAR, CONSTRAINT packages_unique UNIQUE (name, distro, suite, architecture), FOREIGN KEY(pkgbase_id) REFERENCES pkgbases(id) ON DELETE CASCADE, FOREIGN KEY(build_id) REFERENCES builds(id) ON DELETE SET NULL ); INSERT INTO _packages_new (id, pkgbase_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum) SELECT id, pkgbase_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; rebuilderd-0.22.1/migrations/2021-11-25-002754_pkgs-table-uniq/up.sql000064400000000000000000000023701046102023000222230ustar 00000000000000PRAGMA foreign_keys=off; CREATE TABLE _packages_new ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, pkgbase_id INTEGER NOT NULL, name VARCHAR NOT NULL, version VARCHAR NOT NULL, status VARCHAR NOT NULL, distro VARCHAR NOT NULL, suite VARCHAR NOT NULL, architecture VARCHAR NOT NULL, artifact_url VARCHAR NOT NULL, build_id INTEGER, built_at DATETIME, has_diffoscope BOOLEAN NOT NULL, has_attestation BOOLEAN NOT NULL, checksum VARCHAR, CONSTRAINT packages_unique UNIQUE (name, version, distro, suite, architecture), FOREIGN KEY(pkgbase_id) REFERENCES pkgbases(id) ON DELETE CASCADE, FOREIGN KEY(build_id) REFERENCES builds(id) ON DELETE SET NULL ); INSERT INTO _packages_new (id, pkgbase_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum) SELECT id, pkgbase_id, name, version, status, distro, suite, architecture, artifact_url, build_id, built_at, has_diffoscope, has_attestation, checksum FROM packages; DROP TABLE packages; ALTER TABLE _packages_new RENAME TO packages; PRAGMA foreign_keys=on; CREATE INDEX packages_pkgbase_idx ON packages(pkgbase_id); CREATE INDEX queue_pkgbase_idx ON queue(pkgbase_id); rebuilderd-0.22.1/src/api.rs000064400000000000000000000405031046102023000137370ustar 00000000000000use crate::auth; use crate::config::Config; use crate::dashboard::DashboardState; use crate::db::Pool; use crate::models; use crate::sync; use crate::web; use actix_web::{get, http, post, HttpRequest, HttpResponse, Responder}; use chrono::prelude::*; use diesel::SqliteConnection; use rebuilderd_common::api::*; use rebuilderd_common::errors::*; use rebuilderd_common::{PkgRelease, Status}; use std::collections::HashSet; use std::net::IpAddr; use std::sync::{Arc, RwLock}; use std::time::SystemTime; fn forbidden() -> HttpResponse { HttpResponse::Forbidden().body("Authentication failed\n") } fn not_found() -> HttpResponse { HttpResponse::NotFound().body("Not found\n") } fn not_modified() -> HttpResponse { HttpResponse::NotModified().body("") } pub fn header<'a>(req: &'a HttpRequest, key: &str) -> Result<&'a str> { let value = req .headers() .get(key) .ok_or_else(|| format_err!("Missing header"))? .to_str() .context("Failed to decode header value")?; Ok(value) } fn modified_since_duration(req: &HttpRequest, datetime: DateTime) -> Option { header(req, http::header::IF_MODIFIED_SINCE.as_str()) .ok() .and_then(|value| chrono::DateTime::parse_from_rfc2822(value).ok()) .map(|value| value.signed_duration_since(datetime)) } #[get("/api/v0/workers")] pub async fn list_workers( req: HttpRequest, cfg: web::Data, pool: web::Data, ) -> web::Result { if auth::admin(&cfg, &req).is_err() { return Ok(forbidden()); } let mut connection = pool.get().map_err(Error::from)?; models::Worker::mark_stale_workers_offline(connection.as_mut())?; let workers = models::Worker::list(connection.as_mut())?; Ok(HttpResponse::Ok().json(workers)) } // this route is configured in src/main.rs so we can reconfigure the json extractor // #[post("/api/v0/job/sync")] pub async fn sync_work( req: HttpRequest, cfg: web::Data, import: web::Json, pool: web::Data, ) -> web::Result { if auth::admin(&cfg, &req).is_err() { return Ok(forbidden()); } let import = import.into_inner(); let mut connection = pool.get().map_err(Error::from)?; sync::run(import, connection.as_mut())?; Ok(HttpResponse::Ok().json(JobAssignment::Nothing)) } fn opt_filter(this: &str, filter: Option<&str>) -> bool { if let Some(filter) = filter { if this != filter { return true; } } false } #[get("/api/v0/pkgs/list")] pub async fn list_pkgs( req: HttpRequest, query: web::Query, pool: web::Data, ) -> web::Result { let mut connection = pool.get().map_err(Error::from)?; let mut builder = HttpResponse::Ok(); // Set Last-Modified header to the most recent build package time // If If-Modified-Since header is set, compare it to the latest built time. if let Some(latest_built_at) = models::Package::most_recent_built_at(connection.as_mut())? { let latest_built_at = DateTime::from_naive_utc_and_offset(latest_built_at, Utc); if let Some(duration) = modified_since_duration(&req, latest_built_at) { if duration.num_seconds() >= 0 { return Ok(not_modified()); } } let latest_built_at = SystemTime::from(latest_built_at); builder.insert_header(http::header::LastModified(latest_built_at.into())); } let mut pkgs = Vec::::new(); for pkg in models::Package::list(connection.as_mut())? { if opt_filter(&pkg.name, query.name.as_deref()) { continue; } if opt_filter(&pkg.status, query.status.as_deref()) { continue; } if opt_filter(&pkg.distro, query.distro.as_deref()) { continue; } if opt_filter(&pkg.suite, query.suite.as_deref()) { continue; } if opt_filter(&pkg.architecture, query.architecture.as_deref()) { continue; } pkgs.push(pkg.into_api_item()?); } Ok(builder.json(pkgs)) } #[post("/api/v0/queue/list")] pub async fn list_queue( query: web::Json, pool: web::Data, ) -> web::Result { let mut connection = pool.get().map_err(Error::from)?; models::Queued::free_stale_jobs(connection.as_mut())?; let queue = models::Queued::list(query.limit, connection.as_mut())?; let queue: Vec = queue .into_iter() .map(|x| x.into_api_item(connection.as_mut())) .collect::>()?; let now = Utc::now().naive_utc(); Ok(HttpResponse::Ok().json(QueueList { now, queue })) } fn get_worker_from_request( req: &HttpRequest, cfg: &Config, connection: &mut SqliteConnection, ) -> web::Result { let key = header(req, WORKER_KEY_HEADER).context("Failed to get worker key")?; let ip = if let Some(real_ip_header) = &cfg.real_ip_header { let ip = header(req, real_ip_header).context("Failed to locate real ip header")?; ip.parse::() .context("Can't parse real ip header as ip address")? } else { let ci = req .peer_addr() .ok_or_else(|| format_err!("Can't determine client ip"))?; ci.ip() }; debug!("detected worker ip for {:?} as {}", key, ip); if let Some(mut worker) = models::Worker::get(key, connection)? { worker.bump_last_ping(&ip); Ok(worker) } else { let worker = models::NewWorker::new(key.to_string(), ip, None); worker.insert(connection)?; get_worker_from_request(req, cfg, connection) } } #[post("/api/v0/queue/push")] pub async fn push_queue( req: HttpRequest, cfg: web::Data, query: web::Json, pool: web::Data, ) -> web::Result { if auth::admin(&cfg, &req).is_err() { return Ok(forbidden()); } let query = query.into_inner(); let mut connection = pool.get().map_err(Error::from)?; debug!("searching pkg: {:?}", query); let pkgs = models::Package::get_by( &query.name, &query.distro, &query.suite, query.architecture.as_deref(), connection.as_mut(), )?; for pkg in pkgs { debug!("found pkg: {:?}", pkg); let pkgbase = models::PkgBase::get_id(pkg.pkgbase_id, connection.as_mut())?; let item = models::NewQueued::new(pkgbase.id, pkgbase.version, pkgbase.distro, query.priority); debug!("adding to queue: {:?}", item); if let Err(err) = item.insert(connection.as_mut()) { error!("failed to queue item: {:#?}", err); } } Ok(HttpResponse::Ok().json(())) } #[post("/api/v0/queue/pop")] pub async fn pop_queue( req: HttpRequest, cfg: web::Data, query: web::Json, pool: web::Data, ) -> web::Result { if auth::worker(&cfg, &req).is_err() { return Ok(forbidden()); } let mut connection = pool.get().map_err(Error::from)?; let mut worker = get_worker_from_request(&req, &cfg, connection.as_mut())?; models::Queued::free_stale_jobs(connection.as_mut())?; let (resp, status) = if let Some(item) = models::Queued::pop_next(worker.id, &query.supported_backends, connection.as_mut())? { // TODO: claim item correctly let status = format!( "working hard on {} {}", item.pkgbase.name, item.pkgbase.version ); (JobAssignment::Rebuild(Box::new(item)), Some(status)) } else { (JobAssignment::Nothing, None) }; worker.status = status; worker.update(connection.as_mut())?; Ok(HttpResponse::Ok().json(resp)) } #[post("/api/v0/queue/drop")] pub async fn drop_from_queue( req: HttpRequest, cfg: web::Data, query: web::Json, pool: web::Data, ) -> web::Result { if auth::admin(&cfg, &req).is_err() { return Ok(forbidden()); } let query = query.into_inner(); let mut connection = pool.get().map_err(Error::from)?; let pkgbases = models::PkgBase::get_by( &query.name, &query.distro, &query.suite, None, query.architecture.as_deref(), connection.as_mut(), )?; let pkgbases = pkgbases.iter().map(|p| p.id).collect::>(); models::Queued::drop_for_pkgbases(&pkgbases, connection.as_mut())?; Ok(HttpResponse::Ok().json(())) } #[post("/api/v0/pkg/requeue")] pub async fn requeue_pkgbase( req: HttpRequest, cfg: web::Data, query: web::Json, pool: web::Data, ) -> web::Result { if auth::admin(&cfg, &req).is_err() { return Ok(forbidden()); } let mut connection = pool.get().map_err(Error::from)?; let mut pkg_ids = Vec::new(); let mut pkgbase_ids = HashSet::new(); for pkg in models::Package::list(connection.as_mut())? { // TODO: this should be filtered in the database if opt_filter(&pkg.name, query.name.as_deref()) { continue; } if opt_filter(&pkg.status, query.status.as_deref()) { continue; } if opt_filter(&pkg.distro, query.distro.as_deref()) { continue; } if opt_filter(&pkg.suite, query.suite.as_deref()) { continue; } if opt_filter(&pkg.architecture, query.architecture.as_deref()) { continue; } debug!( "Adding pkgbase to be requeued for {:?} {:?}: pkgbase={:?}", pkg.name, pkg.version, pkg.pkgbase_id ); pkg_ids.push(pkg.id); pkgbase_ids.insert(pkg.pkgbase_id); } let pkgbase_ids = pkgbase_ids.into_iter().collect::>(); let pkgbases = models::PkgBase::get_id_list(&pkgbase_ids, connection.as_mut())?; let to_be_queued = pkgbases .into_iter() .map(|pkgbase| { models::NewQueued::new( pkgbase.id, pkgbase.version.to_string(), pkgbase.distro, query.priority, ) }) .collect::>(); models::Queued::insert_batch(&to_be_queued, connection.as_mut())?; if query.reset { models::Package::reset_status_for_requeued_list(&pkg_ids, connection.as_mut())?; } Ok(HttpResponse::Ok().json(())) } #[post("/api/v0/build/ping")] pub async fn ping_build( req: HttpRequest, cfg: web::Data, item: web::Json, pool: web::Data, ) -> web::Result { if auth::worker(&cfg, &req).is_err() { return Ok(forbidden()); } let mut connection = pool.get().map_err(Error::from)?; let worker = get_worker_from_request(&req, &cfg, connection.as_mut())?; debug!("ping from worker: {:?}", worker); let mut item = models::Queued::get_id(item.queue_id, connection.as_mut())?; debug!("trying to ping item: {:?}", item); if item.worker_id != Some(worker.id) { return Err(anyhow!("Trying to write to item we didn't assign").into()); } debug!("updating database (item)"); item.ping_job(connection.as_mut())?; debug!("updating database (worker)"); worker.update(connection.as_mut())?; debug!("successfully pinged job"); Ok(HttpResponse::Ok().json(())) } // this route is configured in src/main.rs so we can reconfigure the json extractor // #[post("/api/v0/build/report")] pub async fn report_build( req: HttpRequest, cfg: web::Data, report: web::Json, pool: web::Data, ) -> web::Result { if auth::worker(&cfg, &req).is_err() { return Ok(forbidden()); } let mut connection = pool.get().map_err(Error::from)?; let mut worker = get_worker_from_request(&req, &cfg, connection.as_mut())?; let queue_item = models::Queued::get_id(report.queue.id, connection.as_mut())?; let mut pkgbase = models::PkgBase::get_id(queue_item.pkgbase_id, connection.as_mut())?; let mut needs_retry = false; for (artifact, rebuild) in &report.rebuilds { let mut packages = models::Package::get_by( &artifact.name, &pkgbase.distro, &pkgbase.suite, None, connection.as_mut(), )?; packages.retain(|x| x.pkgbase_id == pkgbase.id); if packages.len() != 1 { error!("rebuilt artifact didn't match a unique package in database. matches={:?} instead of 1", packages.len()); continue; } let mut pkg = packages.remove(0); // adding build to package let build = models::NewBuild::from_api(rebuild, report.build_log.as_bytes().to_vec()); let build_id = build.insert(connection.as_mut())?; pkg.build_id = Some(build_id); pkg.status = match rebuild.status { BuildStatus::Good => Status::Good.to_string(), _ => Status::Bad.to_string(), }; pkg.built_at = Some(Utc::now().naive_utc()); pkg.has_diffoscope = rebuild.diffoscope.is_some(); pkg.has_attestation = rebuild.attestation.is_some(); if rebuild.status != BuildStatus::Good { needs_retry = true; } pkg.update(connection.as_mut())?; } // update pkgbase if needs_retry { pkgbase.retries += 1; pkgbase.schedule_retry(cfg.schedule.retry_delay_base()); } else { pkgbase.clear_retry(connection.as_mut())?; } pkgbase.update(connection.as_mut())?; // cleanup queue item and worker status queue_item.delete(connection.as_mut())?; worker.status = None; worker.update(connection.as_mut())?; Ok(HttpResponse::Ok().json(())) } #[get("/api/v0/builds/{id}/log")] pub async fn get_build_log( id: web::Path, pool: web::Data, ) -> web::Result { let mut connection = pool.get().map_err(Error::from)?; let build = match models::Build::get_id(*id, connection.as_mut()) { Ok(build) => build, Err(_) => return Ok(not_found()), }; let resp = HttpResponse::Ok() .content_type("text/plain; charset=utf-8") .append_header(("X-Content-Type-Options", "nosniff")) .append_header(("Content-Security-Policy", "default-src 'none'")) .body(build.build_log); Ok(resp) } #[get("/api/v0/builds/{id}/attestation")] pub async fn get_attestation( id: web::Path, pool: web::Data, ) -> web::Result { let mut connection = pool.get().map_err(Error::from)?; let build = match models::Build::get_id(*id, connection.as_mut()) { Ok(build) => build, Err(_) => return Ok(not_found()), }; if let Some(attestation) = build.attestation { let resp = HttpResponse::Ok() .content_type("application/json; charset=utf-8") .append_header(("X-Content-Type-Options", "nosniff")) .append_header(("Content-Security-Policy", "default-src 'none'")) .body(attestation); Ok(resp) } else { Ok(not_found()) } } #[get("/api/v0/builds/{id}/diffoscope")] pub async fn get_diffoscope( id: web::Path, pool: web::Data, ) -> web::Result { let mut connection = pool.get().map_err(Error::from)?; let build = match models::Build::get_id(*id, connection.as_mut()) { Ok(build) => build, Err(_) => return Ok(not_found()), }; if let Some(diffoscope) = build.diffoscope { let resp = HttpResponse::Ok() .content_type("text/plain; charset=utf-8") .append_header(("X-Content-Type-Options", "nosniff")) .append_header(("Content-Security-Policy", "default-src 'none'")) .body(diffoscope); Ok(resp) } else { Ok(not_found()) } } #[get("/api/v0/dashboard")] pub async fn get_dashboard( pool: web::Data, lock: web::Data>>, ) -> web::Result { let mut connection = pool.get().map_err(Error::from)?; let stale = { let state = lock.read().unwrap(); !state.is_fresh() }; if stale { let mut state = lock.write().unwrap(); debug!("Updating cached dashboard"); state.update(connection.as_mut())?; } let state = lock.read().unwrap(); let resp = state.get_response()?; Ok(HttpResponse::Ok().json(resp)) } rebuilderd-0.22.1/src/auth.rs000064400000000000000000000057541046102023000141400ustar 00000000000000use crate::api; use crate::config::Config; use actix_web::HttpRequest; use rand::distr::{Alphanumeric, SampleString}; use rebuilderd_common::api::*; use rebuilderd_common::errors::*; use std::env; use std::fs::{self, OpenOptions}; use std::io::prelude::*; use std::os::unix::fs::OpenOptionsExt; use std::path::PathBuf; pub fn admin(cfg: &Config, req: &HttpRequest) -> Result<()> { let auth_cookie = api::header(req, AUTH_COOKIE_HEADER).context("Failed to get auth cookie")?; if cfg.auth_cookie != auth_cookie { bail!("Wrong auth cookie") } Ok(()) } pub fn worker(cfg: &Config, req: &HttpRequest) -> Result<()> { let worker_key = api::header(req, WORKER_KEY_HEADER); if worker_key.is_err() { debug!("Failed to get worker key"); } let worker_key = worker_key.context("Failed to get worker key")?; if !cfg.worker.authorized_workers.is_empty() { // TODO: we do not challenge the worker keys yet // Vec::contains() is inefficient with &str if !cfg .worker .authorized_workers .iter() .any(|x| x == worker_key) { bail!("Worker key is not on allow-list"); } } if let Some(expected_signup_secret) = &cfg.worker.signup_secret { let signup_secret = api::header(req, SIGNUP_SECRET_HEADER).context("Failed to get worker key")?; if signup_secret == expected_signup_secret { debug!("worker authenticated with signup secret"); Ok(()) } else { bail!("Signup secret mismatched"); } } else { let auth_cookie = api::header(req, AUTH_COOKIE_HEADER).context("Failed to get auth cookie")?; if cfg.auth_cookie == auth_cookie { Ok(()) } else { bail!("Fell back to auth cookie authentication, but didn't match"); } } } pub fn setup_auth_cookie() -> Result { let cookie = if let Ok(cookie) = rebuilderd_common::auth::find_auth_cookie() { debug!("Loaded cookie from filesystem"); cookie } else { debug!("Generating random cookie"); Alphanumeric.sample_string(&mut rand::rng(), 32) }; let cookie_path = if let Ok(cookie_path) = env::var("REBUILDERD_COOKIE_PATH") { PathBuf::from(cookie_path) } else if let Some(data_dir) = dirs_next::data_dir() { data_dir.join("rebuilderd-auth-cookie") } else { PathBuf::from("./auth-cookie") }; if let Some(parent) = cookie_path.parent() { debug!( "Ensuring parent directory for auth cookie exists: {:?}", parent ); fs::create_dir_all(parent)?; } debug!("Writing auth cookie to {:?}", cookie_path); let mut file = OpenOptions::new() .mode(0o640) .write(true) .create(true) .open(cookie_path) .context("Failed to open auth cookie file")?; file.write_all(format!("{}\n", cookie).as_bytes())?; Ok(cookie) } rebuilderd-0.22.1/src/config.rs000064400000000000000000000027171046102023000144400ustar 00000000000000use crate::auth; use rebuilderd_common::config::{ConfigFile, ScheduleConfig, WorkerConfig}; use rebuilderd_common::errors::*; use std::env; use std::fs; use std::path::Path; const DEFAULT_POST_BODY_SIZE_LIMIT: usize = 2_usize.pow(30); // 1 GB #[derive(Debug, Clone)] pub struct Config { pub auth_cookie: String, pub worker: WorkerConfig, pub bind_addr: String, pub real_ip_header: Option, pub post_body_size_limit: usize, pub schedule: ScheduleConfig, } pub fn from_struct(config: ConfigFile, auth_cookie: String) -> Result { let bind_addr = if let Ok(addr) = env::var("HTTP_ADDR") { addr } else if let Some(addr) = config.http.bind_addr { addr } else { "127.0.0.1:8484".to_string() }; Ok(Config { auth_cookie, worker: config.worker, bind_addr, real_ip_header: config.http.real_ip_header, post_body_size_limit: config .http .post_body_size_limit .unwrap_or(DEFAULT_POST_BODY_SIZE_LIMIT), schedule: config.schedule, }) } pub fn load(path: Option<&Path>) -> Result { let config = if let Some(path) = path { let buf = fs::read_to_string(path).context("Failed to read config file")?; toml::from_str(&buf)? } else { ConfigFile::default() }; let auth_cookie = auth::setup_auth_cookie().context("Failed to setup auth cookie")?; from_struct(config, auth_cookie) } rebuilderd-0.22.1/src/dashboard.rs000064400000000000000000000046201046102023000151150ustar 00000000000000use crate::models; use chrono::prelude::*; use rebuilderd_common::api::*; use rebuilderd_common::errors::*; use rebuilderd_common::Status; use std::collections::HashMap; use std::time::{Duration, Instant}; const DASHBOARD_UPDATE_INTERVAL: u64 = 1; // seconds #[derive(Debug)] pub struct DashboardState { response: Option, last_update: Instant, } impl Default for DashboardState { fn default() -> Self { Self::new() } } impl DashboardState { pub fn new() -> DashboardState { DashboardState { response: None, last_update: Instant::now(), } } pub fn is_fresh(&self) -> bool { if self.response.is_some() { self.last_update.elapsed() < Duration::from_secs(DASHBOARD_UPDATE_INTERVAL) } else { false } } pub fn update(&mut self, connection: &mut diesel::SqliteConnection) -> Result<()> { models::Queued::free_stale_jobs(connection)?; let pkgs = models::Package::list(connection)?; let queue = models::Queued::list(None, connection)?; let queue_length = queue.len(); let mut suites = HashMap::new(); for pkg in pkgs { if !suites.contains_key(&pkg.suite) { suites.insert(pkg.suite.clone(), SuiteStats::default()); } if let Some(stats) = suites.get_mut(&pkg.suite) { if let Ok(status) = pkg.status.parse() { match status { Status::Good => stats.good += 1, Status::Unknown => stats.unknown += 1, Status::Bad => stats.bad += 1, } } } } let mut active_builds = Vec::new(); for item in queue { if item.started_at.is_some() { let item = item.into_api_item(connection)?; active_builds.push(item); } } let now = Utc::now().naive_utc(); self.response = Some(DashboardResponse { suites, active_builds, queue_length, now, }); self.last_update = Instant::now(); Ok(()) } pub fn get_response(&self) -> Result<&DashboardResponse> { if let Some(resp) = &self.response { Ok(resp) } else { bail!("No cached state") } } } rebuilderd-0.22.1/src/db.rs000064400000000000000000000100401046102023000135440ustar 00000000000000use diesel::connection::{Instrumentation, SimpleConnection, TransactionManager}; use diesel::prelude::*; use diesel::query_builder::{QueryFragment, QueryId}; use diesel::r2d2::{self, ConnectionManager}; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; use rebuilderd_common::errors::*; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations"); pub type Pool = r2d2::Pool>; pub fn setup(url: &str) -> Result { info!("Using database at {:?}", url); let mut connection = SqliteConnection::establish(url)?; while connection .has_pending_migration(MIGRATIONS) .map_err(|err| anyhow!("Failed to check for pending migrations: {err:#}"))? { let version = connection .run_next_migration(MIGRATIONS) .map_err(|err| anyhow!("Failed to run pending migration: {err:#}"))?; info!("Applied database migration: {version}"); } Ok(connection) } pub fn setup_pool(url: &str) -> Result { setup(url)?; let manager = ConnectionManager::::new(url); let pool = r2d2::Pool::builder() .build(manager) .context("Failed to create pool")?; Ok(pool) } pub struct SqliteConnectionWrap(SqliteConnection); impl std::convert::AsMut for SqliteConnectionWrap { fn as_mut(&mut self) -> &mut SqliteConnection { &mut self.0 } } impl diesel::r2d2::R2D2Connection for SqliteConnectionWrap { fn ping(&mut self) -> QueryResult<()> { self.0.ping() } fn is_broken(&mut self) -> bool { self.0.is_broken() } } impl diesel::connection::ConnectionSealed for SqliteConnectionWrap {} impl diesel::connection::SimpleConnection for SqliteConnectionWrap { fn batch_execute(&mut self, query: &str) -> QueryResult<()> { self.0.batch_execute(query) } } impl Connection for SqliteConnectionWrap { type Backend = ::Backend; type TransactionManager = ::TransactionManager; fn establish(database_url: &str) -> ConnectionResult { let mut c = SqliteConnection::establish(database_url).map_err(|err| { warn!("establish returned error: {:?}", err); err })?; c.batch_execute( " PRAGMA busy_timeout = 10000; -- sleep if the database is busy PRAGMA foreign_keys = ON; -- enforce foreign keys ", ) .map_err(|err| { warn!("executing pragmas for busy_timeout failed: {:?}", err); ConnectionError::CouldntSetupConfiguration(err) })?; c.batch_execute(" PRAGMA journal_mode = WAL; -- better write-concurrency PRAGMA synchronous = NORMAL; -- fsync only in critical moments PRAGMA wal_autocheckpoint = 1000; -- write WAL changes back every 1000 pages, for an in average 1MB WAL file. May affect readers if number is increased PRAGMA wal_checkpoint(TRUNCATE); -- free some space by truncating possibly massive WAL files from the last run. PRAGMA cache_size = 134217728; -- set disk cache size to 128MB ").map_err(|err| { warn!("executing pragmas for wall mode failed: {:?}", err); ConnectionError::CouldntSetupConfiguration(err) })?; Ok(Self(c)) } fn execute_returning_count(&mut self, source: &T) -> QueryResult where T: QueryFragment + QueryId, { self.0.execute_returning_count(source) } fn transaction_state( &mut self, ) -> &mut >::TransactionStateData { self.0.transaction_state() } fn instrumentation(&mut self) -> &mut dyn Instrumentation { self.0.instrumentation() } fn set_instrumentation(&mut self, instrumentation: impl Instrumentation) { self.0.set_instrumentation(instrumentation) } } rebuilderd-0.22.1/src/lib.rs000064400000000000000000000060211046102023000137310ustar 00000000000000extern crate diesel; extern crate diesel_migrations; use crate::config::Config; use crate::dashboard::DashboardState; use crate::models::Build; use actix_web::middleware::Logger; use actix_web::web::Data; use actix_web::{App, HttpServer}; use diesel::SqliteConnection; use rebuilderd_common::errors::*; use std::sync::{Arc, RwLock}; use std::thread; use std::time::Duration; pub mod api; pub mod auth; pub mod config; pub mod dashboard; pub mod db; pub mod models; pub mod schema; pub mod sync; pub mod web; fn db_collect_garbage(connection: &mut SqliteConnection) -> Result<()> { let orphaned = Build::find_orphaned(connection)?; if !orphaned.is_empty() { info!("Deleting {} orphaned builds...", orphaned.len()); for ids in orphaned.chunks(500) { Build::delete_multiple(ids, connection).context("Failed to delete builds")?; debug!("Deleted chunk of {} builds", ids.len()); } info!("Finished removing orphaned builds"); } Ok(()) } pub async fn run_config(config: Config) -> Result<()> { let pool = db::setup_pool("rebuilderd.db")?; let bind_addr = config.bind_addr.clone(); let dashboard_cache = Arc::new(RwLock::new(DashboardState::new())); { let pool = pool.clone(); thread::spawn(move || { let mut connection = pool.get().expect("Failed to get connection from pool"); loop { debug!("Checking for orphaned builds..."); if let Err(err) = db_collect_garbage(connection.as_mut()) { error!("Failed to delete orphaned builds: {:#}", err); } debug!("Sleeping until next garbage collection cycle..."); thread::sleep(Duration::from_secs(24 * 3600)); } }); } HttpServer::new(move || { App::new() .wrap(Logger::default()) .app_data(Data::new(pool.clone())) .app_data(Data::new(config.clone())) .app_data(Data::new(dashboard_cache.clone())) .service(api::list_workers) .service(api::list_pkgs) .service(api::list_queue) .service(api::push_queue) .service(api::pop_queue) .service(api::drop_from_queue) .service(api::requeue_pkgbase) .service(api::ping_build) .service(api::get_build_log) .service(api::get_diffoscope) .service(api::get_attestation) .service(api::get_dashboard) .service( web::resource("/api/v0/build/report") .app_data(web::JsonConfig::default().limit(config.post_body_size_limit)) .route(web::post().to(api::report_build)), ) .service( web::resource("/api/v0/pkgs/sync") .app_data(web::JsonConfig::default().limit(config.post_body_size_limit)) .route(web::post().to(api::sync_work)), ) }) .bind(&bind_addr)? .run() .await?; Ok(()) } rebuilderd-0.22.1/src/main.rs000064400000000000000000000021111046102023000141030ustar 00000000000000use clap::{ArgAction, Parser}; use env_logger::Env; use rebuilderd::config; use rebuilderd_common::errors::*; use std::path::PathBuf; #[derive(Debug, Parser)] #[command(version)] struct Args { /// Verbose logging #[arg(short, long, action(ArgAction::Count))] verbose: u8, /// Load and print a config #[arg(long)] check_config: bool, /// Configuration file path #[arg(short, long)] config: Option, } #[actix_web::main] async fn main() -> Result<()> { let args = Args::parse(); let logging = match args.verbose { 0 => "actix_web=debug,info", 1 => "actix_web=debug,rebuilderd=debug,rebuilderd_common=debug,info", 2 => "debug", 3 => "rebuilderd=trace,rebuilderd_common=trace,debug", _ => "trace", }; env_logger::init_from_env(Env::default().default_filter_or(logging)); dotenvy::dotenv().ok(); let config = config::load(args.config.as_deref())?; if args.check_config { println!("{:#?}", config); } else { rebuilderd::run_config(config).await?; } Ok(()) } rebuilderd-0.22.1/src/models/build.rs000064400000000000000000000047321046102023000155540ustar 00000000000000use crate::schema::*; use diesel::sql_types; use diesel::prelude::*; use diesel::sql_types::Integer; use rebuilderd_common::api::Rebuild; use rebuilderd_common::errors::*; #[derive(Identifiable, Queryable, AsChangeset, Clone, PartialEq, Eq, Debug)] #[diesel(table_name = builds)] pub struct Build { pub id: i32, pub diffoscope: Option, pub build_log: Vec, pub attestation: Option, } impl Build { pub fn get_id(my_id: i32, connection: &mut SqliteConnection) -> Result { use crate::schema::builds::dsl::*; let build = builds .filter(id.eq(my_id)) .first::(connection)?; Ok(build) } pub fn find_orphaned(connection: &mut SqliteConnection) -> Result> { let ids = diesel::sql_query("select id from builds as b where not exists (select 1 from packages as p where p.build_id = b.id);") .load::(connection)?; let ids = ids.into_iter().map(|x| x.id).collect(); Ok(ids) } pub fn delete_multiple(ids: &[i32], connection: &mut SqliteConnection) -> Result<()> { use crate::schema::builds::dsl::*; diesel::delete(builds.filter(id.eq_any(ids))).execute(connection)?; Ok(()) } } #[derive(Debug, QueryableByName)] struct IdRow { #[diesel(sql_type = Integer)] id: i32, } #[derive(Insertable, PartialEq, Eq, Debug, Clone)] #[diesel(table_name = builds)] pub struct NewBuild { pub diffoscope: Option, pub build_log: Vec, pub attestation: Option, } impl NewBuild { pub fn insert(&self, connection: &mut SqliteConnection) -> Result { let id = connection.transaction::<_, Error, _>(|connection| { diesel::insert_into(builds::table) .values(self) .execute(connection)?; define_sql_function!{ fn last_insert_rowid() -> sql_types::Integer; } let rows = diesel::select(last_insert_rowid()).load::(connection)?; if let Some(id) = rows.first() { Ok(*id) } else { bail!("Failed to get last_insert_id") } }).context("Failed to insert build to db")?; Ok(id) } pub fn from_api(rebuild: &Rebuild, build_log: Vec) -> NewBuild { NewBuild { diffoscope: rebuild.diffoscope.clone(), attestation: rebuild.attestation.clone(), build_log, } } } rebuilderd-0.22.1/src/models/mod.rs000064400000000000000000000003401046102023000152230ustar 00000000000000macro_rules! import_models { ($x:ident) => { mod $x; pub use self::$x::*; }; } import_models!(build); import_models!(package); import_models!(pkgbase); import_models!(worker); import_models!(queue); rebuilderd-0.22.1/src/models/package.rs000064400000000000000000000133251046102023000160460ustar 00000000000000use chrono::NaiveDateTime; use crate::schema::*; use diesel::prelude::*; use rebuilderd_common::PkgRelease; use rebuilderd_common::errors::*; #[derive(Identifiable, Queryable, AsChangeset, Clone, PartialEq, Eq, Debug)] #[diesel(treat_none_as_null = true)] #[diesel(table_name = packages)] pub struct Package { pub id: i32, pub pkgbase_id: i32, pub name: String, pub version: String, pub status: String, pub distro: String, pub suite: String, pub architecture: String, pub artifact_url: String, pub build_id: Option, pub built_at: Option, pub has_diffoscope: bool, pub has_attestation: bool, pub checksum: Option, } impl Package { pub fn get_id(my_id: i32, connection: &mut SqliteConnection) -> Result { use crate::schema::packages::dsl::*; let pkg = packages .filter(id.eq(my_id)) .first::(connection)?; Ok(pkg) } pub fn get_by(my_name: &str, my_distro: &str, my_suite: &str, my_architecture: Option<&str>, connection: &mut SqliteConnection) -> Result> { use crate::schema::packages::dsl::*; let mut query = packages .filter(name.eq(my_name)) .filter(distro.eq(my_distro)) .filter(suite.eq(my_suite)) .into_boxed(); if let Some(my_architecture) = my_architecture { query = query.filter(architecture.eq(my_architecture)); } let pkg = query.load::(connection)?; Ok(pkg) } pub fn get_by_api(pkg: &PkgRelease, connection: &mut SqliteConnection) -> Result { use crate::schema::packages::dsl::*; let pkg = packages .filter(name.eq(&pkg.name)) .filter(version.eq(&pkg.version)) .filter(distro.eq(&pkg.distro)) .filter(suite.eq(&pkg.suite)) .filter(architecture.eq(&pkg.architecture)) .first::(connection)?; Ok(pkg) } pub fn list(connection: &mut SqliteConnection) -> Result> { use crate::schema::packages::dsl::*; let pkgs = packages .order_by((name, distro)) .load::(connection)?; Ok(pkgs) } pub fn list_distro_suite(my_distro: &str, my_suite: &str, connection: &mut SqliteConnection) -> Result> { use crate::schema::packages::dsl::*; let pkgs = packages .filter(distro.eq(my_distro)) .filter(suite.eq(my_suite)) .load::(connection)?; Ok(pkgs) } pub fn update(&self, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::packages::columns::*; diesel::update(packages::table.filter(id.eq(self.id))) .set(self) .execute(connection)?; Ok(()) } pub fn reset_status_for_requeued_list(pkgs: &[i32], connection: &mut SqliteConnection) -> Result<()> { use crate::schema::packages::columns::*; diesel::update(packages::table .filter(id.eq_any(pkgs)) ) .set(( status.eq("UNKWN"), build_id.eq(None as Option), )) .execute(connection)?; Ok(()) } pub fn delete(my_id: i32, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::packages::dsl::*; diesel::delete(packages.filter(id.eq(my_id))) .execute(connection)?; Ok(()) } pub fn most_recent_built_at(connection: &mut SqliteConnection) -> Result> { use crate::schema::packages::dsl::*; let latest_built = packages.select(diesel::dsl::max(built_at)).first(connection)?; Ok(latest_built) } pub fn into_api_item(self) -> Result { Ok(PkgRelease { name: self.name, distro: self.distro, architecture: self.architecture, version: self.version, status: self.status.parse()?, suite: self.suite, artifact_url: self.artifact_url, build_id: self.build_id, built_at: self.built_at, has_diffoscope: self.has_diffoscope, has_attestation: self.has_attestation, }) } } #[derive(Insertable, PartialEq, Eq, Debug, Clone)] #[diesel(table_name = packages)] pub struct NewPackage { pub pkgbase_id: i32, pub name: String, pub version: String, pub status: String, pub distro: String, pub suite: String, pub architecture: String, pub artifact_url: String, pub build_id: Option, pub built_at: Option, pub has_diffoscope: bool, pub has_attestation: bool, pub checksum: Option, } impl NewPackage { pub fn insert(&self, connection: &mut SqliteConnection) -> Result<()> { diesel::insert_into(packages::table) .values(self) .execute(connection)?; Ok(()) } pub fn insert_batch(pkgs: &[NewPackage], connection: &mut SqliteConnection) -> Result<()> { diesel::insert_into(packages::table) .values(pkgs) .execute(connection)?; Ok(()) } pub fn from_api(distro: String, pkgbase_id: i32, pkg: PkgRelease) -> NewPackage { NewPackage { pkgbase_id, name: pkg.name, version: pkg.version, status: pkg.status.to_string(), distro, suite: pkg.suite, architecture: pkg.architecture, artifact_url: pkg.artifact_url, build_id: None, built_at: None, has_diffoscope: false, has_attestation: false, checksum: None, } } } rebuilderd-0.22.1/src/models/pkgbase.rs000064400000000000000000000131631046102023000160670ustar 00000000000000use chrono::{Duration, NaiveDateTime, Utc}; use crate::schema::*; use diesel::prelude::*; use rebuilderd_common::PkgGroup; use rebuilderd_common::errors::*; #[derive(Identifiable, Queryable, AsChangeset, Clone, PartialEq, Eq, Debug)] #[diesel(table_name = pkgbases)] pub struct PkgBase { pub id: i32, pub name: String, pub version: String, pub distro: String, pub suite: String, pub architecture: String, pub input_url: Option, pub artifacts: String, pub retries: i32, pub next_retry: Option, } impl PkgBase { pub fn list_distro_suite(my_distro: &str, my_suite: &str, connection: &mut SqliteConnection) -> Result> { use crate::schema::pkgbases::dsl::*; let bases = pkgbases .filter(distro.eq(my_distro)) .filter(suite.eq(my_suite)) .load::(connection)?; Ok(bases) } pub fn list_pkgs(&self, connection: &mut SqliteConnection) -> Result> { use crate::schema::packages::dsl::*; let pkgs = packages .select(id) .filter(pkgbase_id.eq(self.id)) .load(connection)?; Ok(pkgs) } pub fn get_id(my_id: i32, connection: &mut SqliteConnection) -> Result { use crate::schema::pkgbases::dsl::*; let pkgbase = pkgbases .filter(id.eq(my_id)) .first::(connection)?; Ok(pkgbase) } pub fn get_id_list(my_ids: &[i32], connection: &mut SqliteConnection) -> Result> { use crate::schema::pkgbases::dsl::*; let pkgbase = pkgbases .filter(id.eq_any(my_ids)) .load::(connection)?; Ok(pkgbase) } pub fn get_by(my_name: &str, my_distro: &str, my_suite: &str, my_version: Option<&str>, my_architecture: Option<&str>, connection: &mut SqliteConnection) -> Result> { use crate::schema::pkgbases::dsl::*; let mut query = pkgbases .filter(name.eq(my_name)) .filter(distro.eq(my_distro)) .filter(suite.eq(my_suite)) .into_boxed(); if let Some(my_version) = my_version { query = query.filter(version.eq(my_version)); } if let Some(my_architecture) = my_architecture { query = query.filter(architecture.eq(my_architecture)); } Ok(query.load::(connection)?) } pub fn list_distro_suite_due_retries(my_distro: &str, my_suite: &str, connection: &mut SqliteConnection) -> Result> { use crate::schema::pkgbases::dsl::*; use crate::schema::queue; let pkgs = pkgbases .select((id, version)) .filter(distro.eq(my_distro)) .filter(suite.eq(my_suite)) .filter(next_retry.le(Utc::now().naive_utc())) .left_outer_join(queue::table.on(id.eq(queue::pkgbase_id))) .filter(queue::id.is_null()) .load(connection)?; Ok(pkgs) } pub fn schedule_retry(&mut self, retry_delay_base: i64) { let hours = (self.retries as i64 + 1) * retry_delay_base; debug!("scheduling retry in {} hours", hours); let delay = Duration::hours(hours); self.next_retry = Some((Utc::now() + delay).naive_utc()); } pub fn clear_retry(&mut self, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::pkgbases::columns::*; self.next_retry = None; diesel::update(pkgbases::table.filter(id.eq(self.id))) .set(( next_retry.eq(None as Option::), )) .execute(connection)?; Ok(()) } pub fn into_api_item(self) -> Result { let artifacts = serde_json::from_str(&self.artifacts).expect("Failed to deserialize artifact"); Ok(PkgGroup { name: self.name, version: self.version, distro: self.distro, suite: self.suite, architecture: self.architecture, input_url: self.input_url, artifacts, }) } pub fn update(&self, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::pkgbases::columns::*; diesel::update(pkgbases::table.filter(id.eq(self.id))) .set(self) .execute(connection)?; Ok(()) } pub fn delete(my_id: i32, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::pkgbases::dsl::*; diesel::delete(pkgbases.filter(id.eq(my_id))) .execute(connection)?; Ok(()) } pub fn delete_batch(batch: &[i32], connection: &mut SqliteConnection) -> Result<()> { use crate::schema::pkgbases::dsl::*; diesel::delete(pkgbases.filter(id.eq_any(batch))) .execute(connection)?; Ok(()) } } #[derive(Insertable, PartialEq, Eq, Debug, Clone)] #[diesel(table_name = pkgbases)] pub struct NewPkgBase { pub name: String, pub version: String, pub distro: String, pub suite: String, pub architecture: String, pub input_url: Option, pub artifacts: String, pub retries: i32, pub next_retry: Option, } impl NewPkgBase { pub fn insert(&self, connection: &mut SqliteConnection) -> Result<()> { diesel::insert_into(pkgbases::table) .values(self) .execute(connection)?; Ok(()) } pub fn insert_batch(pkgs: &[NewPkgBase], connection: &mut SqliteConnection) -> Result<()> { diesel::insert_into(pkgbases::table) .values(pkgs) .execute(connection)?; Ok(()) } } rebuilderd-0.22.1/src/models/queue.rs000064400000000000000000000154161046102023000156020ustar 00000000000000use crate::schema::*; use rebuilderd_common::errors::*; use rebuilderd_common::config::*; use diesel::prelude::*; use chrono::prelude::*; use chrono::Duration; use serde::{Serialize, Deserialize}; use rebuilderd_common::api::QueueItem; use crate::models::PkgBase; #[derive(Identifiable, Queryable, AsChangeset, Serialize, PartialEq, Eq, Debug)] #[diesel(table_name = queue)] pub struct Queued { pub id: i32, pub pkgbase_id: i32, pub version: String, pub required_backend: String, pub priority: i32, pub queued_at: NaiveDateTime, pub worker_id: Option, pub started_at: Option, pub last_ping: Option, } impl Queued { pub fn get_id(my_id: i32, connection: &mut SqliteConnection) -> Result { use crate::schema::queue::dsl::*; let item = queue .filter(id.eq(my_id)) .first::(connection)?; Ok(item) } pub fn get(pkg: i32, my_version: &str, connection: &mut SqliteConnection) -> Result> { use crate::schema::queue::dsl::*; let job = queue .filter(pkgbase_id.eq(pkg)) .filter(version.eq(my_version)) .first::(connection) .optional()?; Ok(job) } pub fn pop_next(my_worker_id: i32, supported_backends: &[String], connection: &mut SqliteConnection) -> Result> { use crate::schema::queue::dsl::*; let mut query = queue .filter(worker_id.is_null()) .into_boxed(); if !supported_backends.is_empty() { query = query .filter(required_backend.eq_any(supported_backends)); } let item = query .order_by((priority, queued_at, id)) .first::(connection) .optional()?; if let Some(mut item) = item { let now: DateTime = Utc::now(); item.worker_id = Some(my_worker_id); item.started_at = Some(now.naive_utc()); item.last_ping = Some(now.naive_utc()); item.update(connection)?; Ok(Some(item.into_api_item(connection)?)) } else { Ok(None) } } pub fn ping_job(&mut self, connection: &mut SqliteConnection) -> Result<()> { let now: DateTime = Utc::now(); self.last_ping = Some(now.naive_utc()); self.update(connection) } pub fn delete(&self, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::queue::columns::*; diesel::delete(queue::table .filter(id.eq(self.id)) ).execute(connection)?; Ok(()) } pub fn list(limit: Option, connection: &mut SqliteConnection) -> Result> { use crate::schema::queue::dsl::*; let query = Box::new(queue .order_by((priority, queued_at, id))); let results = if let Some(limit) = limit { query .limit(limit) .load::(connection)? } else { query .load::(connection)? }; Ok(results) } pub fn update(&self, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::queue::columns::*; diesel::update(queue::table.filter(id.eq(self.id))) .set(self) .execute(connection)?; Ok(()) } // TODO: is this still needed pub fn queue_batch(pkgbases: &[(i32, String)], required_backend: String, priority: i32, connection: &mut SqliteConnection) -> Result<()> { let pkgbases = pkgbases.iter() .map(|(id, version)| NewQueued::new(*id, version.to_string(), required_backend.clone(), priority)) .collect::>(); diesel::insert_into(queue::table) .values(pkgbases) // TODO: not supported by diesel yet // .on_conflict_do_nothing() .execute(connection)?; Ok(()) } pub fn insert_batch(queued: &[NewQueued], connection: &mut SqliteConnection) -> Result<()> { diesel::insert_into(queue::table) .values(queued) .execute(connection)?; Ok(()) } pub fn drop_for_pkgbases(pkgbases: &[i32], connection: &mut SqliteConnection) -> Result<()> { diesel::delete(queue::table.filter(queue::pkgbase_id.eq_any(pkgbases))) .execute(connection)?; Ok(()) } pub fn requeue(&self, connection: &mut SqliteConnection) -> Result<()> { diesel::update(queue::table) .filter(queue::id.eq(self.id)) .set(( queue::worker_id.eq(Option::::None), queue::started_at.eq(Option::::None), queue::last_ping.eq(Option::::None), )) .execute(connection)?; Ok(()) } pub fn free_stale_jobs(connection: &mut SqliteConnection) -> Result<()> { let now = Utc::now().naive_utc(); let deadline = now - Duration::seconds(PING_DEADLINE); diesel::update(queue::table.filter(queue::last_ping.lt(deadline))) .set(( queue::worker_id.eq(Option::::None), queue::started_at.eq(Option::::None), queue::last_ping.eq(Option::::None), )) .execute(connection)?; Ok(()) } pub fn into_api_item(self, connection: &mut SqliteConnection) -> Result { let pkgbase = PkgBase::get_id(self.pkgbase_id, connection)?; Ok(QueueItem { id: self.id, pkgbase: pkgbase.into_api_item()?, version: self.version, queued_at: self.queued_at, worker_id: self.worker_id, started_at: self.started_at, last_ping: self.last_ping, }) } } #[derive(Insertable, Serialize, Deserialize, Debug)] #[diesel(table_name = queue)] pub struct NewQueued { pub pkgbase_id: i32, pub version: String, pub required_backend: String, pub priority: i32, pub queued_at: NaiveDateTime, } impl NewQueued { pub fn new(pkgbase_id: i32, version: String, required_backend: String, priority: i32) -> NewQueued { let now: DateTime = Utc::now(); NewQueued { pkgbase_id, version, required_backend, priority, queued_at: now.naive_utc(), } } pub fn insert(&self, connection: &mut SqliteConnection) -> Result<()> { // TODO: on conflict do nothing after it landed in diesel sqlite if Queued::get(self.pkgbase_id, &self.version, connection)?.is_none() { diesel::insert_into(queue::table) .values(self) .execute(connection)?; } Ok(()) } } rebuilderd-0.22.1/src/models/worker.rs000064400000000000000000000066671046102023000157770ustar 00000000000000use crate::schema::*; use rebuilderd_common::api; use rebuilderd_common::config::*; use rebuilderd_common::errors::*; use diesel::prelude::*; use chrono::prelude::*; use chrono::Duration; use serde::{Serialize, Deserialize}; use std::net::IpAddr; #[derive(Identifiable, Queryable, AsChangeset, Serialize, PartialEq, Eq, Debug)] #[diesel(table_name = workers)] pub struct Worker { pub id: i32, pub key: String, pub addr: String, pub status: Option, pub last_ping: NaiveDateTime, pub online: bool, } impl Worker { pub fn get(my_key: &str, connection: &mut SqliteConnection) -> Result> { use crate::schema::workers::dsl::*; let worker = workers.filter(key.eq(my_key)) .first::(connection) .optional()?; Ok(worker) } pub fn list(connection: &mut SqliteConnection) -> Result> { use crate::schema::workers::dsl::*; let results = workers.filter(online.eq(true)) .load::(connection)?; Ok(results) } pub fn mark_stale_workers_offline(connection: &mut SqliteConnection) -> Result<()> { use crate::schema::workers::columns::*; let now = Utc::now().naive_utc(); let deadline = now - Duration::seconds(PING_DEADLINE); diesel::update(workers::table.filter(last_ping.lt(deadline))) .set(( online.eq(false), status.eq(None as Option::), )) .execute(connection)?; Ok(()) } pub fn bump_last_ping(&mut self, addr: &IpAddr) { self.addr = addr.to_string(); let now = Utc::now().naive_utc(); self.last_ping = now; self.online = true; } pub fn update(&self, connection: &mut SqliteConnection) -> Result<()> { use crate::schema::workers::columns::*; diesel::update(workers::table.filter(id.eq(self.id))) .set(self) .execute(connection)?; // workaround until we can have a model that can update to null at the same time if self.status.is_none() { diesel::update(workers::table.filter(id.eq(self.id))) .set( status.eq(None as Option::), ) .execute(connection)?; } Ok(()) } } impl From for api::Worker { fn from(worker: Worker) -> api::Worker { api::Worker { key: worker.key, addr: worker.addr, status: worker.status, last_ping: worker.last_ping, online: worker.online, } } } #[derive(Insertable, Serialize, Deserialize, Debug)] #[diesel(table_name = workers)] pub struct NewWorker { pub key: String, pub addr: String, pub status: Option, pub last_ping: NaiveDateTime, pub online: bool, } impl NewWorker { // we can refactor this into an upsert if we can make it return a Worker struct pub fn insert(&self, connection: &mut SqliteConnection) -> Result<()> { diesel::insert_into(workers::table) .values(self) .execute(connection)?; Ok(()) } pub fn new(key: String, addr: IpAddr, status: Option) -> NewWorker { let now: DateTime = Utc::now(); NewWorker { key, addr: addr.to_string(), status, last_ping: now.naive_utc(), online: true, } } } rebuilderd-0.22.1/src/schema.rs000064400000000000000000000034641046102023000144330ustar 00000000000000// @generated automatically by Diesel CLI. diesel::table! { builds (id) { id -> Integer, diffoscope -> Nullable, build_log -> Binary, attestation -> Nullable, } } diesel::table! { packages (id) { id -> Integer, pkgbase_id -> Integer, name -> Text, version -> Text, status -> Text, distro -> Text, suite -> Text, architecture -> Text, artifact_url -> Text, build_id -> Nullable, built_at -> Nullable, has_diffoscope -> Bool, has_attestation -> Bool, checksum -> Nullable, } } diesel::table! { pkgbases (id) { id -> Integer, name -> Text, version -> Text, distro -> Text, suite -> Text, architecture -> Text, input_url -> Nullable, artifacts -> Text, retries -> Integer, next_retry -> Nullable, } } diesel::table! { queue (id) { id -> Integer, pkgbase_id -> Integer, version -> Text, required_backend -> Text, priority -> Integer, queued_at -> Timestamp, worker_id -> Nullable, started_at -> Nullable, last_ping -> Nullable, } } diesel::table! { workers (id) { id -> Integer, key -> Text, addr -> Text, status -> Nullable, last_ping -> Timestamp, online -> Bool, } } diesel::joinable!(packages -> builds (build_id)); diesel::joinable!(packages -> pkgbases (pkgbase_id)); diesel::joinable!(queue -> pkgbases (pkgbase_id)); diesel::joinable!(queue -> workers (worker_id)); diesel::allow_tables_to_appear_in_same_query!(builds, packages, pkgbases, queue, workers,); rebuilderd-0.22.1/src/sync.rs000064400000000000000000000250761046102023000141520ustar 00000000000000use crate::models; use diesel::Connection; use diesel::SqliteConnection; use rebuilderd_common::api::*; use rebuilderd_common::errors::*; use rebuilderd_common::{PkgGroup, Status}; use std::collections::HashMap; const DEFAULT_QUEUE_PRIORITY: i32 = 1; // this holds all pkgsbases we know about // when syncing we remove all pkgbases that are still in the import // the remaining pkgbases are not referenced in the new import that was submitted and groing to be deleted pub struct CurrentArtifactNamespace { pkgbases: HashMap, } impl CurrentArtifactNamespace { pub fn load_current_namespace_from_database( distro: &str, suite: &str, connection: &mut SqliteConnection, ) -> Result { let mut existing_pkgbases = HashMap::new(); for pkgbase in models::PkgBase::list_distro_suite(distro, suite, connection)? { let key = Self::gen_key_for_pkgbase(&pkgbase); debug!( "adding known pkgbase with key {:?} for distro={:?}, suite={:?}", key, distro, suite ); trace!( "adding known pkgbase with key {:?} for distro={:?}, suite={:?} to {:?}", key, distro, suite, pkgbase ); existing_pkgbases.insert(key, pkgbase); } Ok(CurrentArtifactNamespace { pkgbases: existing_pkgbases, }) } fn gen_key(name: &str, version: &str, architecture: &str) -> String { format!("{:?}-{:?}-{:?}", name, version, architecture) } #[inline] fn gen_key_for_pkgbase(pkgbase: &models::PkgBase) -> String { Self::gen_key(&pkgbase.name, &pkgbase.version, &pkgbase.architecture) } #[inline] fn gen_key_for_pkggroup(pkggroup: &PkgGroup) -> String { Self::gen_key(&pkggroup.name, &pkggroup.version, &pkggroup.architecture) } // returns Some(()) if the group was already known and remove // returns None if the group wasn't known and nothing changed pub fn mark_pkggroup_still_present(&mut self, group: &PkgGroup) -> Option<()> { let key = Self::gen_key_for_pkggroup(group); if self.pkgbases.remove_entry(&key).is_some() { debug!("pkgbase is already present: {:?}", key); Some(()) } else { debug!("pkgbase is not yet present: {:?}", key); None } } } // this holds all pkgbases from the import that we didn't know about yet // all of them are going to be added to the database at the end // builds also need to be scheduled afterwards #[derive(Debug, Default)] pub struct NewArtifactNamespace { groups: Vec, } impl NewArtifactNamespace { pub fn new() -> Self { NewArtifactNamespace::default() } pub fn add(&mut self, group: PkgGroup) { self.groups.push(group); } } // TODO: this should be into_api_item fn pkggroup_to_newpkgbase(group: &PkgGroup) -> Result { let artifacts = serde_json::to_string(&group.artifacts)?; Ok(models::NewPkgBase { name: group.name.clone(), version: group.version.clone(), distro: group.distro.clone(), suite: group.suite.clone(), architecture: group.architecture.clone(), input_url: group.input_url.clone(), artifacts, retries: 0, next_retry: None, }) } fn sync(import: &SuiteImport, connection: &mut SqliteConnection) -> Result<()> { connection.transaction::<(), _, _>(|connection| { let distro = &import.distro; let suite = &import.suite; info!("received submitted artifact groups {:?}", import.groups.len()); let mut new_namespace = NewArtifactNamespace::new(); info!("loading existing artifact groups from database..."); let mut current_namespace = CurrentArtifactNamespace::load_current_namespace_from_database(distro, suite, connection)?; info!("found existing artifact groups: len={}", current_namespace.pkgbases.len()); info!("checking groups already in the database..."); let mut num_already_in_database = 0; for group in &import.groups { trace!("received group during import: {:?}", group); if current_namespace.mark_pkggroup_still_present(group).is_some() { num_already_in_database += 1; } else { new_namespace.add(group.clone()); } } info!("found groups already in database: len={}", num_already_in_database); info!("found groups that need to be added to database: len={}", new_namespace.groups.len()); info!("found groups no longer present: len={}", current_namespace.pkgbases.len()); let pkgbase_delete_queue = current_namespace.pkgbases.values().map(|x| x.id).collect::>(); // deleting groups no longer present let mut progress_group_delete = 0; for delete_batch in pkgbase_delete_queue.chunks(1_000) { progress_group_delete += delete_batch.len(); info!("deleting groups in batch: {}/{}", progress_group_delete, pkgbase_delete_queue.len()); if log::log_enabled!(log::Level::Trace) { for pkgbase in delete_batch { trace!("pkgbase in this batch: {:?}", pkgbase); } } models::PkgBase::delete_batch(delete_batch, connection) .with_context(|| anyhow!("Failed to delete pkgbases"))?; } // inserting new groups let mut progress_group_insert = 0; for group_batch in new_namespace.groups.chunks(1_000) { progress_group_insert += group_batch.len(); info!("inserting new groups in batch: {}/{}", progress_group_insert, new_namespace.groups.len()); let group_batch = group_batch.iter() .map(pkggroup_to_newpkgbase) .collect::>>()?; if log::log_enabled!(log::Level::Trace) { for group in &group_batch { trace!("group in this batch: {:?}", group); } } models::NewPkgBase::insert_batch(&group_batch, connection)?; } // detecting pkgbase ids for new artifacts let mut progress_pkgbase_detect = 0; let mut backlog_insert_pkgs = Vec::new(); let mut backlog_insert_queue = Vec::new(); for group_batch in new_namespace.groups.chunks(1_000) { progress_pkgbase_detect += group_batch.len(); info!("detecting pkgbase ids for new artifacts: {}/{}", progress_pkgbase_detect, new_namespace.groups.len()); for group in group_batch { debug!("searching for pkgbases {:?} {:?} {:?} {:?} {:?}", group.name, group.version, distro, suite, group.architecture); let pkgbases = models::PkgBase::get_by(&group.name, distro, suite, Some(&group.version), Some(&group.architecture), connection)?; if pkgbases.len() != 1 { bail!("Failed to determine pkgbase in database for grouop (expected=1, found={}): {:?}", pkgbases.len(), group); } let pkgbase_id = pkgbases[0].id; for artifact in &group.artifacts { backlog_insert_pkgs.push(models::NewPackage { pkgbase_id, name: artifact.name.clone(), version: artifact.version.clone(), status: Status::Unknown.to_string(), distro: distro.clone(), suite: suite.clone(), architecture: group.architecture.clone(), artifact_url: artifact.url.clone(), build_id: None, built_at: None, has_diffoscope: false, has_attestation: false, checksum: None, }); } backlog_insert_queue.push(models::NewQueued::new(pkgbase_id, group.version.clone(), distro.to_string(), DEFAULT_QUEUE_PRIORITY)); } } // inserting new packages let mut progress_pkg_inserts = 0; for pkg_batch in backlog_insert_pkgs.chunks(1_000) { progress_pkg_inserts += pkg_batch.len(); info!("inserting new packages in batch: {}/{}", progress_pkg_inserts, backlog_insert_pkgs.len()); if log::log_enabled!(log::Level::Trace) { for pkg in pkg_batch { trace!("pkg in this batch: {:?}", pkg); } } models::NewPackage::insert_batch(pkg_batch, connection)?; } // inserting to queue // TODO: check if queueing has been disabled in the request, eg. to initially fill the database let mut progress_queue_inserts = 0; for queue_batch in backlog_insert_queue.chunks(1_000) { progress_queue_inserts += queue_batch.len(); info!("inserting to queue in batch: {}/{}", progress_queue_inserts, backlog_insert_queue.len()); if log::log_enabled!(log::Level::Trace) { for queued in queue_batch { trace!("queued in this batch: {:?}", queued); } } models::Queued::insert_batch(queue_batch, connection)?; } Ok(()) })?; info!("successfully synced import to database"); Ok(()) } fn retry(import: &SuiteImport, connection: &mut SqliteConnection) -> Result<()> { info!("selecting packages with due retries"); let queue = models::PkgBase::list_distro_suite_due_retries( import.distro.as_ref(), &import.suite, connection, )?; info!("queueing new retries"); for bases in queue.chunks(1_000) { debug!("queue: {:?}", bases.len()); models::Queued::queue_batch(bases, import.distro.to_string(), 2, connection)?; } info!("successfully triggered {} retries", queue.len()); Ok(()) } pub fn run(import: SuiteImport, connection: &mut SqliteConnection) -> Result<()> { sync(&import, connection)?; retry(&import, connection)?; Ok(()) } rebuilderd-0.22.1/src/web.rs000064400000000000000000000010551046102023000137420ustar 00000000000000pub use actix_web::web::{post, resource, Data, Json, JsonConfig, Path, Query}; use rebuilderd_common::errors; use std::fmt; #[derive(Debug)] pub struct Error { err: rebuilderd_common::errors::Error, } pub type Result = ::std::result::Result; impl fmt::Display for Error { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { write!(w, "{:#}", self.err) } } impl actix_web::error::ResponseError for Error {} impl From for Error { fn from(err: errors::Error) -> Error { Error { err } } }