diff --git a/.gitlab-ci-local-variables.yml b/.gitlab-ci-local-variables.yml new file mode 100644 index 0000000000000000000000000000000000000000..ccf211b131fd4289066c4363a3f599677a23082e --- /dev/null +++ b/.gitlab-ci-local-variables.yml @@ -0,0 +1,4 @@ +--- + +DEBUG: 'true' +TEST_OPTIONS: '--help' \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 122cb08d7b6f282b4d625fd6038d80570c8c4349..154b4be14fe63500de284f1af70f94bfe0d57a83 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,18 +2,15 @@ variables: RUST_VERSION: "1.76" # slim or alpine not adapted because of openSSL dependency TARGET_ARCH: default CARGO_HOME: .cargo + TEST_OPTIONS: --url $CI_PROJECT_URL -a + CLEAN_OPTIONS: --url $CI_PROJECT_URL -b default: cache: - key: rust-$TARGET_ARCH + key: rust-$CI_JOB_NAME paths: - .cargo - - target/debug/deps - - target/debug/build - - target/release/deps - - target/release/build - - target/$TARGET_ARCH/release/deps - - target/$TARGET_ARCH/release/build + - target policy: pull-push stages: @@ -22,8 +19,12 @@ stages: - deploy include: - - remote: 'https://api.r2devops.io/job/r/gitlab/r2devops/hub/docker_build@latest.yaml' - - remote: 'https://api.r2devops.io/job/r/gitlab/r2devops/hub/gitleaks@latest.yaml' + - remote: 'https://gitlab.com/r2devops/hub/-/raw/docker_build@2.0.2/jobs/docker_build/docker_build.yml' + - remote: 'https://gitlab.com/r2devops/hub/-/raw/gitleaks@1.2.2/jobs/gitleaks/gitleaks.yml' + +gitleaks: + stage: build_test + cache: [ ] check-format: stage: build_test @@ -34,15 +35,17 @@ check-format: - cargo fmt --all -- --check - cargo clippy -- -D warnings allow_failure: true - -gitleaks: - stage: build_test + rules: + - if: $CI_COMMIT_REF_NAME == 'main' + - if: $CI_PIPELINE_SOURCE == "merge_request_event" test-rust-current: stage: build_test image: rust:$RUST_VERSION script: - cargo test --verbose + - cargo run -- $TEST_OPTIONS + allow_failure: true rules: - if: $CI_COMMIT_REF_NAME == 'main' - if: $CI_PIPELINE_SOURCE == "merge_request_event" @@ -51,6 +54,11 @@ test-rust-nightly: extends: test-rust-current image: rustlang/rust:nightly +test-clean-rust-current: + extends: test-rust-current + variables: + TEST_OPTIONS: $CLEAN_OPTIONS + .rust-release: stage: release variables: @@ -59,11 +67,12 @@ test-rust-nightly: script: - rustup target add $TARGET_ARCH - cargo build $CARGO_OPTS --target $TARGET_ARCH --release - - if [ -z "$NO_POSTPROCESS" ]; then strip $TARGET; $LDD_CMD $TARGET; $TARGET --help; fi + - if [ -z "$NO_POSTPROCESS" ]; then strip $TARGET; $LDD_CMD $TARGET; $TARGET $TEST_OPTIONS; fi - 'if [ -z "$DEBUG" ]; then curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file $TARGET "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/$TARGET_ARCH/${CI_COMMIT_TAG:-latest}/$APP_NAME"; fi' artifacts: paths: - $TARGET + allow_failure: true rules: - if: $CI_COMMIT_REF_NAME == 'main' - if: $CI_COMMIT_TAG @@ -115,7 +124,7 @@ docker_build: retry: 2 needs: - release-linux - cache: [] + cache: [ ] rules: - if: $CI_COMMIT_REF_NAME == 'main' @@ -128,6 +137,6 @@ docker_build-prod: retry: 2 needs: - release-linux - cache: [] + cache: [ ] rules: - if: $CI_COMMIT_TAG \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2362667252c6c16fbacfb184456ee613af573287..28a7a166a2ec2f3bb8e38aba023aaaf07d5e3997 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -52,9 +52,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" [[package]] name = "ascii" @@ -64,13 +64,13 @@ checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -79,7 +79,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] @@ -92,9 +92,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "95d8e92cac0961e91dbd517496b00f7e9b92363dbe6d42c3198268323798860c" dependencies = [ "addr2line", "cc", @@ -125,9 +125,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block" @@ -146,9 +146,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "byteorder" @@ -164,10 +164,11 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.88" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ + "jobserver", "libc", ] @@ -179,9 +180,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", @@ -189,7 +190,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.3", + "windows-targets 0.52.4", ] [[package]] @@ -260,9 +261,9 @@ dependencies = [ [[package]] name = "cron" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff76b51e4c068c52bfd2866e1567bee7c567ae8f24ada09fd4307019e25eab7" +checksum = "6f8c3e73077b4b4a6ab1ea5047c37c57aee77657bc8ecd6f29b0af082d0b0c07" dependencies = [ "chrono", "nom", @@ -324,7 +325,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -346,7 +347,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core 0.20.8", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -401,7 +402,7 @@ dependencies = [ "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -421,7 +422,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core 0.20.0", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -455,7 +456,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -661,11 +662,11 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git2" -version = "0.18.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" +checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "libgit2-sys", "log", @@ -676,9 +677,9 @@ dependencies = [ [[package]] name = "gitlab" -version = "0.1609.0" +version = "0.1609.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5640bb3c6ee4d4e53188329d2d424ea6d546b188b92e1cfe3785fcda3801b4c4" +checksum = "6a6a894189e53db36e7bbbab410edfca301ee6414e4b83bdcd2a9a8e42190194" dependencies = [ "async-trait", "base64 0.13.1", @@ -786,9 +787,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -833,17 +834,11 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" - [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -927,7 +922,7 @@ dependencies = [ "serde", "serde_derive", "thiserror", - "toml 0.8.10", + "toml 0.8.12", "unic-langid", ] @@ -970,7 +965,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.51", + "syn 2.0.53", "unic-langid", ] @@ -984,7 +979,7 @@ dependencies = [ "i18n-config", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -1028,9 +1023,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.3" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown", @@ -1098,11 +1093,20 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "jobserver" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1149,9 +1153,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" +checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" dependencies = [ "cc", "libc", @@ -1190,9 +1194,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "malloc_buf" @@ -1232,9 +1236,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1260,16 +1264,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.8", - "libc", -] - [[package]] name = "number_prefix" version = "0.4.0" @@ -1326,7 +1320,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -1343,7 +1337,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -1453,9 +1447,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -1492,9 +1486,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1509,9 +1503,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.24" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", @@ -1565,9 +1559,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.2.0" +version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f" +checksum = "fb78f46d0066053d16d4ca7b898e9343bc3530f71c61d5ad84cd404ada068745" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -1576,22 +1570,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.2.0" +version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16" +checksum = "b91ac2a3c6c0520a3fb3dd89321177c3c692937c4eb21893378219da10c44fc8" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.51", + "syn 2.0.53", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.2.0" +version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" +checksum = "86f69089032567ffff4eada41c573fc43ff466c7db7c5688b2e7969584345581" dependencies = [ "sha2", "walkdir", @@ -1611,11 +1605,11 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -1716,7 +1710,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -1779,9 +1773,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -1848,9 +1842,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.51" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -1886,9 +1880,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", @@ -1907,22 +1901,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", ] [[package]] @@ -1959,7 +1953,6 @@ dependencies = [ "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2", "windows-sys 0.48.0", @@ -2000,9 +1993,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", @@ -2021,9 +2014,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ "indexmap", "serde", @@ -2182,9 +2175,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2207,9 +2200,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2217,24 +2210,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -2244,9 +2237,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2254,28 +2247,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.51", + "syn 2.0.53", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2324,7 +2317,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.3", + "windows-targets 0.52.4", ] [[package]] @@ -2342,7 +2335,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.3", + "windows-targets 0.52.4", ] [[package]] @@ -2362,17 +2355,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.3", - "windows_aarch64_msvc 0.52.3", - "windows_i686_gnu 0.52.3", - "windows_i686_msvc 0.52.3", - "windows_x86_64_gnu 0.52.3", - "windows_x86_64_gnullvm 0.52.3", - "windows_x86_64_msvc 0.52.3", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -2383,9 +2376,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -2395,9 +2388,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -2407,9 +2400,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -2419,9 +2412,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -2431,9 +2424,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -2443,9 +2436,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -2455,15 +2448,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.3" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.6.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4191c47f15cc3ec71fcb4913cb83d58def65dd3787610213c649283b5ce178" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 48e1c8ef617c5783761d32a9e18050369adb3a78..9e244bbd84515c1be10cc844bf92231203014d71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,8 @@ chrono = "0.4.34" console = "0.15.2" derive_builder = "0.20.0" dialoguer = "0.11.0" -git2 = { version="0.18.1", features = ["vendored-libgit2"] } -gitlab = "0.1609.0" +git2 = { version = "0.18.1", features = ["vendored-libgit2"] } +gitlab = "0.1609.2" # Erreurs au passage de la version 0.13.0 graphql_client = "~0.11.0" human_bytes = "0.4.3" @@ -27,4 +27,3 @@ rust-embed = "8.0.0" serde = "1.0.190" serde_json = "1.0.107" structopt = "0.3.26" - diff --git a/i18n/en-GB/gitlab_project_doctor.ftl b/i18n/en-GB/gitlab_project_doctor.ftl index bac24ce8c4f8a666935bf215ac272821967c2752..d9c58250cef68adc4ae32da3683b44c4286a7986 100644 --- a/i18n/en-GB/gitlab_project_doctor.ftl +++ b/i18n/en-GB/gitlab_project_doctor.ftl @@ -1,42 +1,48 @@ +ask-age-days = From which age in days ? +ask-delete-files = Delete obsolete files ? +ask-delete-pipelines = Delete old pipelines ? +conf-analysing = Analysis of package configuration +conf-fix = Fix this : {$url} connecting-to-gitlab = Connecting to Gitlab -gitlab-repo = Gitlab repository : {$repo} -error-gl-token = GL_TOKEN environment variable must contain a valid Gitlab private token -error-not-gitlab-repo = This URL is not a gitlab repository -error-not-git-repo = This dir is not a Git repository +container-analysing = Analysis of container registry +container-policy-disabled = The option "Clean up image tags" is disabled. +container-policy-enabled = The option "Clean up image tags" is enabled +container-report = {$image_count} images in container registry. {$old_image_count} are older than {$nb_days} days +container-summary = Container registry size: {$registry_size} +duplicate-assets-option-error = Cannot get the number of duplicate assets to keep option +duplicate-assets-option-onepackage = The number of duplicate assets to keep is 1 +duplicate-assets-option-warn = The number of duplicate assets to keep is NOT 1 +error = Error: +error-gl-token = No token found. Please set the GL_TOKEN variable or the command -t argument with a valid private token or run the program in a Gilab CI job +error-insufficient-privileges = Your token has insufficient privileges error-no-gitlab-remote = This dir does not contain a gitlab remote -size-storage = Storage size: -size-git-repo = Git repository size: -size-artifacts = Artifact jobs size: -size-packages = Package registry size: +error-not-git-repo = This dir is not a Git repository +error-not-gitlab-repo = This URL is not a gitlab repository +gitlab-repo = Gitlab repository : {$repo} +help-analysis = Analysis mode : Output a detailed analysis in JSON format. No cleaning. +help-batch = Batch mode : No questions, no progress bar, ideal for CI environment +help-days = Number of days from which an element is considered "old", 30 by default +help-git-path = Analyze the project from a local path of a Git repository. Ignored if url option is specified +help-token = (Not recommended) Gitlab private token for authentication, maintainer role is needed for objects deletion. It is strongly advised to use the environment variable GL_TOKEN instead of this argument, for security reasons. +help-url = Analyze the project from the URL of Gitlab repository +no-cicd = No CI/CD configured for this project. +no-permission-jobanalysis = The token has no permission for job analysis. package-analysing = Analysis of packages -no-cicd = No CI/CD configured for this project -error = Error: -package-report = {$nb_packages} packages. {$nb_files} files are obsolete ({$size}) +package-clean-report = Deleted {$nb_packages} packages, {$size} saved. package-deleting = Deleting obsolete packages files package-no-deletion = No package has been deleted -error-insufficient-privileges = Your token has insufficient privileges -package-clean-report = Deleted {$nb_packages} packages, {$size} saved. +package-report = {$nb_packages} packages. {$nb_files} files are obsolete ({$size}) pipeline-analysing = Analysis of pipelines -pipeline-report = {$total_pipelines} pipelines. {$old_pipelines} pipelines are older than {$nb_days} days +pipeline-clean-report = Deleted {$nb_pipelines} pipelines. +pipeline-clean-report-size = Deleted {$nb_pipelines} pipelines, {$size} saved. pipeline-deleting = Deleting old pipelines -pipeline-clean-report = Deleted {$nb_pipelines} pipelines, {$size} saved. pipeline-last-notdeleted = Latest pipeline is not deleted. pipeline-no-deletion = No pipeline has been deleted -ask-delete-pipelines = Delete old pipelines ? -ask-delete-files = Delete obsolete files ? -ask-age-days = From which age in days ? -help-url = Analyze the project from the URL of Gitlab repository -help-git-path = Analyze the project from a local path of a Git repository. Ignored if url option is specified -help-batch = Batch mode : No questions, no progress bar, ideal for CI environment -help-days = Number of days from which an element is considered "old", 30 by default -help-analysis = Analysis mode : Output a detailed analysis in JSON format. No cleaning. -container-policy-enabled = The option "Clean up image tags" is enabled -container-policy-disabled = The option "Clean up image tags" is disabled. -conf-analysing = Analysis of package configuration -duplicate-assets-option-onepackage = The number of duplicate assets to keep is 1 -duplicate-assets-option-warn = The number of duplicate assets to keep is NOT 1 -duplicate-assets-option-error = Cannot get the number of duplicate assets to keep option -conf-fix = Fix this : {$url} -container-analysing = Analysis of container registry -container-report = {$image_count} images in container registry. {$old_image_count} are older than {$nb_days} days -container-summary = Container registry size: {$registry_size} \ No newline at end of file +pipeline-report = {$total_pipelines} pipelines. {$old_pipelines} pipelines are older than {$nb_days} days +size-artifacts = Artifact jobs size: +size-git-repo = Git repository size: +size-packages = Package registry size: +size-storage = Storage size: +token-argument = Using the private token from the command argument +token-environment = Using the private token provided in GL_TOKEN variable +token-job = Using the job token from CI_JOB_TOKEN. Warning ! This token provides less permissions than private token ! diff --git a/i18n/fr-FR/gitlab_project_doctor.ftl b/i18n/fr-FR/gitlab_project_doctor.ftl index 98d4720f5057f4e26de43914d4c1499661559ae3..43999a624d6d02dfd432d9f40b129839e92b9626 100644 --- a/i18n/fr-FR/gitlab_project_doctor.ftl +++ b/i18n/fr-FR/gitlab_project_doctor.ftl @@ -1,42 +1,49 @@ +ask-age-days = Datant de plus de combien de jours ? +ask-delete-files = Supprimer fichiers obsolètes ? +ask-delete-pipelines = Supprimer anciens pipelines ? +conf-analysing = Analyse de la configuration des packages +conf-fix = Pour corriger : {$url} connecting-to-gitlab = Connexion à Gitlab -gitlab-repo = Dépôt Gitlab : {$repo} -error-gl-token = GL_TOKEN environment variable must contain a valid Gitlab private tokenerror-not-gitlab-repo = "This URL is not a gitlab repository" -error-not-git-repo = "Ce dossier n'est pas un dépôt Git" +container-analysing = Analyse du container registry +container-policy-disabled = L'option "Clean up image tags" est désactivée. +container-policy-enabled = L'option "Clean up image tags" est activée +container-report = {$image_count} images dans le container registry. {$old_image_count} datent de plus de {$nb_days} jours +container-summary = Taille du container registry : {$registry_size} +duplicate-assets-option-error = Cannot get the number of duplicate assets to keep option +duplicate-assets-option-onepackage = L'option "The number of duplicate assets to keep" vaut 1 +duplicate-assets-option-warn = L'option "The number of duplicate assets to keep" ne vaut PAS 1 +error = Erreur : +error-gl-token = Aucun token trouvé. Veuillez renseigner la variable GL_TOKEN contenant un token privée valide ou bien exécutez le programme dans un job Gilab CI. +error-insufficient-privileges = Le token utilisé n'a pas les permissions requises error-no-gitlab-remote = Ce dépôt Git n'est pas lié à un dépôt Gitlab -size-storage = Taille globale : -size-git-repo = Taille du dépôt Git : -size-artifacts = Taille des artefacts de jobs : -size-packages = Taille du package registry : -size-packages = Package registry size: +error-not-git-repo = "Ce dossier n'est pas un dépôt Git" +error-not-gitlab-repo = "This URL is not a gitlab repository" +gitlab-repo = Dépôt Gitlab : {$repo} +help-analysis = Mode analyse : Analyse détaillé au format JSON. Pas de nettoyage +help-batch = Mode batch : pas de questions, pas de barre de progression, idéal pour du CI +help-days = Nombre de jours d'ancienneté à partir duquel un élément est considéré "ancien" +help-git-path = Analyse du projet à partir d'un chemin vers un dépôt Git. Ignoré si l'option url est spécifiée +help-token = (Non recommandé) Token privé Gitlab d'authentification, avec le rôle maintainer nécessaire pour la suppression. Il est conseillé d'utiliser la variable GL_TOKEN à la place de cet argument, pour des raisons de sécurité. +help-url = Analyse du projet à partir d'une URL Gitlab +no-cicd = Aucun CI/CD configuré pour ce projet. +no-permission-jobanalysis = Le token n'a pas la permission d'analyser les jobs. package-analysing = Analyse du package registry -no-cicd = Aucun CI/CD configuré pour ce projet -error = Erreur : -package-report = {$nb_packages} packages. {$nb_files} fichiers sont obsolètes ({$size}) +package-clean-report = {$nb_packages} packages supprimés, {$size} récupérés. package-deleting = Suppression des fichiers de package obsolètes package-no-deletion = Aucun package n'a été supprimé -error-insufficient-privileges = Le token utilisé n'a pas les permissions requises -package-clean-report = {$nb_packages} packages supprimés, {$size} récupérés. +package-report = {$nb_packages} packages. {$nb_files} fichiers sont obsolètes ({$size}) pipeline-analysing = Analyse des pipelines -pipeline-report = {$total_pipelines} pipelines. {$old_pipelines} pipelines datent de plus de {$nb_days} jours +pipeline-clean-report = {$nb_pipelines} pipelines supprimés. +pipeline-clean-report-size = {$nb_pipelines} pipelines supprimés, {$size} économisés. pipeline-deleting = Suppression des anciens pipelines -pipeline-clean-report = {$nb_pipelines} pipelines supprimés, {$size} économisés. pipeline-last-notdeleted = Le dernier pipeline n'est pas supprimé. pipeline-no-deletion = Aucun pipeline n'a été supprimé. -ask-delete-pipelines = Supprimer anciens pipelines ? -ask-delete-files = Supprimer fichiers obsolètes ? -ask-age-days = Datant de plus de combien de jours ? -help-url = Analyse du projet à partir d'une URL Gitlab -help-git-path = Analyse du projet à partir d'un chemin vers un dépôt Git. Ignoré si l'option url est spécifiée -help-batch = Mode batch : pas de questions, pas de barre de progression, idéal pour du CI -help-days = Nombre de jours d'ancienneté à partir duquel un élément est considéré "ancien" -help-analysis = Mode analyse : Analyse détaillé au format JSON. Pas de nettoyage -container-policy-enabled = L'option "Clean up image tags" est activée -container-policy-disabled = L'option "Clean up image tags" est désactivée. -conf-analysing = Analyse de la configuration des packages -duplicate-assets-option-onepackage = L'option "The number of duplicate assets to keep" vaut 1 -duplicate-assets-option-warn = L'option "The number of duplicate assets to keep" ne vaut PAS 1 -duplicate-assets-option-error = Cannot get the number of duplicate assets to keep option -conf-fix = Pour corriger : {$url} -container-analysing = Analyse du container registry -container-report = {$image_count} images dans le container registry. {$old_image_count} datent de plus de {$nb_days} jours -container-summary = Taille du container registry : {$registry_size} \ No newline at end of file +pipeline-report = {$total_pipelines} pipelines. {$old_pipelines} pipelines datent de plus de {$nb_days} jours +size-artifacts = Taille des artefacts de jobs : +size-git-repo = Taille du dépôt Git : +size-packages = Package registry size: +size-packages = Taille du package registry : +size-storage = Taille globale : +token-argument = Utilisation du token privé fourni en argument de commande +token-environment = Utilisation du token privé founi par la variable GL_TOKEN +token-job = Utilisation du token de job CI_JOB_TOKEN. Attention ! Ce token offre moins de permissions qu'un token privé diff --git a/src/cli.rs b/src/cli.rs index 8a68eccda18866e1b7cb2eb0fc5c0f8d72c1145f..24816f0f80a93c0e47b597608b019ee7954e8da6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,15 +1,16 @@ -use atty::Stream; use std::fmt::Write; use std::time::Duration; use std::{panic, process}; -use crate::{fl, ReportPending, ReportStatus, Reportable}; +use atty::Stream; use console::style; use dialoguer::{Confirm, Input}; use indicatif::{ProgressBar, ProgressStyle}; use lazy_static::lazy_static; use structopt::StructOpt; +use crate::{fl, ReportPending, ReportStatus, Reportable}; + pub fn fatal_if_none<T>(result: Option<T>, msg: &str) -> T { match result { Some(x) => x, @@ -23,21 +24,24 @@ lazy_static! { static ref HELP_URL: String = fl!("help-url"); static ref HELP_GIT_PATH: String = fl!("help-git-path"); static ref HELP_BATCH_MODE: String = fl!("help-batch"); + static ref HELP_TOKEN: String = fl!("help-token"); static ref HELP_DAYS: String = fl!("help-days"); static ref HELP_ANALYSIS: String = fl!("help-analysis"); } #[derive(StructOpt)] pub struct Args { - #[structopt(name = "url", long, help = &HELP_URL)] + #[structopt(name = "url", long, help = & HELP_URL)] pub url: Option<String>, - #[structopt(name = "git_path", required_unless = "url", help = &HELP_GIT_PATH)] + #[structopt(long = "token", short = "t", help = & HELP_TOKEN)] + pub token: Option<String>, + #[structopt(name = "git_path", required_unless = "url", help = & HELP_GIT_PATH)] pub git_path: Option<String>, - #[structopt(long = "batch", short = "b", help = &HELP_BATCH_MODE)] + #[structopt(long = "batch", short = "b", help = & HELP_BATCH_MODE)] pub batch_mode: bool, - #[structopt(long = "days", short = "d", default_value = "30", help = &HELP_DAYS)] + #[structopt(long = "days", short = "d", default_value = "30", help = & HELP_DAYS)] pub days: usize, - #[structopt(long = "analysis", short = "a", help = &HELP_ANALYSIS)] + #[structopt(long = "analysis", short = "a", help = & HELP_ANALYSIS)] pub analysis_mode: bool, } diff --git a/src/diagnosis/container_analysis.rs b/src/diagnosis/container_analysis.rs index ba95504bef3d1ba2c98eb951848fe68f37642071..a546619ac2f372219cd9947bf7dff2db547503aa 100644 --- a/src/diagnosis/container_analysis.rs +++ b/src/diagnosis/container_analysis.rs @@ -1,4 +1,4 @@ -use chrono::{DateTime, Duration, Local}; +use chrono::{DateTime, Local, TimeDelta}; use gitlab::api::{Pagination, Query}; use gitlab::Gitlab; use human_bytes::human_bytes; @@ -120,17 +120,13 @@ impl ReportJob for ContainerAnalysisJob { gitlab::api::paged(endpoint, Pagination::All).query(&self.gitlab); match query { Err(e) => self.into_report( - vec![ReportStatus::ERROR(format!( - "{} {}", - fl!("error"), - e.to_string() - ))], + vec![ReportStatus::ERROR(format!("{} {}", fl!("error"), e))], vec![], ), Ok(containers) => { let container_repos = self.get_detailed_repo(&containers); let days = self.days; - let ref_date = Local::now() - Duration::days(days as i64); + let ref_date = Local::now() - TimeDelta::try_days(days as i64).unwrap(); let image_count: usize = container_repos.iter().map(|cr| cr.tags.len()).sum(); let registry_size: u64 = container_repos diff --git a/src/diagnosis/gitlab_connection.rs b/src/diagnosis/gitlab_connection.rs index 06affbaec984977f61a5a25b5a54a5887e119620..3a436b30eff6639f6e363e50f038e70f468d8026 100644 --- a/src/diagnosis/gitlab_connection.rs +++ b/src/diagnosis/gitlab_connection.rs @@ -16,6 +16,14 @@ use crate::fl; type Result<T> = std::result::Result<T, Box<dyn error::Error>>; +// An enum of a Gitlab token type : private or job token +#[derive(Debug, Deserialize, Clone)] +pub enum GitlabToken { + PrivateTokenFromArg(String), + PrivateTokenFromEnv(String), + JobToken(String), +} + #[derive(Debug, Deserialize, Clone, Serialize)] pub struct Statistics { pub commit_count: u64, @@ -24,6 +32,7 @@ pub struct Statistics { pub job_artifacts_size: u64, pub packages_size: u64, } + #[derive(Debug, Deserialize, Clone)] pub struct ContainerExpirationPolicy { pub enabled: bool, @@ -33,7 +42,7 @@ pub struct ContainerExpirationPolicy { pub struct Project { pub id: u64, pub name: String, - pub statistics: Statistics, + pub statistics: Option<Statistics>, pub jobs_enabled: bool, pub container_registry_enabled: bool, pub container_expiration_policy: Option<ContainerExpirationPolicy>, @@ -46,6 +55,7 @@ pub struct GitlabRepository { pub gitlab: Gitlab, pub project: Project, pub repo: Option<Repository>, + pub token: GitlabToken, } pub struct ConnectionReport { @@ -54,8 +64,8 @@ pub struct ConnectionReport { } pub enum ConnectionJob { - FromUrl(String), - FromPath(String), + FromUrl(String, Option<String>), + FromPath(String, Option<String>), } impl ReportJob for ConnectionJob { @@ -67,8 +77,10 @@ impl ReportJob for ConnectionJob { job: { std::thread::spawn(|| { ConnectionJob::_to_report_status(match self { - ConnectionJob::FromUrl(url) => ConnectionJob::_from_url(&url), - ConnectionJob::FromPath(path) => ConnectionJob::_from_git_path(&path), + ConnectionJob::FromUrl(url, token) => ConnectionJob::_from_url(&url, token), + ConnectionJob::FromPath(path, token) => { + ConnectionJob::_from_git_path(&path, token) + } }) }) }, @@ -87,24 +99,45 @@ impl Reportable for ConnectionReport { impl ConnectionJob { fn _to_report_status(result: Result<GitlabRepository>) -> ConnectionReport { match result { - Ok(gitlab) => ConnectionReport { - report_status: vec![ - ReportStatus::OK(fl!("gitlab-repo", repo = gitlab.url.as_str())), - _report_global_storage(&gitlab.project), - _report_repo_storage(&gitlab.project), - _report_artifact_storage(&gitlab.project), - _report_package_storage(&gitlab.project), - ], - data: Some(gitlab), - }, + Ok(gitlab) => { + let token_status = match gitlab.token { + GitlabToken::PrivateTokenFromArg(_) => ReportStatus::OK(fl!("token-argument")), + GitlabToken::PrivateTokenFromEnv(_) => { + ReportStatus::OK(fl!("token-environment")) + } + GitlabToken::JobToken(_) => ReportStatus::WARNING(fl!("token-job")), + }; + let report_status = if let Some(stats) = &gitlab.project.statistics { + vec![ + token_status, + ReportStatus::OK(fl!("gitlab-repo", repo = gitlab.url.as_str())), + _report_global_storage(stats), + _report_repo_storage(stats), + _report_artifact_storage(stats), + _report_package_storage(stats), + ] + } else { + vec![ + token_status, + ReportStatus::OK(fl!("gitlab-repo", repo = gitlab.url.as_str())), + ] + }; + ConnectionReport { + report_status, + data: Some(gitlab), + } + } Err(e) => ConnectionReport { data: None, report_status: vec![ReportStatus::ERROR(format!("{}", e))], }, } } - fn _gitlab_project(server: &str, path: &str) -> Result<(Gitlab, Project)> { - let token = env::var("GL_TOKEN").map_err(|_| fl!("error-gl-token"))?; + fn _gitlab_project_private_token( + server: &str, + path: &str, + token: &str, + ) -> Result<(Gitlab, Project)> { let client = Gitlab::new(server, token)?; let endpoint = projects::Project::builder() .project(path) @@ -116,75 +149,108 @@ impl ConnectionJob { Ok((client, project)) } - fn _from_url(url: &str) -> Result<GitlabRepository> { + fn _gitlab_project_job_token(server: &str, token: &str) -> Result<(Gitlab, Project)> { + let client = Gitlab::new_job_token(server, token)?; + let project = Project { + id: env::var("CI_PROJECT_ID")?.parse()?, + name: env::var("CI_PROJECT_NAME")?, + statistics: None, + jobs_enabled: true, + container_expiration_policy: None, + container_registry_enabled: false, // TODO is there a way to find it out with job token? + web_url: env::var("CI_PROJECT_URL")?, + path_with_namespace: env::var("CI_PROJECT_PATH")?, + }; + Ok((client, project)) + } + fn _env_token(token: Option<String>) -> Result<GitlabToken> { + if let Some(token_value) = token { + Ok(GitlabToken::PrivateTokenFromArg(token_value)) + } else if let Ok(token_value) = env::var("GL_TOKEN") { + Ok(GitlabToken::PrivateTokenFromEnv(token_value)) + } else { + Ok(GitlabToken::JobToken( + env::var("CI_JOB_TOKEN").map_err(|_| fl!("error-gl-token"))?, + )) + } + } + + fn _gitlab_project(server: &str, path: &str, token: &GitlabToken) -> Result<(Gitlab, Project)> { + match token { + GitlabToken::PrivateTokenFromArg(token) | GitlabToken::PrivateTokenFromEnv(token) => { + Self::_gitlab_project_private_token(server, path, token) + } + GitlabToken::JobToken(token) => Self::_gitlab_project_job_token(server, token), + } + } + + fn _from_url(url: &str, token: Option<String>) -> Result<GitlabRepository> { let (server, path) = path_from_git_url(url).ok_or_else(|| fl!("error-not-gitlab-repo"))?; - let (gitlab, project) = ConnectionJob::_gitlab_project(server, path)?; + let used_token = Self::_env_token(token)?; + let (gitlab, project) = ConnectionJob::_gitlab_project(server, path, &used_token)?; Ok(GitlabRepository { url: String::from(path), gitlab, project, repo: None, + token: used_token, }) } - fn _from_git_path(path: &str) -> Result<GitlabRepository> { + fn _from_git_path(path: &str, token: Option<String>) -> Result<GitlabRepository> { let repo = Repository::open(path).map_err(|_| fl!("error-not-git-repo"))?; let (server, url_path) = gitlab_url(&repo).ok_or_else(|| fl!("error-no-gitlab-remote"))?; - let (gitlab, project) = ConnectionJob::_gitlab_project(&server, &url_path)?; + let used_token = Self::_env_token(token)?; + let (gitlab, project) = ConnectionJob::_gitlab_project(&server, &url_path, &used_token)?; Ok(GitlabRepository { url: url_path, gitlab, project, repo: Some(repo), + token: used_token, }) } } -fn _report_global_storage(project: &Project) -> ReportStatus { +fn _report_global_storage(stats: &Statistics) -> ReportStatus { let msg = format!( "{} {}", fl!("size-storage"), - human_bytes(project.statistics.storage_size as f64) + human_bytes(stats.storage_size as f64) ); - warning_if(project.statistics.storage_size > STORAGE_LIMIT, msg) + warning_if(stats.storage_size > STORAGE_LIMIT, msg) } -fn _report_repo_storage(project: &Project) -> ReportStatus { +fn _report_repo_storage(stats: &Statistics) -> ReportStatus { let msg = format!( "{} {} ({} %)", fl!("size-git-repo"), - human_bytes(project.statistics.repository_size as f64), - 100 * project.statistics.repository_size / project.statistics.storage_size + human_bytes(stats.repository_size as f64), + 100 * stats.repository_size / stats.storage_size ); - warning_if(project.statistics.repository_size > REPO_LIMIT, msg) + warning_if(stats.repository_size > REPO_LIMIT, msg) } -fn _report_artifact_storage(project: &Project) -> ReportStatus { +fn _report_artifact_storage(stats: &Statistics) -> ReportStatus { let msg = format!( "{} {} ({} %)", fl!("size-artifacts"), - human_bytes(project.statistics.job_artifacts_size as f64), - 100 * project.statistics.job_artifacts_size / project.statistics.storage_size + human_bytes(stats.job_artifacts_size as f64), + 100 * stats.job_artifacts_size / stats.storage_size ); - warning_if( - project.statistics.job_artifacts_size > ARTIFACT_JOBS_LIMIT, - msg, - ) + warning_if(stats.job_artifacts_size > ARTIFACT_JOBS_LIMIT, msg) } -fn _report_package_storage(project: &Project) -> ReportStatus { +fn _report_package_storage(stats: &Statistics) -> ReportStatus { let msg = format!( "{} {} ({} %)", fl!("size-packages"), - human_bytes(project.statistics.packages_size as f64), - 100 * project.statistics.packages_size / project.statistics.storage_size + human_bytes(stats.packages_size as f64), + 100 * stats.packages_size / stats.storage_size ); - warning_if( - project.statistics.packages_size > PACKAGE_REGISTRY_LIMIT, - msg, - ) + warning_if(stats.packages_size > PACKAGE_REGISTRY_LIMIT, msg) } fn gitlab_url(repo: &Repository) -> Option<(String, String)> { diff --git a/src/diagnosis/job_analysis.rs b/src/diagnosis/job_analysis.rs index c5a7e2588131d236915ce9ac46a57147e0319ab2..eed9e04469517c4fad818c45b9c9090f8bd6d134 100644 --- a/src/diagnosis/job_analysis.rs +++ b/src/diagnosis/job_analysis.rs @@ -1,4 +1,4 @@ -use chrono::{DateTime, Duration, Local}; +use chrono::{DateTime, Local, TimeDelta}; use gitlab::api::paged; use gitlab::api::{projects, Pagination, Query}; use gitlab::Gitlab; @@ -7,7 +7,7 @@ use serde::Deserialize; use crate::diagnosis::gitlab_connection::{GitlabRepository, Project}; use crate::diagnosis::ReportStatus; -use crate::{ReportJob, ReportPending, Reportable}; +use crate::{fl, ReportJob, ReportPending, Reportable}; #[derive(Debug, Deserialize)] pub struct Artifact { @@ -38,6 +38,16 @@ impl Reportable for JobAnalysisReport { } } +impl JobAnalysisReport { + pub fn simple(status: ReportStatus) -> JobAnalysisReport { + JobAnalysisReport { + gitlab_jobs: vec![], + report_status: vec![status], + savable_bytes: 0, + } + } +} + impl ReportJob for JobAnalysisJob { type Diagnosis = JobAnalysisReport; @@ -47,27 +57,25 @@ impl ReportJob for JobAnalysisJob { job: { std::thread::spawn(move || { if !self.project.jobs_enabled { - return JobAnalysisReport { - report_status: vec![ReportStatus::NA( - "No CI/CD configured on this project".to_string(), - )], - gitlab_jobs: vec![], - savable_bytes: 0, - }; + return JobAnalysisReport::simple(ReportStatus::NA(fl!("no-cicd"))); } let endpoint = projects::jobs::Jobs::builder() .project(self.project.id) .build() .unwrap(); - let jobs: Vec<GitlabJob> = paged(endpoint, Pagination::All) - .query(&self.gitlab) - .unwrap(); - let (report, bytes_savable) = self._number_jobs(&jobs); - JobAnalysisReport { - report_status: vec![report], - gitlab_jobs: jobs, - savable_bytes: bytes_savable, - } + paged(endpoint, Pagination::All).query(&self.gitlab).map_or( + JobAnalysisReport::simple(ReportStatus::NA(fl!( + "no-permission-jobanalysis" + ))), + |jobs| { + let (report, bytes_savable) = self._number_jobs(&jobs); + JobAnalysisReport { + report_status: vec![report], + gitlab_jobs: jobs, + savable_bytes: bytes_savable, + } + }, + ) }) }, progress: None, @@ -86,7 +94,7 @@ impl JobAnalysisJob { } fn _number_jobs(&self, jobs: &[GitlabJob]) -> (ReportStatus, u64) { - let ref_date = Local::now() - Duration::days(self.days as i64); + let ref_date = Local::now() - TimeDelta::try_days(self.days as i64).unwrap(); let mut old_count: usize = 0; let mut old_size: u64 = 0; for job in jobs.iter() { diff --git a/src/diagnosis/package_analysis.rs b/src/diagnosis/package_analysis.rs index 6f8073fc4c8d6add51de8706710543f4df7eabe6..f1152f1050a64fd80a342c811afae57dd04859be 100644 --- a/src/diagnosis/package_analysis.rs +++ b/src/diagnosis/package_analysis.rs @@ -99,11 +99,9 @@ impl ReportJob for PackageAnalysisJob { let query: Result<Vec<GitlabPackage>, _> = gitlab::api::paged(endpoint, Pagination::All).query(&self.gitlab); match query { - Err(e) => self.default_report(ReportStatus::ERROR(format!( - "{} {}", - fl!("error"), - e.to_string() - ))), + Err(e) => { + self.default_report(ReportStatus::ERROR(format!("{} {}", fl!("error"), e))) + } Ok(mut packages) => { packages.sort_by(|a, b| b.created_at.partial_cmp(&a.created_at).unwrap()); let mut savable_bytes = 0; @@ -205,7 +203,7 @@ fn _get_extension(file_name: &str) -> &str { #[cfg(test)] mod tests { - use chrono::Duration; + use chrono::TimeDelta; use super::*; @@ -216,36 +214,36 @@ mod tests { id: 42, name: "generic".to_string(), package_type: "".to_string(), - created_at: Local::now() - Duration::days(30), + created_at: Local::now() - TimeDelta::try_days(30).unwrap(), }; let files = vec![ GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(4), + created_at: Local::now() - TimeDelta::try_days(4).unwrap(), file_name: "abc.txt".to_string(), size: 13, }, GitlabPackageFile { id: 54, - created_at: Local::now() - Duration::days(5), + created_at: Local::now() - TimeDelta::try_days(5).unwrap(), file_name: "abc.txt".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(6), + created_at: Local::now() - TimeDelta::try_days(6).unwrap(), file_name: "zyx.txt".to_string(), size: 13, }, GitlabPackageFile { id: 56, - created_at: Local::now() - Duration::days(7), + created_at: Local::now() - TimeDelta::try_days(7).unwrap(), file_name: "abc.txt".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(8), + created_at: Local::now() - TimeDelta::try_days(8).unwrap(), file_name: "zyx.txt".to_string(), size: 13, }, @@ -265,7 +263,7 @@ mod tests { id: 42, name: "my-generic".to_string(), package_type: "generic".to_string(), - created_at: Local::now() - Duration::days(30), + created_at: Local::now() - TimeDelta::try_days(30).unwrap(), }; let files = vec![]; @@ -283,42 +281,42 @@ mod tests { id: 42, name: "my-app".to_string(), package_type: "maven".to_string(), - created_at: Local::now() - Duration::days(30), + created_at: Local::now() - TimeDelta::try_days(30).unwrap(), }; let files = vec![ GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(4), + created_at: Local::now() - TimeDelta::try_days(4).unwrap(), file_name: "my-app-1.5-20181107.152550-1.jar".to_string(), size: 13, }, GitlabPackageFile { id: 54, - created_at: Local::now() - Duration::days(4), + created_at: Local::now() - TimeDelta::try_days(4).unwrap(), file_name: "my-app-1.5-20181107.152550-1.pom".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(4), + created_at: Local::now() - TimeDelta::try_days(4).unwrap(), file_name: "maven-metadata.xml".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(5), + created_at: Local::now() - TimeDelta::try_days(5).unwrap(), file_name: "my-app-1.5-20181007.142550-1.jar".to_string(), size: 13, }, GitlabPackageFile { id: 54, - created_at: Local::now() - Duration::days(5), + created_at: Local::now() - TimeDelta::try_days(5).unwrap(), file_name: "my-app-1.5-20181007.142550-1.pom".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(5), + created_at: Local::now() - TimeDelta::try_days(5).unwrap(), file_name: "maven-metadata.xml".to_string(), size: 13, }, @@ -338,42 +336,42 @@ mod tests { id: 42, name: "my-app".to_string(), package_type: "generic".to_string(), - created_at: Local::now() - Duration::days(30), + created_at: Local::now() - TimeDelta::try_days(30).unwrap(), }; let files = vec![ GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(4), + created_at: Local::now() - TimeDelta::try_days(4).unwrap(), file_name: "my-app-1.5-20181107.152550-1.jar".to_string(), size: 13, }, GitlabPackageFile { id: 54, - created_at: Local::now() - Duration::days(4), + created_at: Local::now() - TimeDelta::try_days(4).unwrap(), file_name: "my-app-1.5-20181107.152550-1.pom".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(4), + created_at: Local::now() - TimeDelta::try_days(4).unwrap(), file_name: "maven-metadata.xml".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(5), + created_at: Local::now() - TimeDelta::try_days(5).unwrap(), file_name: "my-app-1.5-20181007.142550-1.jar".to_string(), size: 13, }, GitlabPackageFile { id: 54, - created_at: Local::now() - Duration::days(5), + created_at: Local::now() - TimeDelta::try_days(5).unwrap(), file_name: "my-app-1.5-20181007.142550-1.pom".to_string(), size: 13, }, GitlabPackageFile { id: 50, - created_at: Local::now() - Duration::days(5), + created_at: Local::now() - TimeDelta::try_days(5).unwrap(), file_name: "maven-metadata.xml".to_string(), size: 13, }, diff --git a/src/diagnosis/pipeline_analysis.rs b/src/diagnosis/pipeline_analysis.rs index 06a1e5d600afe8047387c791f72a13b70132bbdb..062dba4d906f9b5ffc90b0fffe407b2f79d9ae1b 100644 --- a/src/diagnosis/pipeline_analysis.rs +++ b/src/diagnosis/pipeline_analysis.rs @@ -1,4 +1,4 @@ -use chrono::{DateTime, Duration, Local}; +use chrono::{DateTime, Local, TimeDelta}; use gitlab::api::{Pagination, Query}; use gitlab::Gitlab; use serde::Deserialize; @@ -32,7 +32,7 @@ impl Reportable for PipelineAnalysisReport { } impl PipelineAnalysisJob { - fn to_report( + fn into_report( self, report_status: Vec<ReportStatus>, pipelines: Vec<GitlabPipeline>, @@ -54,7 +54,7 @@ impl ReportJob for PipelineAnalysisJob { pending_msg: fl!("pipeline-analysing"), job: std::thread::spawn(move || { if !self.project.jobs_enabled { - return self.to_report(vec![ReportStatus::NA(fl!("no-cicd"))], vec![]); + return self.into_report(vec![ReportStatus::NA(fl!("no-cicd"))], vec![]); } let endpoint = gitlab::api::projects::pipelines::Pipelines::builder() @@ -64,19 +64,15 @@ impl ReportJob for PipelineAnalysisJob { let query: Result<Vec<GitlabPipeline>, _> = gitlab::api::paged(endpoint, Pagination::All).query(&self.gitlab); match query { - Err(e) => self.to_report( - vec![ReportStatus::ERROR(format!( - "{} {}", - fl!("error"), - e.to_string() - ))], + Err(e) => self.into_report( + vec![ReportStatus::ERROR(format!("{} {}", fl!("error"), e))], vec![], ), Ok(mut pipelines) => { let days = self.days; - let ref_date = Local::now() - Duration::days(days as i64); + let ref_date = Local::now() - TimeDelta::try_days(days as i64).unwrap(); pipelines.sort_by(|a, b| a.created_at.partial_cmp(&b.created_at).unwrap()); - self.to_report( + self.into_report( vec![ReportStatus::NA(fl!( "pipeline-report", total_pipelines = pipelines.len(), diff --git a/src/diagnosis/pipeline_clean.rs b/src/diagnosis/pipeline_clean.rs index af6e3cc13f329af38472eddfb0183f7ba8f20f3a..501d0399ec74d4da28a4eae33a4ef648f894ca74 100644 --- a/src/diagnosis/pipeline_clean.rs +++ b/src/diagnosis/pipeline_clean.rs @@ -1,15 +1,15 @@ use std::cmp::max; use std::sync::mpsc; -use chrono::{Duration, Local}; +use chrono::{Local, TimeDelta}; use gitlab::api::{ApiError, Query}; use gitlab::Gitlab; use human_bytes::human_bytes; -use crate::diagnosis::gitlab_connection::Project; +use crate::{fl, Reportable, ReportPending, ReportStatus}; +use crate::diagnosis::{GITLAB_SCOPE_ERROR, RemedyJob}; +use crate::diagnosis::gitlab_connection::{Project, Statistics}; use crate::diagnosis::pipeline_analysis::{GitlabPipeline, PipelineAnalysisReport}; -use crate::diagnosis::{RemedyJob, GITLAB_SCOPE_ERROR}; -use crate::{fl, ReportPending, ReportStatus, Reportable}; pub struct PipelineCleanJob { pub pipeline_report: PipelineAnalysisReport, @@ -17,7 +17,7 @@ pub struct PipelineCleanJob { } pub struct PipelineCleanReport { - pub saved_bytes: u64, + pub saved_bytes: Option<u64>, pub deleted_pipelines: Vec<GitlabPipeline>, pub report_status: Vec<ReportStatus>, } @@ -31,7 +31,7 @@ impl Reportable for PipelineCleanReport { impl PipelineCleanReport { fn fatal_error(id: u64, msg: &str) -> Self { Self { - saved_bytes: 0, + saved_bytes: None, deleted_pipelines: vec![], report_status: vec![ReportStatus::ERROR(format!( "Pipeline {} - Error : {}", @@ -46,7 +46,7 @@ impl RemedyJob for PipelineCleanJob { fn remedy(self) -> ReportPending<Self::Report> { let (tx, rx) = mpsc::channel(); - let ref_date = Local::now() - Duration::days(self.days as i64); + let ref_date = Local::now() - TimeDelta::try_days(self.days as i64).unwrap(); let count = self .pipeline_report .pipelines @@ -57,6 +57,13 @@ impl RemedyJob for PipelineCleanJob { pending_msg: fl!("pipeline-deleting"), job: std::thread::spawn(move || { let mut deleted_pipelines = vec![]; + if self.pipeline_report.pipelines.is_empty() { + return PipelineCleanReport { + saved_bytes: None, + deleted_pipelines, + report_status: vec![ReportStatus::NA(fl!("pipeline-no-deletion"))], + }; + } let last_index = self.pipeline_report.pipelines.len() - 1; let mut last_is_old = false; for (i, pipeline) in self.pipeline_report.pipelines.into_iter().enumerate() { @@ -115,15 +122,30 @@ impl RemedyJob for PipelineCleanJob { } let _ = tx.send(i); } - let saved_bytes = PipelineCleanJob::_compute_saved_bytes( - &self.pipeline_report.gitlab, - &self.pipeline_report.project, - ); - let mut report_status = vec![ReportStatus::OK(fl!( - "pipeline-clean-report", - nb_pipelines = deleted_pipelines.len(), - size = human_bytes(saved_bytes as f64) - ))]; + + let mut report_status = vec![]; + + let saved_bytes = + if let Some(stats) = self.pipeline_report.project.statistics.as_ref() { + let saved_bytes_value = PipelineCleanJob::_compute_saved_bytes( + &self.pipeline_report.gitlab, + &self.pipeline_report.project, + stats, + ); + report_status.push(ReportStatus::OK(fl!( + "pipeline-clean-report-size", + nb_pipelines = deleted_pipelines.len(), + size = human_bytes(saved_bytes_value as f64) + ))); + Some(saved_bytes_value) + } else { + report_status.push(ReportStatus::OK(fl!( + "pipeline-clean-report", + nb_pipelines = deleted_pipelines.len() + ))); + None + }; + if last_is_old { report_status.push(ReportStatus::NA(fl!("pipeline-last-notdeleted"))); } @@ -147,8 +169,8 @@ impl PipelineCleanJob { } } - fn _compute_saved_bytes(gitlab: &Gitlab, project: &Project) -> u64 { - let old_size = project.statistics.job_artifacts_size; + fn _compute_saved_bytes(gitlab: &Gitlab, project: &Project, stats: &Statistics) -> u64 { + let old_size = stats.job_artifacts_size; let endpoint = gitlab::api::projects::Project::builder() .project(project.id) .statistics(true) @@ -157,7 +179,7 @@ impl PipelineCleanJob { let new_size = endpoint .query(gitlab) - .map(|p: Project| p.statistics.job_artifacts_size) + .map(|p: Project| p.statistics.unwrap().job_artifacts_size) .unwrap_or(old_size); max(0, old_size - new_size) } diff --git a/src/main.rs b/src/main.rs index 7c182ecb4d1c37ff95c918fc72970c46fb61289f..f9f64561fd5d83617cf3cdd4f717816c2a640a37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,10 @@ +use i18n_embed::{ + fluent::{fluent_language_loader, FluentLanguageLoader}, + DesktopLanguageRequester, +}; +use lazy_static::lazy_static; +use rust_embed::RustEmbed; +use serde::Serialize; use structopt::StructOpt; use cli::Args; @@ -12,13 +19,6 @@ use crate::diagnosis::pipeline_analysis::{PipelineAnalysisJob, PipelineAnalysisR use crate::diagnosis::pipeline_clean::PipelineCleanJob; use crate::diagnosis::ReportStatus; use crate::diagnosis::{RemedyJob, ReportJob, ReportPending, Reportable}; -use i18n_embed::{ - fluent::{fluent_language_loader, FluentLanguageLoader}, - DesktopLanguageRequester, -}; -use lazy_static::lazy_static; -use rust_embed::RustEmbed; -use serde::Serialize; pub mod api; pub mod cli; @@ -68,7 +68,7 @@ macro_rules! fl { #[derive(Serialize)] struct AnalysisReport { pub url: String, - pub stats: Statistics, + pub stats: Option<Statistics>, pub savable_bytes_jobs: u64, pub savable_bytes_packages: u64, pub savable_bytes_containers: u64, @@ -78,52 +78,52 @@ struct AnalysisReport { impl AnalysisReport { pub fn compute_values(&mut self) { - let rating_number = self._get_rating(); - self.rating = Some( - RATING_ACRONYM[RATING_RANGE - .iter() - .position(|&e| rating_number < e) - .unwrap_or(RATING_ACRONYM.len() - 1)], - ); - - let impact_number = self._get_impact(); - self.impact = Some( - IMPACT_ACRONYM[IMPACT_RANGE - .iter() - .position(|&e| impact_number < e) - .unwrap_or(IMPACT_ACRONYM.len() - 1)], - ); + if let Some(stats) = &self.stats { + let rating_number = self._get_rating(stats); + self.rating = Some( + RATING_ACRONYM[RATING_RANGE + .iter() + .position(|&e| rating_number < e) + .unwrap_or(RATING_ACRONYM.len() - 1)], + ); + + let impact_number = self._get_impact(stats); + self.impact = Some( + IMPACT_ACRONYM[IMPACT_RANGE + .iter() + .position(|&e| impact_number < e) + .unwrap_or(IMPACT_ACRONYM.len() - 1)], + ); + } } - pub fn _get_impact(&self) -> u64 { + pub fn _get_impact(&self, stats: &Statistics) -> u64 { // Impact == Disk impact. git repo is evaluated ten times - self.stats.repository_size * 9 + self.stats.storage_size + stats.repository_size * 9 + stats.storage_size } - pub fn _get_rating(&self) -> u64 { + pub fn _get_rating(&self, stats: &Statistics) -> u64 { // Rating == Margin of improvement (less is better) // Containers are ignored for now let repo_limit = 100 * 1024 * 1024; - let savable_repo = if self.stats.repository_size > repo_limit { - self.stats.repository_size - repo_limit + let savable_repo = if stats.repository_size > repo_limit { + stats.repository_size - repo_limit } else { 0 }; (savable_repo * 9 + self.savable_bytes_jobs + self.savable_bytes_packages) * 100 - / (self.stats.repository_size * 9 - + self.stats.job_artifacts_size - + self.stats.packages_size) + / (stats.repository_size * 9 + stats.job_artifacts_size + stats.packages_size) } } fn _connect_to_gitlab(args: &Args) -> GitlabRepository { let connection_job = { if args.url.is_some() { - ConnectionJob::FromUrl(args.url.as_ref().unwrap().clone()) + ConnectionJob::FromUrl(args.url.as_ref().unwrap().clone(), args.token.clone()) } else { let default_path = String::from("."); let path: &str = args.git_path.as_ref().unwrap_or(&default_path); - ConnectionJob::FromPath(path.to_string()) + ConnectionJob::FromPath(path.to_string(), args.token.clone()) } };