From 95e21cb4fecc6eb941057f87876d3b753d3ed58a Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 29 Mar 2023 18:38:16 +0200 Subject: [PATCH 1/4] feat(gitea): Add Gitea resource to fetch PRs --- images/gitea/.dockerignore | 3 + images/gitea/Cargo.lock | 1441 +++++++++++++++++++++++++++++++++++ images/gitea/Cargo.toml | 22 + images/gitea/Dockerfile | 41 + images/gitea/README.adoc | 23 + images/gitea/shims/pr/check | 2 + images/gitea/shims/pr/in | 2 + images/gitea/shims/pr/out | 2 + images/gitea/src/cmd/pr.rs | 147 ++++ images/gitea/src/main.rs | 54 ++ images/gitea/src/types.rs | 6 + 11 files changed, 1743 insertions(+) create mode 100644 images/gitea/.dockerignore create mode 100644 images/gitea/Cargo.lock create mode 100644 images/gitea/Cargo.toml create mode 100644 images/gitea/Dockerfile create mode 100644 images/gitea/README.adoc create mode 100755 images/gitea/shims/pr/check create mode 100755 images/gitea/shims/pr/in create mode 100755 images/gitea/shims/pr/out create mode 100644 images/gitea/src/cmd/pr.rs create mode 100644 images/gitea/src/main.rs create mode 100644 images/gitea/src/types.rs diff --git a/images/gitea/.dockerignore b/images/gitea/.dockerignore new file mode 100644 index 0000000..456a7a8 --- /dev/null +++ b/images/gitea/.dockerignore @@ -0,0 +1,3 @@ +.git/ +target/ +README.adoc diff --git a/images/gitea/Cargo.lock b/images/gitea/Cargo.lock new file mode 100644 index 0000000..af9935b --- /dev/null +++ b/images/gitea/Cargo.lock @@ -0,0 +1,1441 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anstream" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-wincon", + "concolor-override", + "concolor-query", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" + +[[package]] +name = "anstyle-parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-wincon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +dependencies = [ + "anstyle", + "windows-sys 0.45.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6efb5f0a41b5ef5b50c5da28c07609c20091df0c1fc33d418fa2a7e693c2b624" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671fcaa5debda4b9a84aa7fde49c907c8986c0e6ab927e04217c9cb74e7c8bc9" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "once_cell", + "strsim", + "unicase", + "unicode-width", +] + +[[package]] +name = "clap_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.11", +] + +[[package]] +name = "clap_lex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + +[[package]] +name = "color-eyre" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "concolor-override" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" + +[[package]] +name = "concolor-query" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" +dependencies = [ + "windows-sys 0.45.0", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "eyre" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +dependencies = [ + "indenter", + "once_cell", +] + +[[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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" + +[[package]] +name = "futures-io" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" + +[[package]] +name = "futures-sink" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" + +[[package]] +name = "futures-task" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" + +[[package]] +name = "futures-util" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +dependencies = [ + "futures-core", + "futures-io", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + +[[package]] +name = "gitea" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "reqwest", + "serde", + "serde_json", + "time", + "tracing", + "tracing-error", + "tracing-subscriber", + "url", +] + +[[package]] +name = "h2" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + +[[package]] +name = "is-terminal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.45.0", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "linux-raw-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[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.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.45.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro2" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "reqwest" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" + +[[package]] +name = "rustix" +version = "0.37.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c348b5dc624ecee40108aa2922fed8bad89d7fcc2b9f8cb18f632898ac4a37f9" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.11", +] + +[[package]] +name = "serde_json" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +dependencies = [ + "itoa", + "ryu", + "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 = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e3787bb71465627110e7d87ed4faaa36c1f61042ee67badb9e2ef173accc40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +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.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" +dependencies = [ + "autocfg", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "windows-sys 0.45.0", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-util" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "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 = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[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-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] diff --git a/images/gitea/Cargo.toml b/images/gitea/Cargo.toml new file mode 100644 index 0000000..f3dbee5 --- /dev/null +++ b/images/gitea/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "gitea" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.2.0", features = ["cargo", "color", "unicode", "std", "derive"] } +color-eyre = "0.6.2" +reqwest = { version = "0.11.16", default-features = false, features = ["blocking", "json", "rustls-tls-native-roots"] } +serde_json = "1.0.95" +serde = { version = "1.0.159", features = ["derive"] } +time = { version = "0.3.20", features = ["formatting", "macros", "serde"] } +tracing = "0.1.37" +tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } +url = { version = "2.3.1", features = ["serde"] } +tracing-error = "0.2.0" + +[profile.release] +strip = "debuginfo" +lto = true diff --git a/images/gitea/Dockerfile b/images/gitea/Dockerfile new file mode 100644 index 0000000..1916764 --- /dev/null +++ b/images/gitea/Dockerfile @@ -0,0 +1,41 @@ +FROM rust:alpine AS builder + +# Use a dummy project to ensure the crate index is up to date. +RUN set -e; \ + cargo new --color always /tmp/dummy; \ + cargo add --color always --manifest-path /tmp/dummy/Cargo.toml serde; \ + rm -rf /tmp/dummy; \ + cargo new --color always --bin /app + +WORKDIR /app + +RUN apk add --no-cache \ + # openssl-dev \ + # pkgconfig \ + musl-dev + +# Build dependencies with a dummy project to cache those regardless of changes +# in the actual source code +COPY ./Cargo.toml ./Cargo.lock /app/ +RUN cargo build --color always --release --locked + +COPY . . +RUN touch -a -m ./src/main.rs && cargo build --color always --release --locked + +FROM alpine AS pr +# FROM debian:bullseye-slim AS pr + +RUN apk add --no-cache ca-certificates +# RUN set -e; \ +# apt-get update; \ +# apt-get install -y --no-install-recommends \ +# ca-certificates; \ +# rm -fr /var/apt/lists/*; + +LABEL version="0.1.0" + +ENV RUST_BACKTRACE=1 +ENV RUST_LOG=info + +COPY ./shims/pr/* /opt/resource/ +COPY --from=builder /app/target/release/gitea /bin/ diff --git a/images/gitea/README.adoc b/images/gitea/README.adoc new file mode 100644 index 0000000..b65b7ed --- /dev/null +++ b/images/gitea/README.adoc @@ -0,0 +1,23 @@ += Gitea Concourse Resource + +== Actions + +[source,yaml] +---- +- name: prs + type: gitea-pr + icon: git + source: + access_token: ((my_cred.token)) + repo: some-repo + owner: some_user_or_org + hostname: https://example.com +---- + +=== `check` + +Returns the list of currently active pull requests + +=== `in` + +Writes information about the currently active pull requests to `$1/prs.json`, which can be consumed by a `load_var` step. diff --git a/images/gitea/shims/pr/check b/images/gitea/shims/pr/check new file mode 100755 index 0000000..9bdeef2 --- /dev/null +++ b/images/gitea/shims/pr/check @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea pr check "$@" diff --git a/images/gitea/shims/pr/in b/images/gitea/shims/pr/in new file mode 100755 index 0000000..b30fefb --- /dev/null +++ b/images/gitea/shims/pr/in @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea pr in "$@" diff --git a/images/gitea/shims/pr/out b/images/gitea/shims/pr/out new file mode 100755 index 0000000..719df67 --- /dev/null +++ b/images/gitea/shims/pr/out @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea pr out "$@" diff --git a/images/gitea/src/cmd/pr.rs b/images/gitea/src/cmd/pr.rs new file mode 100644 index 0000000..b730202 --- /dev/null +++ b/images/gitea/src/cmd/pr.rs @@ -0,0 +1,147 @@ +use std::fs; +use std::io::{self, Read}; +use std::path::Path; + +use color_eyre::eyre::{self, Context}; +use color_eyre::Result; +use reqwest::blocking::{Client, Response}; +use reqwest::header::HeaderMap; +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; +use url::Url; + +use crate::types::PullRequest; +use crate::Action; + +static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); + +#[derive(Deserialize, Serialize, Debug)] +struct Source { + access_token: String, + owner: String, + repo: String, + url: Url, +} + +#[derive(Deserialize, Serialize, Debug)] +struct Version { + prs: Vec, + #[serde(with = "time::serde::timestamp")] + timestamp: OffsetDateTime, +} + +#[derive(Deserialize, Serialize, Debug)] +struct Config { + /// Resource configuration. + /// Passed verbatim from the definition in the pipeline. + source: Source, + /// For 'check': + /// Previous version of this resource. + /// Will be empty for the very first request. + /// For 'in': + /// The version metadata to create this as. + version: Option, +} + +#[tracing::instrument(skip_all)] +fn make_client(src: &Source) -> Result { + let mut headers = HeaderMap::new(); + headers.insert( + "Authorization", + format!("token {}", src.access_token).try_into()?, + ); + + Client::builder() + .default_headers(headers) + .user_agent(USER_AGENT) + .build() + .map_err(From::from) +} + +#[tracing::instrument(skip_all)] +fn fetch(src: &Source) -> Result { + let client = make_client(&src).wrap_err("Failed to create HTTP client")?; + let url = src + .url + .join(&format!("api/v1/repos/{}/{}/pulls", src.owner, src.repo)) + .wrap_err("Invalid URL")?; + + client + .get(url) + .query(&[("sort", "oldest"), ("state", "open")]) + .send() + .map_err(From::from) +} + +#[tracing::instrument(skip_all)] +fn action_check(conf: Config) -> Result<()> { + let prs: Vec = fetch(&conf.source)?.json()?; + let mut version = Version { + prs: prs.iter().map(|pr| pr.number.to_string()).collect(), + timestamp: OffsetDateTime::now_utc(), + }; + version.prs.sort_unstable(); + + let out = if let Some(prev) = conf.version { + if prev.prs == version.prs { + vec![prev] + } else { + vec![prev, version] + } + } else { + vec![version] + }; + + serde_json::to_writer_pretty(io::stdout(), &out) + .wrap_err("Failed to write result to stdout")?; + + Ok(()) +} + +#[tracing::instrument(skip_all)] +fn action_in(conf: Config, dest: impl AsRef) -> Result<()> { + let version = if let Some(version) = conf.version { + version + } else { + eyre::bail!("Version missing in 'in' action."); + }; + + let bytes = fetch(&conf.source)?.bytes()?; + let prs: Vec = serde_json::from_slice(&bytes)?; + + { + let mut prs: Vec<_> = prs.iter().map(|pr| pr.number.to_string()).collect(); + prs.sort_unstable(); + if version.prs != prs { + eyre::bail!("Version to fetch does not match current resource."); + } + } + + let path = dest.as_ref().join("prs.json"); + let _ = fs::create_dir_all(dest); + fs::write(&path, &bytes)?; + + Ok(()) +} + +#[tracing::instrument(skip_all)] +pub(crate) fn run(action: &Action) -> Result<()> { + let config: Config = { + let mut buf = String::new(); + io::stdin() + .read_to_string(&mut buf) + .wrap_err("Failed to read from stdin")?; + + if buf.is_empty() { + eyre::bail!("No data received on stdin"); + } + + serde_json::from_str(&buf).wrap_err("Failed to parse stdin")? + }; + + match action { + Action::Check => action_check(config), + Action::In { dest } => action_in(config, dest), + Action::Out => Ok(()), + } +} diff --git a/images/gitea/src/main.rs b/images/gitea/src/main.rs new file mode 100644 index 0000000..f1989f0 --- /dev/null +++ b/images/gitea/src/main.rs @@ -0,0 +1,54 @@ +use std::path::PathBuf; + +use clap::{Parser, Subcommand}; +use color_eyre::Result; +use tracing_error::ErrorLayer; +use tracing_subscriber::fmt; +use tracing_subscriber::prelude::*; +use tracing_subscriber::EnvFilter; + +#[derive(Debug, Parser)] +#[command(author, version, about, long_about = None)] +#[command(propagate_version = true)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Clone, Debug, Subcommand)] +enum Commands { + Pr { + #[command(subcommand)] + action: Action, + }, +} + +#[derive(Clone, Debug, Subcommand)] +pub(crate) enum Action { + Check, + In { dest: PathBuf }, + Out, +} + +mod types; +mod cmd { + pub mod pr; +} + +// #[tracing::instrument] +fn main() -> Result<()> { + let filter_layer = EnvFilter::try_from_default_env() + .or_else(|_| EnvFilter::try_new("info")) + .unwrap(); + + tracing_subscriber::registry() + .with(filter_layer) + .with(ErrorLayer::new(fmt::format::Pretty::default())) + .init(); + + let cli = Cli::parse(); + + match &cli.command { + Commands::Pr { action } => cmd::pr::run(action), + } +} diff --git a/images/gitea/src/types.rs b/images/gitea/src/types.rs new file mode 100644 index 0000000..09b611b --- /dev/null +++ b/images/gitea/src/types.rs @@ -0,0 +1,6 @@ +use serde::Deserialize; + +#[derive(Clone, Debug, Deserialize)] +pub struct PullRequest { + pub number: u64, +} From 43b974361ee58840aa399f2b02975dd560d7c214 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 29 Mar 2023 23:49:57 +0200 Subject: [PATCH 2/4] fix(gitea): Fix version data Concourse only accepts strings for values in the version data. --- images/gitea/Cargo.lock | 151 ++++++++++++++++--------------------- images/gitea/Cargo.toml | 6 +- images/gitea/src/cmd/pr.rs | 72 ++++++++++++++---- images/gitea/src/main.rs | 13 ---- images/gitea/src/types.rs | 14 ++++ 5 files changed, 135 insertions(+), 121 deletions(-) diff --git a/images/gitea/Cargo.lock b/images/gitea/Cargo.lock index af9935b..52cf3f5 100644 --- a/images/gitea/Cargo.lock +++ b/images/gitea/Cargo.lock @@ -159,6 +159,29 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +[[package]] +name = "cli-table" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adfbb116d9e2c4be7011360d0c0bee565712c11e969c9609b25b619366dc379d" +dependencies = [ + "cli-table-derive", + "csv", + "termcolor", + "unicode-width", +] + +[[package]] +name = "cli-table-derive" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af3bfb9da627b0a6c467624fb7963921433774ed435493b5c08a3053e829ad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "color-eyre" version = "0.6.2" @@ -217,6 +240,27 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "csv" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "encoding_rs" version = "0.8.32" @@ -331,14 +375,12 @@ name = "gitea" version = "0.1.0" dependencies = [ "clap", + "cli-table", "color-eyre", "reqwest", "serde", "serde_json", "time", - "tracing", - "tracing-error", - "tracing-subscriber", "url", ] @@ -556,15 +598,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata", -] - [[package]] name = "memchr" version = "2.5.0" @@ -598,16 +631,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "num_cpus" version = "1.15.0" @@ -639,12 +662,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "owo-colors" version = "3.5.0" @@ -687,30 +704,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "regex" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "reqwest" version = "0.11.16" @@ -927,12 +920,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - [[package]] name = "socket2" version = "0.4.9" @@ -977,6 +964,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -1084,21 +1080,9 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "tracing-core" version = "0.1.30" @@ -1119,33 +1103,15 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "tracing-log" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - [[package]] name = "tracing-subscriber" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", "sharded-slab", - "smallvec", "thread_local", - "tracing", "tracing-core", - "tracing-log", ] [[package]] @@ -1344,6 +1310,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/images/gitea/Cargo.toml b/images/gitea/Cargo.toml index f3dbee5..51e08d7 100644 --- a/images/gitea/Cargo.toml +++ b/images/gitea/Cargo.toml @@ -11,11 +11,9 @@ color-eyre = "0.6.2" reqwest = { version = "0.11.16", default-features = false, features = ["blocking", "json", "rustls-tls-native-roots"] } serde_json = "1.0.95" serde = { version = "1.0.159", features = ["derive"] } -time = { version = "0.3.20", features = ["formatting", "macros", "serde"] } -tracing = "0.1.37" -tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } +time = { version = "0.3.20", features = ["formatting", "parsing", "serde"] } url = { version = "2.3.1", features = ["serde"] } -tracing-error = "0.2.0" +cli-table = "0.4.7" [profile.release] strip = "debuginfo" diff --git a/images/gitea/src/cmd/pr.rs b/images/gitea/src/cmd/pr.rs index b730202..2e5577f 100644 --- a/images/gitea/src/cmd/pr.rs +++ b/images/gitea/src/cmd/pr.rs @@ -2,11 +2,14 @@ use std::fs; use std::io::{self, Read}; use std::path::Path; +use cli_table::format::Justify; +use cli_table::{print_stderr, Cell, Style, Table}; use color_eyre::eyre::{self, Context}; use color_eyre::Result; use reqwest::blocking::{Client, Response}; use reqwest::header::HeaderMap; use serde::{Deserialize, Serialize}; +use serde_json::json; use time::OffsetDateTime; use url::Url; @@ -25,11 +28,26 @@ struct Source { #[derive(Deserialize, Serialize, Debug)] struct Version { - prs: Vec, - #[serde(with = "time::serde::timestamp")] + prs: String, + #[serde(with = "time::serde::iso8601")] timestamp: OffsetDateTime, } +impl<'a, I: Iterator> From for Version { + fn from(prs: I) -> Self { + Self { + prs: prs.fold(String::new(), |mut s, pr| { + if !s.is_empty() { + s.push(','); + } + s.push_str(&pr.number.to_string()); + s + }), + timestamp: OffsetDateTime::now_utc(), + } + } +} + #[derive(Deserialize, Serialize, Debug)] struct Config { /// Resource configuration. @@ -43,7 +61,6 @@ struct Config { version: Option, } -#[tracing::instrument(skip_all)] fn make_client(src: &Source) -> Result { let mut headers = HeaderMap::new(); headers.insert( @@ -58,7 +75,6 @@ fn make_client(src: &Source) -> Result { .map_err(From::from) } -#[tracing::instrument(skip_all)] fn fetch(src: &Source) -> Result { let client = make_client(&src).wrap_err("Failed to create HTTP client")?; let url = src @@ -73,14 +89,9 @@ fn fetch(src: &Source) -> Result { .map_err(From::from) } -#[tracing::instrument(skip_all)] fn action_check(conf: Config) -> Result<()> { let prs: Vec = fetch(&conf.source)?.json()?; - let mut version = Version { - prs: prs.iter().map(|pr| pr.number.to_string()).collect(), - timestamp: OffsetDateTime::now_utc(), - }; - version.prs.sort_unstable(); + let version = Version::from(prs.iter()); let out = if let Some(prev) = conf.version { if prev.prs == version.prs { @@ -92,15 +103,40 @@ fn action_check(conf: Config) -> Result<()> { vec![version] }; + let table: Vec<_> = prs + .iter() + .map(|pr| { + vec![ + pr.number.cell().justify(Justify::Center), + pr.title.clone().cell(), + pr.user.login.clone().cell(), + pr.base.r#ref.clone().cell(), + pr.head.r#ref.clone().cell(), + ] + }) + .collect(); + + let table = table + .table() + .title(vec![ + "#".cell().bold(true), + "Title".cell().bold(true), + "User".cell().bold(true), + "Base".cell().bold(true), + "Head".cell().bold(true), + ]) + .bold(true); + + let _ = print_stderr(table); + serde_json::to_writer_pretty(io::stdout(), &out) .wrap_err("Failed to write result to stdout")?; Ok(()) } -#[tracing::instrument(skip_all)] fn action_in(conf: Config, dest: impl AsRef) -> Result<()> { - let version = if let Some(version) = conf.version { + let old_version = if let Some(version) = conf.version { version } else { eyre::bail!("Version missing in 'in' action."); @@ -108,11 +144,10 @@ fn action_in(conf: Config, dest: impl AsRef) -> Result<()> { let bytes = fetch(&conf.source)?.bytes()?; let prs: Vec = serde_json::from_slice(&bytes)?; + let version = Version::from(prs.iter()); { - let mut prs: Vec<_> = prs.iter().map(|pr| pr.number.to_string()).collect(); - prs.sort_unstable(); - if version.prs != prs { + if version.prs != old_version.prs { eyre::bail!("Version to fetch does not match current resource."); } } @@ -121,10 +156,15 @@ fn action_in(conf: Config, dest: impl AsRef) -> Result<()> { let _ = fs::create_dir_all(dest); fs::write(&path, &bytes)?; + let out = json!({ + "version": version, + }); + + serde_json::to_writer_pretty(io::stdout(), &out)?; + Ok(()) } -#[tracing::instrument(skip_all)] pub(crate) fn run(action: &Action) -> Result<()> { let config: Config = { let mut buf = String::new(); diff --git a/images/gitea/src/main.rs b/images/gitea/src/main.rs index f1989f0..1f71387 100644 --- a/images/gitea/src/main.rs +++ b/images/gitea/src/main.rs @@ -2,10 +2,6 @@ use std::path::PathBuf; use clap::{Parser, Subcommand}; use color_eyre::Result; -use tracing_error::ErrorLayer; -use tracing_subscriber::fmt; -use tracing_subscriber::prelude::*; -use tracing_subscriber::EnvFilter; #[derive(Debug, Parser)] #[command(author, version, about, long_about = None)] @@ -37,15 +33,6 @@ mod cmd { // #[tracing::instrument] fn main() -> Result<()> { - let filter_layer = EnvFilter::try_from_default_env() - .or_else(|_| EnvFilter::try_new("info")) - .unwrap(); - - tracing_subscriber::registry() - .with(filter_layer) - .with(ErrorLayer::new(fmt::format::Pretty::default())) - .init(); - let cli = Cli::parse(); match &cli.command { diff --git a/images/gitea/src/types.rs b/images/gitea/src/types.rs index 09b611b..17f450e 100644 --- a/images/gitea/src/types.rs +++ b/images/gitea/src/types.rs @@ -1,6 +1,20 @@ use serde::Deserialize; +#[derive(Clone, Debug, Deserialize)] +pub struct Ref { + pub r#ref: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct User { + pub login: String, +} + #[derive(Clone, Debug, Deserialize)] pub struct PullRequest { pub number: u64, + pub title: String, + pub user: User, + pub base: Ref, + pub head: Ref, } From 3cde8dde52586a22c92892c513200e4fe6e665de Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 20 Nov 2023 16:29:32 +0100 Subject: [PATCH 3/4] gitea: Implement package --- images/gitea/Cargo.lock | 118 +++++++++++- images/gitea/Cargo.toml | 9 +- images/gitea/Dockerfile | 19 +- images/gitea/shims/package/check | 2 + images/gitea/shims/package/in | 2 + images/gitea/shims/package/out | 2 + images/gitea/src/cmd/package.rs | 301 +++++++++++++++++++++++++++++++ images/gitea/src/cmd/pr.rs | 6 +- images/gitea/src/main.rs | 12 +- images/gitea/src/types.rs | 28 ++- images/gitea/test.sh | 38 ++++ 11 files changed, 514 insertions(+), 23 deletions(-) create mode 100755 images/gitea/shims/package/check create mode 100755 images/gitea/shims/package/in create mode 100755 images/gitea/shims/package/out create mode 100644 images/gitea/src/cmd/package.rs create mode 100755 images/gitea/test.sh diff --git a/images/gitea/Cargo.lock b/images/gitea/Cargo.lock index 52cf3f5..e0411d0 100644 --- a/images/gitea/Cargo.lock +++ b/images/gitea/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.2.6" @@ -90,6 +99,16 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bstr" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.12.0" @@ -185,8 +204,7 @@ dependencies = [ [[package]] name = "color-eyre" version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +source = "git+https://github.com/sclu1034/color-eyre.git?branch=fork#0fa05eba9954be223b06468c8760b97e660f9941" dependencies = [ "backtrace", "color-spantrace", @@ -372,11 +390,12 @@ checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "gitea" -version = "0.1.0" +version = "0.1.2" dependencies = [ "clap", "cli-table", "color-eyre", + "globwalk", "reqwest", "serde", "serde_json", @@ -384,6 +403,30 @@ dependencies = [ "url", ] +[[package]] +name = "globset" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + [[package]] name = "h2" version = "0.3.16" @@ -511,6 +554,23 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ignore" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "indenter" version = "0.3.3" @@ -600,9 +660,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "mime" @@ -704,6 +764,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "reqwest" version = "0.11.16" @@ -817,6 +906,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.21" @@ -1192,6 +1290,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" diff --git a/images/gitea/Cargo.toml b/images/gitea/Cargo.toml index 51e08d7..7ec1d78 100644 --- a/images/gitea/Cargo.toml +++ b/images/gitea/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gitea" -version = "0.1.0" +version = "0.1.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -14,7 +14,14 @@ serde = { version = "1.0.159", features = ["derive"] } time = { version = "0.3.20", features = ["formatting", "parsing", "serde"] } url = { version = "2.3.1", features = ["serde"] } cli-table = "0.4.7" +globwalk = "0.8.1" [profile.release] strip = "debuginfo" lto = true + +[profile.dev.package.backtrace] +opt-level = 3 + +[patch.crates-io] +color-eyre = { git = "https://github.com/sclu1034/color-eyre.git", branch = "fork" } diff --git a/images/gitea/Dockerfile b/images/gitea/Dockerfile index 1916764..8dc4bea 100644 --- a/images/gitea/Dockerfile +++ b/images/gitea/Dockerfile @@ -22,20 +22,19 @@ RUN cargo build --color always --release --locked COPY . . RUN touch -a -m ./src/main.rs && cargo build --color always --release --locked -FROM alpine AS pr -# FROM debian:bullseye-slim AS pr +FROM alpine AS final RUN apk add --no-cache ca-certificates -# RUN set -e; \ -# apt-get update; \ -# apt-get install -y --no-install-recommends \ -# ca-certificates; \ -# rm -fr /var/apt/lists/*; - -LABEL version="0.1.0" ENV RUST_BACKTRACE=1 ENV RUST_LOG=info -COPY ./shims/pr/* /opt/resource/ COPY --from=builder /app/target/release/gitea /bin/ + +# Put this last, as it's the only thing that's different between variants. +# This way, the previous layers can all be shared. + +ARG VARIANT="missing build arg 'VARIANT'" +ARG VERSION="0.1.0" +LABEL version="$VERSION" +COPY ./shims/${VARIANT}/* /opt/resource/ diff --git a/images/gitea/shims/package/check b/images/gitea/shims/package/check new file mode 100755 index 0000000..82430e1 --- /dev/null +++ b/images/gitea/shims/package/check @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea package check "$@" diff --git a/images/gitea/shims/package/in b/images/gitea/shims/package/in new file mode 100755 index 0000000..48c8805 --- /dev/null +++ b/images/gitea/shims/package/in @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea package in "$@" diff --git a/images/gitea/shims/package/out b/images/gitea/shims/package/out new file mode 100755 index 0000000..0ea48e9 --- /dev/null +++ b/images/gitea/shims/package/out @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea package out "$@" diff --git a/images/gitea/src/cmd/package.rs b/images/gitea/src/cmd/package.rs new file mode 100644 index 0000000..ec43d59 --- /dev/null +++ b/images/gitea/src/cmd/package.rs @@ -0,0 +1,301 @@ +use std::fs; +use std::io::{self, Read, Write}; +use std::path::Path; + +use cli_table::format::Justify; +use cli_table::{Cell, Style, Table}; +use color_eyre::eyre::{self, Context}; +use color_eyre::{Help, Report, Result}; +use globwalk::{DirEntry, GlobWalkerBuilder}; +use reqwest::blocking::Client; +use reqwest::header::HeaderMap; +use reqwest::StatusCode; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use time::format_description::well_known::Iso8601; +use url::Url; + +use crate::types::{Package, PackageType}; +use crate::{Action, USER_AGENT}; + +#[derive(Deserialize, Serialize, Debug)] +struct Source { + access_token: String, + owner: String, + url: Url, + r#type: PackageType, + name: String, +} + +#[derive(Deserialize, Serialize, Debug)] +struct Version { + version: String, +} + +#[derive(Deserialize, Serialize, Debug)] +struct Params { + version: String, + globs: Vec, + #[serde(default)] + fail_fast: bool, + #[serde(default)] + r#override: bool, +} + +#[derive(Deserialize, Serialize, Debug)] +struct Config { + /// Resource configuration. + /// Passed verbatim from the definition in the pipeline. + source: Source, + /// For 'check': + /// Previous version of this resource. + /// Will be empty for the very first request. + /// For 'in': + /// The version metadata to create this as. + version: Option, + params: Option, +} + +fn make_client(src: &Source) -> Result { + let mut headers = HeaderMap::new(); + headers.insert( + "Authorization", + format!("token {}", src.access_token).try_into()?, + ); + + Client::builder() + .default_headers(headers) + .user_agent(USER_AGENT) + .build() + .map_err(From::from) +} + +fn action_check(conf: Config) -> Result<()> { + let client = make_client(&conf.source)?; + let url = conf + .source + .url + .join(&format!("api/v1/packages/{}", conf.source.owner)) + .wrap_err("Invalid URL")?; + + let mut pkgs: Vec = client + .get(url) + .query(&[ + ("type", conf.source.r#type.to_string()), + ("q", conf.source.name), + ]) + .send()? + .json()?; + + if pkgs.is_empty() { + return io::stdout().write_all(b"[]").map_err(From::from); + } + + pkgs.sort_unstable_by_key(|pkg| pkg.created_at); + + let table: Vec<_> = pkgs + .iter() + .map(|pkg| { + vec![ + pkg.id.cell().justify(Justify::Center), + pkg.name.clone().cell(), + pkg.owner.login.clone().cell(), + pkg.version.clone().cell(), + pkg.created_at + .format(&Iso8601::DEFAULT) + .unwrap_or_default() + .cell(), + ] + }) + .collect(); + + let table = table + .table() + .title(vec![ + "#".cell().bold(true), + "Name".cell().bold(true), + "Owner".cell().bold(true), + "Version".cell().bold(true), + "Created At".cell().bold(true), + ]) + .bold(true); + + let _ = cli_table::print_stderr(table); + + let newest = pkgs + .last() + .expect("List of packages should not be empty.") + .version + .clone(); + + let out = if let Some(prev) = conf.version { + if prev.version == newest { + vec![prev] + } else { + vec![prev, Version { version: newest }] + } + } else { + vec![Version { version: newest }] + }; + + serde_json::to_writer_pretty(io::stdout(), &out) + .wrap_err("Failed to write result to stdout")?; + + Ok(()) +} + +fn action_out(conf: Config, dir: impl AsRef) -> Result<()> { + let dir = dir + .as_ref() + .canonicalize() + .wrap_err_with(|| format!("Invalid file path '{}'", dir.as_ref().display()))?; + + let Some(params) = conf.params else { + eyre::bail!("Missing params"); + }; + + if params.globs.is_empty() { + eyre::bail!("`params.globs` must not be empty"); + } + + let client = make_client(&conf.source)?; + let url = conf + .source + .url + .join(&format!( + // The trailing slash is required, to make sure this entire URL is used + // when `join`ing the file name later. Otherwise, the last component + // would be considered a "file" part itself, and replaced by a future `join`. + "api/packages/{}/{}/{}/{}/", + conf.source.owner, conf.source.r#type, conf.source.name, params.version + )) + .wrap_err("Invalid URL")?; + + let walker = GlobWalkerBuilder::from_patterns(dir, ¶ms.globs) + .max_depth(3) + .file_type(globwalk::FileType::FILE) + .build() + .wrap_err("Failed to create glob walker")?; + + let handle_glob = |entry| { + let entry: DirEntry = entry?; + + let name = entry.file_name(); + let path = entry.path(); + let url = url.join(&name.to_string_lossy()).wrap_err("Invalid url")?; + + if params.r#override { + client + .delete(url.clone()) + .send() + .wrap_err_with(|| format!("Failed request 'DELETE {}'", &url))?; + } + + let data = fs::read(path) + .wrap_err_with(|| format!("Failed to read package file '{}'", path.display()))?; + + let res = client + .put(url.clone()) + .body(data) + .send() + .wrap_err_with(|| format!("Failed request 'PUT {}'", &url))?; + + match res.status() { + StatusCode::CREATED => { + eprintln!( + "Uploaded file '{}', version={}, package={}", + name.to_string_lossy(), + params.version, + conf.source.name + ); + } + StatusCode::BAD_REQUEST => { + eyre::bail!( + "Package, version or file name are invalid. package={}, version={}, file={}", + conf.source.name, + params.version, + name.to_string_lossy(), + ); + } + StatusCode::CONFLICT => { + eyre::bail!( + "File '{}' already exists. version={}, package={}", + name.to_string_lossy(), + params.version, + conf.source.name + ); + } + StatusCode::INTERNAL_SERVER_ERROR => { + eyre::bail!( + "Internal server error: {} {}", + res.status(), + res.text().unwrap_or_default() + ); + } + code => { + eyre::bail!("Unexpected status code {}\ntext = {:?}", code, res.text()); + } + } + + Ok::<_, Report>(()) + }; + + let mut has_entry = false; + + let mut errors = Vec::new(); + for entry in walker { + has_entry = true; + if let Err(err) = handle_glob(entry) { + errors.push(err); + if params.fail_fast { + break; + } + } + } + + if !errors.is_empty() { + let mut err = eyre::eyre!("Failed to upload package with {} errors", errors.len()); + + for e in errors { + err = err.report(e); + } + + return Err(err); + } + + if !has_entry { + eyre::bail!("Globs didn't produce any files"); + } + + let out = json!({ + "version": { + "version": params.version + } + }); + + serde_json::to_writer_pretty(io::stdout(), &out) + .wrap_err("Failed to write result to stdout")?; + + Ok(()) +} + +pub(crate) fn run(action: &Action) -> Result<()> { + let config: Config = { + let mut buf = String::new(); + io::stdin() + .read_to_string(&mut buf) + .wrap_err("Failed to read from stdin")?; + + if buf.is_empty() { + eyre::bail!("No data received on stdin"); + } + + serde_json::from_str(&buf).wrap_err("Failed to parse stdin")? + }; + + match action { + Action::Check => action_check(config), + Action::In { dest: _ } => Ok(()), + Action::Out { src } => action_out(config, src), + } +} diff --git a/images/gitea/src/cmd/pr.rs b/images/gitea/src/cmd/pr.rs index 2e5577f..eafbcff 100644 --- a/images/gitea/src/cmd/pr.rs +++ b/images/gitea/src/cmd/pr.rs @@ -14,9 +14,7 @@ use time::OffsetDateTime; use url::Url; use crate::types::PullRequest; -use crate::Action; - -static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); +use crate::{Action, USER_AGENT}; #[derive(Deserialize, Serialize, Debug)] struct Source { @@ -182,6 +180,6 @@ pub(crate) fn run(action: &Action) -> Result<()> { match action { Action::Check => action_check(config), Action::In { dest } => action_in(config, dest), - Action::Out => Ok(()), + Action::Out { src: _ } => Ok(()), } } diff --git a/images/gitea/src/main.rs b/images/gitea/src/main.rs index 1f71387..4e6e13f 100644 --- a/images/gitea/src/main.rs +++ b/images/gitea/src/main.rs @@ -3,6 +3,8 @@ use std::path::PathBuf; use clap::{Parser, Subcommand}; use color_eyre::Result; +static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); + #[derive(Debug, Parser)] #[command(author, version, about, long_about = None)] #[command(propagate_version = true)] @@ -17,25 +19,31 @@ enum Commands { #[command(subcommand)] action: Action, }, + Package { + #[command(subcommand)] + action: Action, + }, } #[derive(Clone, Debug, Subcommand)] pub(crate) enum Action { Check, In { dest: PathBuf }, - Out, + Out { src: PathBuf }, } mod types; mod cmd { + pub mod package; pub mod pr; } -// #[tracing::instrument] fn main() -> Result<()> { + color_eyre::install()?; let cli = Cli::parse(); match &cli.command { Commands::Pr { action } => cmd::pr::run(action), + Commands::Package { action } => cmd::package::run(action), } } diff --git a/images/gitea/src/types.rs b/images/gitea/src/types.rs index 17f450e..23d7b6a 100644 --- a/images/gitea/src/types.rs +++ b/images/gitea/src/types.rs @@ -1,4 +1,5 @@ -use serde::Deserialize; +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; #[derive(Clone, Debug, Deserialize)] pub struct Ref { @@ -18,3 +19,28 @@ pub struct PullRequest { pub base: Ref, pub head: Ref, } + +#[derive(Copy, Clone, Deserialize, Serialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum PackageType { + Generic, +} + +impl std::fmt::Display for PackageType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PackageType::Generic => write!(f, "generic"), + } + } +} + +#[derive(Clone, Debug, Deserialize)] +pub struct Package { + #[serde(with = "time::serde::iso8601")] + pub created_at: OffsetDateTime, + pub id: u64, + pub name: String, + pub owner: User, + pub r#type: PackageType, + pub version: String, +} diff --git a/images/gitea/test.sh b/images/gitea/test.sh new file mode 100755 index 0000000..1dbfc6a --- /dev/null +++ b/images/gitea/test.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +set -e + +cargo build + +run() { +./target/debug/gitea package "$1" < Date: Thu, 23 Nov 2023 11:39:12 +0100 Subject: [PATCH 4/4] gitea: Implement commit statuses For now this is just a simple implementation only supporting `put` steps. `in` is a noop, so `no_get: true` is recommended. --- images/gitea/shims/status/check | 2 + images/gitea/shims/status/in | 2 + images/gitea/shims/status/out | 2 + images/gitea/src/cmd/package.rs | 23 +---- images/gitea/src/cmd/pr.rs | 22 +---- images/gitea/src/cmd/status.rs | 154 ++++++++++++++++++++++++++++++++ images/gitea/src/main.rs | 7 ++ images/gitea/src/util.rs | 19 ++++ 8 files changed, 194 insertions(+), 37 deletions(-) create mode 100755 images/gitea/shims/status/check create mode 100755 images/gitea/shims/status/in create mode 100755 images/gitea/shims/status/out create mode 100644 images/gitea/src/cmd/status.rs create mode 100644 images/gitea/src/util.rs diff --git a/images/gitea/shims/status/check b/images/gitea/shims/status/check new file mode 100755 index 0000000..05c370e --- /dev/null +++ b/images/gitea/shims/status/check @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea status check "$@" diff --git a/images/gitea/shims/status/in b/images/gitea/shims/status/in new file mode 100755 index 0000000..c652bb8 --- /dev/null +++ b/images/gitea/shims/status/in @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea status in "$@" diff --git a/images/gitea/shims/status/out b/images/gitea/shims/status/out new file mode 100755 index 0000000..af0e7e5 --- /dev/null +++ b/images/gitea/shims/status/out @@ -0,0 +1,2 @@ +#!/bin/sh +/bin/gitea status out "$@" diff --git a/images/gitea/src/cmd/package.rs b/images/gitea/src/cmd/package.rs index ec43d59..d82d765 100644 --- a/images/gitea/src/cmd/package.rs +++ b/images/gitea/src/cmd/package.rs @@ -7,8 +7,6 @@ use cli_table::{Cell, Style, Table}; use color_eyre::eyre::{self, Context}; use color_eyre::{Help, Report, Result}; use globwalk::{DirEntry, GlobWalkerBuilder}; -use reqwest::blocking::Client; -use reqwest::header::HeaderMap; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -16,7 +14,8 @@ use time::format_description::well_known::Iso8601; use url::Url; use crate::types::{Package, PackageType}; -use crate::{Action, USER_AGENT}; +use crate::util::make_client; +use crate::Action; #[derive(Deserialize, Serialize, Debug)] struct Source { @@ -56,22 +55,8 @@ struct Config { params: Option, } -fn make_client(src: &Source) -> Result { - let mut headers = HeaderMap::new(); - headers.insert( - "Authorization", - format!("token {}", src.access_token).try_into()?, - ); - - Client::builder() - .default_headers(headers) - .user_agent(USER_AGENT) - .build() - .map_err(From::from) -} - fn action_check(conf: Config) -> Result<()> { - let client = make_client(&conf.source)?; + let client = make_client(&conf.source.access_token)?; let url = conf .source .url @@ -158,7 +143,7 @@ fn action_out(conf: Config, dir: impl AsRef) -> Result<()> { eyre::bail!("`params.globs` must not be empty"); } - let client = make_client(&conf.source)?; + let client = make_client(&conf.source.access_token)?; let url = conf .source .url diff --git a/images/gitea/src/cmd/pr.rs b/images/gitea/src/cmd/pr.rs index eafbcff..a20f39a 100644 --- a/images/gitea/src/cmd/pr.rs +++ b/images/gitea/src/cmd/pr.rs @@ -6,15 +6,15 @@ use cli_table::format::Justify; use cli_table::{print_stderr, Cell, Style, Table}; use color_eyre::eyre::{self, Context}; use color_eyre::Result; -use reqwest::blocking::{Client, Response}; -use reqwest::header::HeaderMap; +use reqwest::blocking::Response; use serde::{Deserialize, Serialize}; use serde_json::json; use time::OffsetDateTime; use url::Url; use crate::types::PullRequest; -use crate::{Action, USER_AGENT}; +use crate::util::make_client; +use crate::Action; #[derive(Deserialize, Serialize, Debug)] struct Source { @@ -59,22 +59,8 @@ struct Config { version: Option, } -fn make_client(src: &Source) -> Result { - let mut headers = HeaderMap::new(); - headers.insert( - "Authorization", - format!("token {}", src.access_token).try_into()?, - ); - - Client::builder() - .default_headers(headers) - .user_agent(USER_AGENT) - .build() - .map_err(From::from) -} - fn fetch(src: &Source) -> Result { - let client = make_client(&src).wrap_err("Failed to create HTTP client")?; + let client = make_client(&src.access_token).wrap_err("Failed to create HTTP client")?; let url = src .url .join(&format!("api/v1/repos/{}/{}/pulls", src.owner, src.repo)) diff --git a/images/gitea/src/cmd/status.rs b/images/gitea/src/cmd/status.rs new file mode 100644 index 0000000..5533bae --- /dev/null +++ b/images/gitea/src/cmd/status.rs @@ -0,0 +1,154 @@ +use color_eyre::eyre; +use color_eyre::eyre::WrapErr; +use color_eyre::Help; +use color_eyre::Result; +use color_eyre::SectionExt; +use reqwest::StatusCode; +use serde::Deserialize; +use serde::Serialize; +use serde_json::json; +use std::io; +use std::io::Read; +use std::path::Path; +use url::Url; + +use crate::util::make_client; +use crate::Action; + +#[derive(Deserialize, Serialize, Debug)] +struct Source { + access_token: String, + owner: String, + url: Url, + repo: String, + sha: String, + context: String, + description: Option, + target_url: Option, +} + +#[derive(Deserialize, Serialize, Debug, Copy, Clone)] +#[serde(rename_all = "snake_case")] +enum State { + Pending, + Success, + Error, + Failure, + Warning, +} + +impl std::fmt::Display for State { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + State::Pending => write!(f, "pending"), + State::Success => write!(f, "success"), + State::Error => write!(f, "error"), + State::Failure => write!(f, "failure"), + State::Warning => write!(f, "warning"), + } + } +} + +#[derive(Deserialize, Serialize, Debug)] +struct Params { + state: State, + description: Option, +} + +#[derive(Deserialize, Serialize, Debug)] +struct Config { + /// Resource configuration. + /// Passed verbatim from the definition in the pipeline. + source: Source, + params: Params, +} + +fn action_out(conf: Config, _dir: impl AsRef) -> Result<()> { + let params = conf.params; + let description = params.description.or(conf.source.description); + + let client = make_client(&conf.source.access_token)?; + let url = conf + .source + .url + .join(&format!( + // The trailing slash is required, to make sure this entire URL is used + // when `join`ing the file name later. Otherwise, the last component + // would be considered a "file" part itself, and replaced by a future `join`. + "api/v1/repos/{}/{}/statuses/{}", + conf.source.owner, conf.source.repo, conf.source.sha + )) + .wrap_err("Invalid URL")?; + + let body = json!({ + "context": conf.source.context, + "description": description, + "state": params.state, + "target_url": conf.source.target_url, + }); + + let res = client + .post(url.clone()) + .json(&body) + .send() + .wrap_err_with(|| format!("Failed to send request 'POST {}'", url))?; + + match res.status() { + StatusCode::CREATED => { + eprintln!( + "Created status '{}' on commit '{}'", + params.state, conf.source.sha + ); + } + StatusCode::BAD_REQUEST => { + eyre::bail!( + "Invalid request: {:?}. state={}, context={}, description={:?}, target_url={:?}", + res.text(), + params.state, + conf.source.context, + description, + conf.source.target_url + ) + } + code => { + eyre::bail!("Unexpected status code {}\ntext = {:?}", code, res.text()); + } + } + + println!("{{ \"version\": {{}} }}"); + Ok(()) +} + +pub(crate) fn run(action: &Action) -> Result<()> { + // TODO: Gitea does actually support fetching statuses, making `check` and `in` viable, + // theoretically. But it also doesn't make much sense to implement them. + match action { + Action::Check => { + // Dummy implemented that always reports nothing. + println!("[]"); + Ok(()) + } + Action::In { dest: _ } => { + println!("{{}}"); + Ok(()) + } + Action::Out { src } => { + let config: Config = { + let mut buf = String::new(); + io::stdin() + .read_to_string(&mut buf) + .wrap_err("Failed to read from stdin")?; + + if buf.is_empty() { + eyre::bail!("No data received on stdin"); + } + + serde_json::from_str(&buf) + .wrap_err("Failed to parse stdin") + .with_section(|| buf.header("JSON"))? + }; + + action_out(config, src) + } + } +} diff --git a/images/gitea/src/main.rs b/images/gitea/src/main.rs index 4e6e13f..23a608d 100644 --- a/images/gitea/src/main.rs +++ b/images/gitea/src/main.rs @@ -23,6 +23,10 @@ enum Commands { #[command(subcommand)] action: Action, }, + Status { + #[command(subcommand)] + action: Action, + }, } #[derive(Clone, Debug, Subcommand)] @@ -33,9 +37,11 @@ pub(crate) enum Action { } mod types; +mod util; mod cmd { pub mod package; pub mod pr; + pub mod status; } fn main() -> Result<()> { @@ -45,5 +51,6 @@ fn main() -> Result<()> { match &cli.command { Commands::Pr { action } => cmd::pr::run(action), Commands::Package { action } => cmd::package::run(action), + Commands::Status { action } => cmd::status::run(action), } } diff --git a/images/gitea/src/util.rs b/images/gitea/src/util.rs new file mode 100644 index 0000000..825c978 --- /dev/null +++ b/images/gitea/src/util.rs @@ -0,0 +1,19 @@ +use color_eyre::Result; +use reqwest::blocking::Client; +use reqwest::header::HeaderMap; + +use crate::USER_AGENT; + +pub(crate) fn make_client(access_token: impl AsRef) -> Result { + let mut headers = HeaderMap::new(); + headers.insert( + "Authorization", + format!("token {}", access_token.as_ref()).try_into()?, + ); + + Client::builder() + .default_headers(headers) + .user_agent(USER_AGENT) + .build() + .map_err(From::from) +}