├── .github ├── FUNDING.yml ├── auto-assign.yml └── workflows │ ├── auto-assign.yml │ ├── ci.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── README.md ├── action.yml ├── ci-local.sh ├── docs ├── USAGE.md ├── architecture │ └── flow.png └── release │ ├── release-process.md │ └── v1.md ├── src ├── github.rs ├── joke.rs ├── main.rs ├── summarizer.rs └── utils.rs └── test_resources └── testfile.txt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: 2 | - "https://www.patreon.com/bansikah22" 3 | - "https://liberapay.com/bansikah22" 4 | # - "https://www.buymeacoffee.com/yourusername" 5 | # - "https://ko-fi.com/yourusername" 6 | -------------------------------------------------------------------------------- /.github/auto-assign.yml: -------------------------------------------------------------------------------- 1 | addReviewers: true 2 | addAssignees: true 3 | reviewers: 4 | - bansikah22 5 | - Christiantyemele 6 | assignees: 7 | - bansikah22 8 | numberOfReviewers: 1 9 | -------------------------------------------------------------------------------- /.github/workflows/auto-assign.yml: -------------------------------------------------------------------------------- 1 | name: "Auto Assign Reviewers" 2 | 3 | on: 4 | pull_request: 5 | types: [opened, ready_for_review] 6 | 7 | jobs: 8 | auto-assign: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Assign Reviewers and Assignees 12 | uses: kentaro-m/auto-assign-action@v2.0.0 13 | with: 14 | configuration-path: .github/auto-assign.yml 15 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [pull_request] 4 | 5 | env: 6 | CARGO_TERM_COLOR: always 7 | RUSTFLAGS: -D warnings 8 | 9 | jobs: 10 | 11 | ci: 12 | name: Build and test 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v4 18 | 19 | - name: Cache dependencies 20 | uses: actions/cache@v4 21 | with: 22 | path: | 23 | ~/.cargo/bin 24 | ~/.cargo/registry/index/ 25 | ~/.cargo/registry/cache/ 26 | ~/.cargo/git/db/ 27 | target/ 28 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 29 | restore-keys: | 30 | ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 31 | ${{ runner.os }}-cargo 32 | 33 | - name: Set up Rust 34 | uses: actions-rust-lang/setup-rust-toolchain@v1 35 | with: 36 | toolchain: stable 37 | rustflags: 38 | 39 | - name: Install Nextest test runner 40 | uses: taiki-e/install-action@nextest 41 | 42 | - name: Check Formatting 43 | run: cargo fmt --all -- --check 44 | 45 | - name: Build Project 46 | run: cargo build --workspace --all-features 47 | 48 | - name: Run Tests 49 | run: cargo nextest run --workspace --all-targets --all-features --no-fail-fast || echo "No tests found, skipping..." 50 | 51 | - name: Lints checks 52 | run: | 53 | cargo clippy --workspace --all-targets --all-features -- -D warnings 54 | 55 | - name: Check API documentation 56 | run: cargo doc --workspace --all-features --no-deps -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Setup Rust 21 | uses: actions-rs/toolchain@v1 22 | with: 23 | toolchain: stable 24 | profile: minimal 25 | override: true 26 | 27 | - name: Build 28 | uses: actions-rs/cargo@v1 29 | with: 30 | command: build 31 | args: --release --verbose 32 | 33 | - name: Test 34 | uses: actions-rs/cargo@v1 35 | with: 36 | command: test 37 | args: --verbose 38 | 39 | - name: Package Binary 40 | run: | 41 | # Create a temporary directory for packaging 42 | mkdir -p package 43 | cp target/release/pr-summarizer package/ 44 | 45 | # Package the binary properly 46 | cd package 47 | tar -czf ../pr-summarizer-${{ github.ref_name }}.tar.gz pr-summarizer 48 | cd .. 49 | 50 | # Verify the archive 51 | echo "Verifying archive contents:" 52 | tar -tvf pr-summarizer-${{ github.ref_name }}.tar.gz 53 | if: success() 54 | 55 | - name: Create and Upload Release 56 | uses: softprops/action-gh-release@v1 57 | with: 58 | tag_name: ${{ github.ref_name }} 59 | name: Release ${{ github.ref_name }} 60 | draft: false 61 | prerelease: false 62 | body: | 63 | ## What's New 64 | - Automated PR summarization with jokes 🎉 65 | - Enhanced with emojis for a polished look ✨ 66 | - Built with Rust 🦀 67 | - See [README.md](README.md) for usage instructions 68 | files: pr-summarizer-${{ github.ref_name }}.tar.gz 69 | env: 70 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: PR Summarizer 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened] 6 | 7 | permissions: 8 | pull-requests: write # Required to comment on PRs 9 | issues: write # Required for PR comments via issues API 10 | 11 | jobs: 12 | summarize: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 # Ensures full history for diff analysis 19 | 20 | - name: Run PR Summarizer 21 | uses: ./ # Uses the local action in my repository 22 | with: 23 | github_token: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | 4 | # Generated by Cargo 5 | # will have compiled files and executables 6 | debug/ 7 | target/ 8 | 9 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 10 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 11 | Cargo.lock 12 | 13 | # These are backup files generated by rustfmt 14 | **/*.rs.bk 15 | 16 | # MSVC Windows builds of rustc generate these, which store debugging information 17 | *.pdb 18 | 19 | # RustRover 20 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 21 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 22 | # and can be added to the global gitignore or merged into this file. For a more nuclear 23 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 24 | #.idea/ 25 | 26 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "android-tzdata" 31 | version = "0.1.1" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 34 | 35 | [[package]] 36 | name = "android_system_properties" 37 | version = "0.1.5" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 40 | dependencies = [ 41 | "libc", 42 | ] 43 | 44 | [[package]] 45 | name = "anstream" 46 | version = "0.6.18" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 49 | dependencies = [ 50 | "anstyle", 51 | "anstyle-parse", 52 | "anstyle-query", 53 | "anstyle-wincon", 54 | "colorchoice", 55 | "is_terminal_polyfill", 56 | "utf8parse", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle" 61 | version = "1.0.10" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 64 | 65 | [[package]] 66 | name = "anstyle-parse" 67 | version = "0.2.6" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 70 | dependencies = [ 71 | "utf8parse", 72 | ] 73 | 74 | [[package]] 75 | name = "anstyle-query" 76 | version = "1.1.2" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 79 | dependencies = [ 80 | "windows-sys 0.59.0", 81 | ] 82 | 83 | [[package]] 84 | name = "anstyle-wincon" 85 | version = "3.0.7" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 88 | dependencies = [ 89 | "anstyle", 90 | "once_cell", 91 | "windows-sys 0.59.0", 92 | ] 93 | 94 | [[package]] 95 | name = "anyhow" 96 | version = "1.0.97" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" 99 | 100 | [[package]] 101 | name = "arc-swap" 102 | version = "1.7.1" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" 105 | 106 | [[package]] 107 | name = "async-trait" 108 | version = "0.1.87" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" 111 | dependencies = [ 112 | "proc-macro2", 113 | "quote", 114 | "syn", 115 | ] 116 | 117 | [[package]] 118 | name = "atomic-waker" 119 | version = "1.1.2" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 122 | 123 | [[package]] 124 | name = "autocfg" 125 | version = "1.4.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 128 | 129 | [[package]] 130 | name = "backtrace" 131 | version = "0.3.74" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 134 | dependencies = [ 135 | "addr2line", 136 | "cfg-if", 137 | "libc", 138 | "miniz_oxide", 139 | "object", 140 | "rustc-demangle", 141 | "windows-targets", 142 | ] 143 | 144 | [[package]] 145 | name = "base64" 146 | version = "0.22.1" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 149 | 150 | [[package]] 151 | name = "bitflags" 152 | version = "2.9.0" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 155 | 156 | [[package]] 157 | name = "bumpalo" 158 | version = "3.17.0" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 161 | 162 | [[package]] 163 | name = "bytes" 164 | version = "1.10.1" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 167 | 168 | [[package]] 169 | name = "cc" 170 | version = "1.2.16" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" 173 | dependencies = [ 174 | "shlex", 175 | ] 176 | 177 | [[package]] 178 | name = "cfg-if" 179 | version = "1.0.0" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 182 | 183 | [[package]] 184 | name = "chrono" 185 | version = "0.4.40" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" 188 | dependencies = [ 189 | "android-tzdata", 190 | "iana-time-zone", 191 | "js-sys", 192 | "num-traits", 193 | "serde", 194 | "wasm-bindgen", 195 | "windows-link", 196 | ] 197 | 198 | [[package]] 199 | name = "colorchoice" 200 | version = "1.0.3" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 203 | 204 | [[package]] 205 | name = "core-foundation" 206 | version = "0.9.4" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 209 | dependencies = [ 210 | "core-foundation-sys", 211 | "libc", 212 | ] 213 | 214 | [[package]] 215 | name = "core-foundation" 216 | version = "0.10.0" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" 219 | dependencies = [ 220 | "core-foundation-sys", 221 | "libc", 222 | ] 223 | 224 | [[package]] 225 | name = "core-foundation-sys" 226 | version = "0.8.7" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 229 | 230 | [[package]] 231 | name = "deranged" 232 | version = "0.3.11" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 235 | dependencies = [ 236 | "powerfmt", 237 | ] 238 | 239 | [[package]] 240 | name = "displaydoc" 241 | version = "0.2.5" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 244 | dependencies = [ 245 | "proc-macro2", 246 | "quote", 247 | "syn", 248 | ] 249 | 250 | [[package]] 251 | name = "dotenv" 252 | version = "0.15.0" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 255 | 256 | [[package]] 257 | name = "either" 258 | version = "1.15.0" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 261 | 262 | [[package]] 263 | name = "encoding_rs" 264 | version = "0.8.35" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 267 | dependencies = [ 268 | "cfg-if", 269 | ] 270 | 271 | [[package]] 272 | name = "env_filter" 273 | version = "0.1.3" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" 276 | dependencies = [ 277 | "log", 278 | "regex", 279 | ] 280 | 281 | [[package]] 282 | name = "env_logger" 283 | version = "0.11.7" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" 286 | dependencies = [ 287 | "anstream", 288 | "anstyle", 289 | "env_filter", 290 | "jiff", 291 | "log", 292 | ] 293 | 294 | [[package]] 295 | name = "equivalent" 296 | version = "1.0.2" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 299 | 300 | [[package]] 301 | name = "errno" 302 | version = "0.3.10" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" 305 | dependencies = [ 306 | "libc", 307 | "windows-sys 0.59.0", 308 | ] 309 | 310 | [[package]] 311 | name = "fastrand" 312 | version = "2.3.0" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 315 | 316 | [[package]] 317 | name = "fnv" 318 | version = "1.0.7" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 321 | 322 | [[package]] 323 | name = "foreign-types" 324 | version = "0.3.2" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 327 | dependencies = [ 328 | "foreign-types-shared", 329 | ] 330 | 331 | [[package]] 332 | name = "foreign-types-shared" 333 | version = "0.1.1" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 336 | 337 | [[package]] 338 | name = "form_urlencoded" 339 | version = "1.2.1" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 342 | dependencies = [ 343 | "percent-encoding", 344 | ] 345 | 346 | [[package]] 347 | name = "futures" 348 | version = "0.3.31" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 351 | dependencies = [ 352 | "futures-channel", 353 | "futures-core", 354 | "futures-executor", 355 | "futures-io", 356 | "futures-sink", 357 | "futures-task", 358 | "futures-util", 359 | ] 360 | 361 | [[package]] 362 | name = "futures-channel" 363 | version = "0.3.31" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 366 | dependencies = [ 367 | "futures-core", 368 | "futures-sink", 369 | ] 370 | 371 | [[package]] 372 | name = "futures-core" 373 | version = "0.3.31" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 376 | 377 | [[package]] 378 | name = "futures-executor" 379 | version = "0.3.31" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 382 | dependencies = [ 383 | "futures-core", 384 | "futures-task", 385 | "futures-util", 386 | ] 387 | 388 | [[package]] 389 | name = "futures-io" 390 | version = "0.3.31" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 393 | 394 | [[package]] 395 | name = "futures-macro" 396 | version = "0.3.31" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 399 | dependencies = [ 400 | "proc-macro2", 401 | "quote", 402 | "syn", 403 | ] 404 | 405 | [[package]] 406 | name = "futures-sink" 407 | version = "0.3.31" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 410 | 411 | [[package]] 412 | name = "futures-task" 413 | version = "0.3.31" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 416 | 417 | [[package]] 418 | name = "futures-util" 419 | version = "0.3.31" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 422 | dependencies = [ 423 | "futures-channel", 424 | "futures-core", 425 | "futures-io", 426 | "futures-macro", 427 | "futures-sink", 428 | "futures-task", 429 | "memchr", 430 | "pin-project-lite", 431 | "pin-utils", 432 | "slab", 433 | ] 434 | 435 | [[package]] 436 | name = "getrandom" 437 | version = "0.2.15" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 440 | dependencies = [ 441 | "cfg-if", 442 | "js-sys", 443 | "libc", 444 | "wasi 0.11.0+wasi-snapshot-preview1", 445 | "wasm-bindgen", 446 | ] 447 | 448 | [[package]] 449 | name = "getrandom" 450 | version = "0.3.1" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" 453 | dependencies = [ 454 | "cfg-if", 455 | "libc", 456 | "wasi 0.13.3+wasi-0.2.2", 457 | "windows-targets", 458 | ] 459 | 460 | [[package]] 461 | name = "gimli" 462 | version = "0.31.1" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 465 | 466 | [[package]] 467 | name = "h2" 468 | version = "0.4.8" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" 471 | dependencies = [ 472 | "atomic-waker", 473 | "bytes", 474 | "fnv", 475 | "futures-core", 476 | "futures-sink", 477 | "http", 478 | "indexmap", 479 | "slab", 480 | "tokio", 481 | "tokio-util", 482 | "tracing", 483 | ] 484 | 485 | [[package]] 486 | name = "hashbrown" 487 | version = "0.15.2" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 490 | 491 | [[package]] 492 | name = "heck" 493 | version = "0.4.1" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 496 | 497 | [[package]] 498 | name = "http" 499 | version = "1.2.0" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" 502 | dependencies = [ 503 | "bytes", 504 | "fnv", 505 | "itoa", 506 | ] 507 | 508 | [[package]] 509 | name = "http-body" 510 | version = "1.0.1" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 513 | dependencies = [ 514 | "bytes", 515 | "http", 516 | ] 517 | 518 | [[package]] 519 | name = "http-body-util" 520 | version = "0.1.2" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 523 | dependencies = [ 524 | "bytes", 525 | "futures-util", 526 | "http", 527 | "http-body", 528 | "pin-project-lite", 529 | ] 530 | 531 | [[package]] 532 | name = "httparse" 533 | version = "1.10.1" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 536 | 537 | [[package]] 538 | name = "hyper" 539 | version = "1.6.0" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 542 | dependencies = [ 543 | "bytes", 544 | "futures-channel", 545 | "futures-util", 546 | "h2", 547 | "http", 548 | "http-body", 549 | "httparse", 550 | "itoa", 551 | "pin-project-lite", 552 | "smallvec", 553 | "tokio", 554 | "want", 555 | ] 556 | 557 | [[package]] 558 | name = "hyper-rustls" 559 | version = "0.27.5" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" 562 | dependencies = [ 563 | "futures-util", 564 | "http", 565 | "hyper", 566 | "hyper-util", 567 | "log", 568 | "rustls", 569 | "rustls-native-certs", 570 | "rustls-pki-types", 571 | "tokio", 572 | "tokio-rustls", 573 | "tower-service", 574 | ] 575 | 576 | [[package]] 577 | name = "hyper-timeout" 578 | version = "0.5.2" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" 581 | dependencies = [ 582 | "hyper", 583 | "hyper-util", 584 | "pin-project-lite", 585 | "tokio", 586 | "tower-service", 587 | ] 588 | 589 | [[package]] 590 | name = "hyper-tls" 591 | version = "0.6.0" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 594 | dependencies = [ 595 | "bytes", 596 | "http-body-util", 597 | "hyper", 598 | "hyper-util", 599 | "native-tls", 600 | "tokio", 601 | "tokio-native-tls", 602 | "tower-service", 603 | ] 604 | 605 | [[package]] 606 | name = "hyper-util" 607 | version = "0.1.10" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" 610 | dependencies = [ 611 | "bytes", 612 | "futures-channel", 613 | "futures-util", 614 | "http", 615 | "http-body", 616 | "hyper", 617 | "pin-project-lite", 618 | "socket2", 619 | "tokio", 620 | "tower-service", 621 | "tracing", 622 | ] 623 | 624 | [[package]] 625 | name = "iana-time-zone" 626 | version = "0.1.61" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 629 | dependencies = [ 630 | "android_system_properties", 631 | "core-foundation-sys", 632 | "iana-time-zone-haiku", 633 | "js-sys", 634 | "wasm-bindgen", 635 | "windows-core", 636 | ] 637 | 638 | [[package]] 639 | name = "iana-time-zone-haiku" 640 | version = "0.1.2" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 643 | dependencies = [ 644 | "cc", 645 | ] 646 | 647 | [[package]] 648 | name = "icu_collections" 649 | version = "1.5.0" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 652 | dependencies = [ 653 | "displaydoc", 654 | "yoke", 655 | "zerofrom", 656 | "zerovec", 657 | ] 658 | 659 | [[package]] 660 | name = "icu_locid" 661 | version = "1.5.0" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 664 | dependencies = [ 665 | "displaydoc", 666 | "litemap", 667 | "tinystr", 668 | "writeable", 669 | "zerovec", 670 | ] 671 | 672 | [[package]] 673 | name = "icu_locid_transform" 674 | version = "1.5.0" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 677 | dependencies = [ 678 | "displaydoc", 679 | "icu_locid", 680 | "icu_locid_transform_data", 681 | "icu_provider", 682 | "tinystr", 683 | "zerovec", 684 | ] 685 | 686 | [[package]] 687 | name = "icu_locid_transform_data" 688 | version = "1.5.0" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 691 | 692 | [[package]] 693 | name = "icu_normalizer" 694 | version = "1.5.0" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 697 | dependencies = [ 698 | "displaydoc", 699 | "icu_collections", 700 | "icu_normalizer_data", 701 | "icu_properties", 702 | "icu_provider", 703 | "smallvec", 704 | "utf16_iter", 705 | "utf8_iter", 706 | "write16", 707 | "zerovec", 708 | ] 709 | 710 | [[package]] 711 | name = "icu_normalizer_data" 712 | version = "1.5.0" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 715 | 716 | [[package]] 717 | name = "icu_properties" 718 | version = "1.5.1" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 721 | dependencies = [ 722 | "displaydoc", 723 | "icu_collections", 724 | "icu_locid_transform", 725 | "icu_properties_data", 726 | "icu_provider", 727 | "tinystr", 728 | "zerovec", 729 | ] 730 | 731 | [[package]] 732 | name = "icu_properties_data" 733 | version = "1.5.0" 734 | source = "registry+https://github.com/rust-lang/crates.io-index" 735 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 736 | 737 | [[package]] 738 | name = "icu_provider" 739 | version = "1.5.0" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 742 | dependencies = [ 743 | "displaydoc", 744 | "icu_locid", 745 | "icu_provider_macros", 746 | "stable_deref_trait", 747 | "tinystr", 748 | "writeable", 749 | "yoke", 750 | "zerofrom", 751 | "zerovec", 752 | ] 753 | 754 | [[package]] 755 | name = "icu_provider_macros" 756 | version = "1.5.0" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 759 | dependencies = [ 760 | "proc-macro2", 761 | "quote", 762 | "syn", 763 | ] 764 | 765 | [[package]] 766 | name = "idna" 767 | version = "1.0.3" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 770 | dependencies = [ 771 | "idna_adapter", 772 | "smallvec", 773 | "utf8_iter", 774 | ] 775 | 776 | [[package]] 777 | name = "idna_adapter" 778 | version = "1.2.0" 779 | source = "registry+https://github.com/rust-lang/crates.io-index" 780 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 781 | dependencies = [ 782 | "icu_normalizer", 783 | "icu_properties", 784 | ] 785 | 786 | [[package]] 787 | name = "indexmap" 788 | version = "2.7.1" 789 | source = "registry+https://github.com/rust-lang/crates.io-index" 790 | checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" 791 | dependencies = [ 792 | "equivalent", 793 | "hashbrown", 794 | ] 795 | 796 | [[package]] 797 | name = "ipnet" 798 | version = "2.11.0" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 801 | 802 | [[package]] 803 | name = "iri-string" 804 | version = "0.7.7" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "dc0f0a572e8ffe56e2ff4f769f32ffe919282c3916799f8b68688b6030063bea" 807 | dependencies = [ 808 | "memchr", 809 | "serde", 810 | ] 811 | 812 | [[package]] 813 | name = "is_terminal_polyfill" 814 | version = "1.70.1" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 817 | 818 | [[package]] 819 | name = "itertools" 820 | version = "0.14.0" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" 823 | dependencies = [ 824 | "either", 825 | ] 826 | 827 | [[package]] 828 | name = "itoa" 829 | version = "1.0.15" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 832 | 833 | [[package]] 834 | name = "jiff" 835 | version = "0.2.4" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" 838 | dependencies = [ 839 | "jiff-static", 840 | "log", 841 | "portable-atomic", 842 | "portable-atomic-util", 843 | "serde", 844 | ] 845 | 846 | [[package]] 847 | name = "jiff-static" 848 | version = "0.2.4" 849 | source = "registry+https://github.com/rust-lang/crates.io-index" 850 | checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" 851 | dependencies = [ 852 | "proc-macro2", 853 | "quote", 854 | "syn", 855 | ] 856 | 857 | [[package]] 858 | name = "js-sys" 859 | version = "0.3.77" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 862 | dependencies = [ 863 | "once_cell", 864 | "wasm-bindgen", 865 | ] 866 | 867 | [[package]] 868 | name = "jsonwebtoken" 869 | version = "9.3.1" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" 872 | dependencies = [ 873 | "base64", 874 | "js-sys", 875 | "pem", 876 | "ring", 877 | "serde", 878 | "serde_json", 879 | "simple_asn1", 880 | ] 881 | 882 | [[package]] 883 | name = "libc" 884 | version = "0.2.170" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" 887 | 888 | [[package]] 889 | name = "linux-raw-sys" 890 | version = "0.4.15" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 893 | 894 | [[package]] 895 | name = "litemap" 896 | version = "0.7.5" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" 899 | 900 | [[package]] 901 | name = "lock_api" 902 | version = "0.4.12" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 905 | dependencies = [ 906 | "autocfg", 907 | "scopeguard", 908 | ] 909 | 910 | [[package]] 911 | name = "log" 912 | version = "0.4.26" 913 | source = "registry+https://github.com/rust-lang/crates.io-index" 914 | checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" 915 | 916 | [[package]] 917 | name = "memchr" 918 | version = "2.7.4" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 921 | 922 | [[package]] 923 | name = "mime" 924 | version = "0.3.17" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 927 | 928 | [[package]] 929 | name = "miniz_oxide" 930 | version = "0.8.5" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" 933 | dependencies = [ 934 | "adler2", 935 | ] 936 | 937 | [[package]] 938 | name = "mio" 939 | version = "1.0.3" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 942 | dependencies = [ 943 | "libc", 944 | "wasi 0.11.0+wasi-snapshot-preview1", 945 | "windows-sys 0.52.0", 946 | ] 947 | 948 | [[package]] 949 | name = "native-tls" 950 | version = "0.2.14" 951 | source = "registry+https://github.com/rust-lang/crates.io-index" 952 | checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 953 | dependencies = [ 954 | "libc", 955 | "log", 956 | "openssl", 957 | "openssl-probe", 958 | "openssl-sys", 959 | "schannel", 960 | "security-framework 2.11.1", 961 | "security-framework-sys", 962 | "tempfile", 963 | ] 964 | 965 | [[package]] 966 | name = "num-bigint" 967 | version = "0.4.6" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 970 | dependencies = [ 971 | "num-integer", 972 | "num-traits", 973 | ] 974 | 975 | [[package]] 976 | name = "num-conv" 977 | version = "0.1.0" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 980 | 981 | [[package]] 982 | name = "num-integer" 983 | version = "0.1.46" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 986 | dependencies = [ 987 | "num-traits", 988 | ] 989 | 990 | [[package]] 991 | name = "num-traits" 992 | version = "0.2.19" 993 | source = "registry+https://github.com/rust-lang/crates.io-index" 994 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 995 | dependencies = [ 996 | "autocfg", 997 | ] 998 | 999 | [[package]] 1000 | name = "object" 1001 | version = "0.36.7" 1002 | source = "registry+https://github.com/rust-lang/crates.io-index" 1003 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1004 | dependencies = [ 1005 | "memchr", 1006 | ] 1007 | 1008 | [[package]] 1009 | name = "octocrab" 1010 | version = "0.43.0" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "27527d68322f4c603319f7958973db8f9fa4be62c0e3fafe084f5562cf6353df" 1013 | dependencies = [ 1014 | "arc-swap", 1015 | "async-trait", 1016 | "base64", 1017 | "bytes", 1018 | "cfg-if", 1019 | "chrono", 1020 | "either", 1021 | "futures", 1022 | "futures-util", 1023 | "http", 1024 | "http-body", 1025 | "http-body-util", 1026 | "hyper", 1027 | "hyper-rustls", 1028 | "hyper-timeout", 1029 | "hyper-util", 1030 | "jsonwebtoken", 1031 | "once_cell", 1032 | "percent-encoding", 1033 | "pin-project", 1034 | "secrecy", 1035 | "serde", 1036 | "serde_json", 1037 | "serde_path_to_error", 1038 | "serde_urlencoded", 1039 | "snafu", 1040 | "tokio", 1041 | "tower", 1042 | "tower-http", 1043 | "tracing", 1044 | "url", 1045 | "web-time", 1046 | ] 1047 | 1048 | [[package]] 1049 | name = "once_cell" 1050 | version = "1.20.3" 1051 | source = "registry+https://github.com/rust-lang/crates.io-index" 1052 | checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" 1053 | 1054 | [[package]] 1055 | name = "openssl" 1056 | version = "0.10.71" 1057 | source = "registry+https://github.com/rust-lang/crates.io-index" 1058 | checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" 1059 | dependencies = [ 1060 | "bitflags", 1061 | "cfg-if", 1062 | "foreign-types", 1063 | "libc", 1064 | "once_cell", 1065 | "openssl-macros", 1066 | "openssl-sys", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "openssl-macros" 1071 | version = "0.1.1" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1074 | dependencies = [ 1075 | "proc-macro2", 1076 | "quote", 1077 | "syn", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "openssl-probe" 1082 | version = "0.1.6" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1085 | 1086 | [[package]] 1087 | name = "openssl-sys" 1088 | version = "0.9.106" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" 1091 | dependencies = [ 1092 | "cc", 1093 | "libc", 1094 | "pkg-config", 1095 | "vcpkg", 1096 | ] 1097 | 1098 | [[package]] 1099 | name = "parking_lot" 1100 | version = "0.12.3" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1103 | dependencies = [ 1104 | "lock_api", 1105 | "parking_lot_core", 1106 | ] 1107 | 1108 | [[package]] 1109 | name = "parking_lot_core" 1110 | version = "0.9.10" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1113 | dependencies = [ 1114 | "cfg-if", 1115 | "libc", 1116 | "redox_syscall", 1117 | "smallvec", 1118 | "windows-targets", 1119 | ] 1120 | 1121 | [[package]] 1122 | name = "pem" 1123 | version = "3.0.5" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" 1126 | dependencies = [ 1127 | "base64", 1128 | "serde", 1129 | ] 1130 | 1131 | [[package]] 1132 | name = "percent-encoding" 1133 | version = "2.3.1" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1136 | 1137 | [[package]] 1138 | name = "pin-project" 1139 | version = "1.1.10" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" 1142 | dependencies = [ 1143 | "pin-project-internal", 1144 | ] 1145 | 1146 | [[package]] 1147 | name = "pin-project-internal" 1148 | version = "1.1.10" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" 1151 | dependencies = [ 1152 | "proc-macro2", 1153 | "quote", 1154 | "syn", 1155 | ] 1156 | 1157 | [[package]] 1158 | name = "pin-project-lite" 1159 | version = "0.2.16" 1160 | source = "registry+https://github.com/rust-lang/crates.io-index" 1161 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1162 | 1163 | [[package]] 1164 | name = "pin-utils" 1165 | version = "0.1.0" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1168 | 1169 | [[package]] 1170 | name = "pkg-config" 1171 | version = "0.3.32" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1174 | 1175 | [[package]] 1176 | name = "portable-atomic" 1177 | version = "1.11.0" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" 1180 | 1181 | [[package]] 1182 | name = "portable-atomic-util" 1183 | version = "0.2.4" 1184 | source = "registry+https://github.com/rust-lang/crates.io-index" 1185 | checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" 1186 | dependencies = [ 1187 | "portable-atomic", 1188 | ] 1189 | 1190 | [[package]] 1191 | name = "powerfmt" 1192 | version = "0.2.0" 1193 | source = "registry+https://github.com/rust-lang/crates.io-index" 1194 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1195 | 1196 | [[package]] 1197 | name = "ppv-lite86" 1198 | version = "0.2.21" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1201 | dependencies = [ 1202 | "zerocopy", 1203 | ] 1204 | 1205 | [[package]] 1206 | name = "pr-summarizer" 1207 | version = "0.1.0" 1208 | dependencies = [ 1209 | "anyhow", 1210 | "dotenv", 1211 | "env_logger", 1212 | "itertools", 1213 | "log", 1214 | "octocrab", 1215 | "random-number", 1216 | "regex", 1217 | "reqwest", 1218 | "serde", 1219 | "serde_json", 1220 | "tokio", 1221 | ] 1222 | 1223 | [[package]] 1224 | name = "proc-macro-hack" 1225 | version = "0.5.20+deprecated" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" 1228 | 1229 | [[package]] 1230 | name = "proc-macro2" 1231 | version = "1.0.94" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 1234 | dependencies = [ 1235 | "unicode-ident", 1236 | ] 1237 | 1238 | [[package]] 1239 | name = "quote" 1240 | version = "1.0.39" 1241 | source = "registry+https://github.com/rust-lang/crates.io-index" 1242 | checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" 1243 | dependencies = [ 1244 | "proc-macro2", 1245 | ] 1246 | 1247 | [[package]] 1248 | name = "rand" 1249 | version = "0.8.5" 1250 | source = "registry+https://github.com/rust-lang/crates.io-index" 1251 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1252 | dependencies = [ 1253 | "libc", 1254 | "rand_chacha", 1255 | "rand_core", 1256 | ] 1257 | 1258 | [[package]] 1259 | name = "rand_chacha" 1260 | version = "0.3.1" 1261 | source = "registry+https://github.com/rust-lang/crates.io-index" 1262 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1263 | dependencies = [ 1264 | "ppv-lite86", 1265 | "rand_core", 1266 | ] 1267 | 1268 | [[package]] 1269 | name = "rand_core" 1270 | version = "0.6.4" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1273 | dependencies = [ 1274 | "getrandom 0.2.15", 1275 | ] 1276 | 1277 | [[package]] 1278 | name = "random-number" 1279 | version = "0.1.9" 1280 | source = "registry+https://github.com/rust-lang/crates.io-index" 1281 | checksum = "7fc8cdd49be664772ffc3dbfa743bb8c34b78f9cc6a9f50e56ae878546796067" 1282 | dependencies = [ 1283 | "proc-macro-hack", 1284 | "rand", 1285 | "random-number-macro-impl", 1286 | ] 1287 | 1288 | [[package]] 1289 | name = "random-number-macro-impl" 1290 | version = "0.1.8" 1291 | source = "registry+https://github.com/rust-lang/crates.io-index" 1292 | checksum = "f5135143cb48d14289139e4615bffec0d59b4cbfd4ea2398a3770bd2abfc4aa2" 1293 | dependencies = [ 1294 | "proc-macro-hack", 1295 | "quote", 1296 | "syn", 1297 | ] 1298 | 1299 | [[package]] 1300 | name = "redox_syscall" 1301 | version = "0.5.10" 1302 | source = "registry+https://github.com/rust-lang/crates.io-index" 1303 | checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" 1304 | dependencies = [ 1305 | "bitflags", 1306 | ] 1307 | 1308 | [[package]] 1309 | name = "regex" 1310 | version = "1.11.1" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 1313 | dependencies = [ 1314 | "aho-corasick", 1315 | "memchr", 1316 | "regex-automata", 1317 | "regex-syntax", 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "regex-automata" 1322 | version = "0.4.9" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 1325 | dependencies = [ 1326 | "aho-corasick", 1327 | "memchr", 1328 | "regex-syntax", 1329 | ] 1330 | 1331 | [[package]] 1332 | name = "regex-syntax" 1333 | version = "0.8.5" 1334 | source = "registry+https://github.com/rust-lang/crates.io-index" 1335 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 1336 | 1337 | [[package]] 1338 | name = "reqwest" 1339 | version = "0.12.12" 1340 | source = "registry+https://github.com/rust-lang/crates.io-index" 1341 | checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" 1342 | dependencies = [ 1343 | "base64", 1344 | "bytes", 1345 | "encoding_rs", 1346 | "futures-core", 1347 | "futures-util", 1348 | "h2", 1349 | "http", 1350 | "http-body", 1351 | "http-body-util", 1352 | "hyper", 1353 | "hyper-rustls", 1354 | "hyper-tls", 1355 | "hyper-util", 1356 | "ipnet", 1357 | "js-sys", 1358 | "log", 1359 | "mime", 1360 | "native-tls", 1361 | "once_cell", 1362 | "percent-encoding", 1363 | "pin-project-lite", 1364 | "rustls-pemfile", 1365 | "serde", 1366 | "serde_json", 1367 | "serde_urlencoded", 1368 | "sync_wrapper", 1369 | "system-configuration", 1370 | "tokio", 1371 | "tokio-native-tls", 1372 | "tower", 1373 | "tower-service", 1374 | "url", 1375 | "wasm-bindgen", 1376 | "wasm-bindgen-futures", 1377 | "web-sys", 1378 | "windows-registry", 1379 | ] 1380 | 1381 | [[package]] 1382 | name = "ring" 1383 | version = "0.17.12" 1384 | source = "registry+https://github.com/rust-lang/crates.io-index" 1385 | checksum = "ed9b823fa29b721a59671b41d6b06e66b29e0628e207e8b1c3ceeda701ec928d" 1386 | dependencies = [ 1387 | "cc", 1388 | "cfg-if", 1389 | "getrandom 0.2.15", 1390 | "libc", 1391 | "untrusted", 1392 | "windows-sys 0.52.0", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "rustc-demangle" 1397 | version = "0.1.24" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1400 | 1401 | [[package]] 1402 | name = "rustix" 1403 | version = "0.38.44" 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" 1405 | checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" 1406 | dependencies = [ 1407 | "bitflags", 1408 | "errno", 1409 | "libc", 1410 | "linux-raw-sys", 1411 | "windows-sys 0.59.0", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "rustls" 1416 | version = "0.23.23" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" 1419 | dependencies = [ 1420 | "log", 1421 | "once_cell", 1422 | "ring", 1423 | "rustls-pki-types", 1424 | "rustls-webpki", 1425 | "subtle", 1426 | "zeroize", 1427 | ] 1428 | 1429 | [[package]] 1430 | name = "rustls-native-certs" 1431 | version = "0.8.1" 1432 | source = "registry+https://github.com/rust-lang/crates.io-index" 1433 | checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" 1434 | dependencies = [ 1435 | "openssl-probe", 1436 | "rustls-pki-types", 1437 | "schannel", 1438 | "security-framework 3.2.0", 1439 | ] 1440 | 1441 | [[package]] 1442 | name = "rustls-pemfile" 1443 | version = "2.2.0" 1444 | source = "registry+https://github.com/rust-lang/crates.io-index" 1445 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 1446 | dependencies = [ 1447 | "rustls-pki-types", 1448 | ] 1449 | 1450 | [[package]] 1451 | name = "rustls-pki-types" 1452 | version = "1.11.0" 1453 | source = "registry+https://github.com/rust-lang/crates.io-index" 1454 | checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" 1455 | 1456 | [[package]] 1457 | name = "rustls-webpki" 1458 | version = "0.102.8" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 1461 | dependencies = [ 1462 | "ring", 1463 | "rustls-pki-types", 1464 | "untrusted", 1465 | ] 1466 | 1467 | [[package]] 1468 | name = "rustversion" 1469 | version = "1.0.20" 1470 | source = "registry+https://github.com/rust-lang/crates.io-index" 1471 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 1472 | 1473 | [[package]] 1474 | name = "ryu" 1475 | version = "1.0.20" 1476 | source = "registry+https://github.com/rust-lang/crates.io-index" 1477 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1478 | 1479 | [[package]] 1480 | name = "schannel" 1481 | version = "0.1.27" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 1484 | dependencies = [ 1485 | "windows-sys 0.59.0", 1486 | ] 1487 | 1488 | [[package]] 1489 | name = "scopeguard" 1490 | version = "1.2.0" 1491 | source = "registry+https://github.com/rust-lang/crates.io-index" 1492 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1493 | 1494 | [[package]] 1495 | name = "secrecy" 1496 | version = "0.10.3" 1497 | source = "registry+https://github.com/rust-lang/crates.io-index" 1498 | checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" 1499 | dependencies = [ 1500 | "zeroize", 1501 | ] 1502 | 1503 | [[package]] 1504 | name = "security-framework" 1505 | version = "2.11.1" 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" 1507 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 1508 | dependencies = [ 1509 | "bitflags", 1510 | "core-foundation 0.9.4", 1511 | "core-foundation-sys", 1512 | "libc", 1513 | "security-framework-sys", 1514 | ] 1515 | 1516 | [[package]] 1517 | name = "security-framework" 1518 | version = "3.2.0" 1519 | source = "registry+https://github.com/rust-lang/crates.io-index" 1520 | checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" 1521 | dependencies = [ 1522 | "bitflags", 1523 | "core-foundation 0.10.0", 1524 | "core-foundation-sys", 1525 | "libc", 1526 | "security-framework-sys", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "security-framework-sys" 1531 | version = "2.14.0" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 1534 | dependencies = [ 1535 | "core-foundation-sys", 1536 | "libc", 1537 | ] 1538 | 1539 | [[package]] 1540 | name = "serde" 1541 | version = "1.0.219" 1542 | source = "registry+https://github.com/rust-lang/crates.io-index" 1543 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 1544 | dependencies = [ 1545 | "serde_derive", 1546 | ] 1547 | 1548 | [[package]] 1549 | name = "serde_derive" 1550 | version = "1.0.219" 1551 | source = "registry+https://github.com/rust-lang/crates.io-index" 1552 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 1553 | dependencies = [ 1554 | "proc-macro2", 1555 | "quote", 1556 | "syn", 1557 | ] 1558 | 1559 | [[package]] 1560 | name = "serde_json" 1561 | version = "1.0.140" 1562 | source = "registry+https://github.com/rust-lang/crates.io-index" 1563 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 1564 | dependencies = [ 1565 | "itoa", 1566 | "memchr", 1567 | "ryu", 1568 | "serde", 1569 | ] 1570 | 1571 | [[package]] 1572 | name = "serde_path_to_error" 1573 | version = "0.1.17" 1574 | source = "registry+https://github.com/rust-lang/crates.io-index" 1575 | checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" 1576 | dependencies = [ 1577 | "itoa", 1578 | "serde", 1579 | ] 1580 | 1581 | [[package]] 1582 | name = "serde_urlencoded" 1583 | version = "0.7.1" 1584 | source = "registry+https://github.com/rust-lang/crates.io-index" 1585 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1586 | dependencies = [ 1587 | "form_urlencoded", 1588 | "itoa", 1589 | "ryu", 1590 | "serde", 1591 | ] 1592 | 1593 | [[package]] 1594 | name = "shlex" 1595 | version = "1.3.0" 1596 | source = "registry+https://github.com/rust-lang/crates.io-index" 1597 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1598 | 1599 | [[package]] 1600 | name = "signal-hook-registry" 1601 | version = "1.4.2" 1602 | source = "registry+https://github.com/rust-lang/crates.io-index" 1603 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 1604 | dependencies = [ 1605 | "libc", 1606 | ] 1607 | 1608 | [[package]] 1609 | name = "simple_asn1" 1610 | version = "0.6.3" 1611 | source = "registry+https://github.com/rust-lang/crates.io-index" 1612 | checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" 1613 | dependencies = [ 1614 | "num-bigint", 1615 | "num-traits", 1616 | "thiserror", 1617 | "time", 1618 | ] 1619 | 1620 | [[package]] 1621 | name = "slab" 1622 | version = "0.4.9" 1623 | source = "registry+https://github.com/rust-lang/crates.io-index" 1624 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1625 | dependencies = [ 1626 | "autocfg", 1627 | ] 1628 | 1629 | [[package]] 1630 | name = "smallvec" 1631 | version = "1.14.0" 1632 | source = "registry+https://github.com/rust-lang/crates.io-index" 1633 | checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" 1634 | 1635 | [[package]] 1636 | name = "snafu" 1637 | version = "0.8.5" 1638 | source = "registry+https://github.com/rust-lang/crates.io-index" 1639 | checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" 1640 | dependencies = [ 1641 | "snafu-derive", 1642 | ] 1643 | 1644 | [[package]] 1645 | name = "snafu-derive" 1646 | version = "0.8.5" 1647 | source = "registry+https://github.com/rust-lang/crates.io-index" 1648 | checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917" 1649 | dependencies = [ 1650 | "heck", 1651 | "proc-macro2", 1652 | "quote", 1653 | "syn", 1654 | ] 1655 | 1656 | [[package]] 1657 | name = "socket2" 1658 | version = "0.5.8" 1659 | source = "registry+https://github.com/rust-lang/crates.io-index" 1660 | checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" 1661 | dependencies = [ 1662 | "libc", 1663 | "windows-sys 0.52.0", 1664 | ] 1665 | 1666 | [[package]] 1667 | name = "stable_deref_trait" 1668 | version = "1.2.0" 1669 | source = "registry+https://github.com/rust-lang/crates.io-index" 1670 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1671 | 1672 | [[package]] 1673 | name = "subtle" 1674 | version = "2.6.1" 1675 | source = "registry+https://github.com/rust-lang/crates.io-index" 1676 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1677 | 1678 | [[package]] 1679 | name = "syn" 1680 | version = "2.0.99" 1681 | source = "registry+https://github.com/rust-lang/crates.io-index" 1682 | checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" 1683 | dependencies = [ 1684 | "proc-macro2", 1685 | "quote", 1686 | "unicode-ident", 1687 | ] 1688 | 1689 | [[package]] 1690 | name = "sync_wrapper" 1691 | version = "1.0.2" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1694 | dependencies = [ 1695 | "futures-core", 1696 | ] 1697 | 1698 | [[package]] 1699 | name = "synstructure" 1700 | version = "0.13.1" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 1703 | dependencies = [ 1704 | "proc-macro2", 1705 | "quote", 1706 | "syn", 1707 | ] 1708 | 1709 | [[package]] 1710 | name = "system-configuration" 1711 | version = "0.6.1" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 1714 | dependencies = [ 1715 | "bitflags", 1716 | "core-foundation 0.9.4", 1717 | "system-configuration-sys", 1718 | ] 1719 | 1720 | [[package]] 1721 | name = "system-configuration-sys" 1722 | version = "0.6.0" 1723 | source = "registry+https://github.com/rust-lang/crates.io-index" 1724 | checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 1725 | dependencies = [ 1726 | "core-foundation-sys", 1727 | "libc", 1728 | ] 1729 | 1730 | [[package]] 1731 | name = "tempfile" 1732 | version = "3.17.1" 1733 | source = "registry+https://github.com/rust-lang/crates.io-index" 1734 | checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" 1735 | dependencies = [ 1736 | "cfg-if", 1737 | "fastrand", 1738 | "getrandom 0.3.1", 1739 | "once_cell", 1740 | "rustix", 1741 | "windows-sys 0.59.0", 1742 | ] 1743 | 1744 | [[package]] 1745 | name = "thiserror" 1746 | version = "2.0.12" 1747 | source = "registry+https://github.com/rust-lang/crates.io-index" 1748 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 1749 | dependencies = [ 1750 | "thiserror-impl", 1751 | ] 1752 | 1753 | [[package]] 1754 | name = "thiserror-impl" 1755 | version = "2.0.12" 1756 | source = "registry+https://github.com/rust-lang/crates.io-index" 1757 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 1758 | dependencies = [ 1759 | "proc-macro2", 1760 | "quote", 1761 | "syn", 1762 | ] 1763 | 1764 | [[package]] 1765 | name = "time" 1766 | version = "0.3.39" 1767 | source = "registry+https://github.com/rust-lang/crates.io-index" 1768 | checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" 1769 | dependencies = [ 1770 | "deranged", 1771 | "itoa", 1772 | "num-conv", 1773 | "powerfmt", 1774 | "serde", 1775 | "time-core", 1776 | "time-macros", 1777 | ] 1778 | 1779 | [[package]] 1780 | name = "time-core" 1781 | version = "0.1.3" 1782 | source = "registry+https://github.com/rust-lang/crates.io-index" 1783 | checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" 1784 | 1785 | [[package]] 1786 | name = "time-macros" 1787 | version = "0.2.20" 1788 | source = "registry+https://github.com/rust-lang/crates.io-index" 1789 | checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" 1790 | dependencies = [ 1791 | "num-conv", 1792 | "time-core", 1793 | ] 1794 | 1795 | [[package]] 1796 | name = "tinystr" 1797 | version = "0.7.6" 1798 | source = "registry+https://github.com/rust-lang/crates.io-index" 1799 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 1800 | dependencies = [ 1801 | "displaydoc", 1802 | "zerovec", 1803 | ] 1804 | 1805 | [[package]] 1806 | name = "tokio" 1807 | version = "1.44.0" 1808 | source = "registry+https://github.com/rust-lang/crates.io-index" 1809 | checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" 1810 | dependencies = [ 1811 | "backtrace", 1812 | "bytes", 1813 | "libc", 1814 | "mio", 1815 | "parking_lot", 1816 | "pin-project-lite", 1817 | "signal-hook-registry", 1818 | "socket2", 1819 | "tokio-macros", 1820 | "windows-sys 0.52.0", 1821 | ] 1822 | 1823 | [[package]] 1824 | name = "tokio-macros" 1825 | version = "2.5.0" 1826 | source = "registry+https://github.com/rust-lang/crates.io-index" 1827 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 1828 | dependencies = [ 1829 | "proc-macro2", 1830 | "quote", 1831 | "syn", 1832 | ] 1833 | 1834 | [[package]] 1835 | name = "tokio-native-tls" 1836 | version = "0.3.1" 1837 | source = "registry+https://github.com/rust-lang/crates.io-index" 1838 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1839 | dependencies = [ 1840 | "native-tls", 1841 | "tokio", 1842 | ] 1843 | 1844 | [[package]] 1845 | name = "tokio-rustls" 1846 | version = "0.26.2" 1847 | source = "registry+https://github.com/rust-lang/crates.io-index" 1848 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 1849 | dependencies = [ 1850 | "rustls", 1851 | "tokio", 1852 | ] 1853 | 1854 | [[package]] 1855 | name = "tokio-util" 1856 | version = "0.7.13" 1857 | source = "registry+https://github.com/rust-lang/crates.io-index" 1858 | checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" 1859 | dependencies = [ 1860 | "bytes", 1861 | "futures-core", 1862 | "futures-sink", 1863 | "pin-project-lite", 1864 | "tokio", 1865 | ] 1866 | 1867 | [[package]] 1868 | name = "tower" 1869 | version = "0.5.2" 1870 | source = "registry+https://github.com/rust-lang/crates.io-index" 1871 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 1872 | dependencies = [ 1873 | "futures-core", 1874 | "futures-util", 1875 | "pin-project-lite", 1876 | "sync_wrapper", 1877 | "tokio", 1878 | "tokio-util", 1879 | "tower-layer", 1880 | "tower-service", 1881 | "tracing", 1882 | ] 1883 | 1884 | [[package]] 1885 | name = "tower-http" 1886 | version = "0.6.2" 1887 | source = "registry+https://github.com/rust-lang/crates.io-index" 1888 | checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" 1889 | dependencies = [ 1890 | "bitflags", 1891 | "bytes", 1892 | "futures-util", 1893 | "http", 1894 | "http-body", 1895 | "iri-string", 1896 | "pin-project-lite", 1897 | "tower", 1898 | "tower-layer", 1899 | "tower-service", 1900 | "tracing", 1901 | ] 1902 | 1903 | [[package]] 1904 | name = "tower-layer" 1905 | version = "0.3.3" 1906 | source = "registry+https://github.com/rust-lang/crates.io-index" 1907 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1908 | 1909 | [[package]] 1910 | name = "tower-service" 1911 | version = "0.3.3" 1912 | source = "registry+https://github.com/rust-lang/crates.io-index" 1913 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1914 | 1915 | [[package]] 1916 | name = "tracing" 1917 | version = "0.1.41" 1918 | source = "registry+https://github.com/rust-lang/crates.io-index" 1919 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1920 | dependencies = [ 1921 | "log", 1922 | "pin-project-lite", 1923 | "tracing-attributes", 1924 | "tracing-core", 1925 | ] 1926 | 1927 | [[package]] 1928 | name = "tracing-attributes" 1929 | version = "0.1.28" 1930 | source = "registry+https://github.com/rust-lang/crates.io-index" 1931 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 1932 | dependencies = [ 1933 | "proc-macro2", 1934 | "quote", 1935 | "syn", 1936 | ] 1937 | 1938 | [[package]] 1939 | name = "tracing-core" 1940 | version = "0.1.33" 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" 1942 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 1943 | dependencies = [ 1944 | "once_cell", 1945 | ] 1946 | 1947 | [[package]] 1948 | name = "try-lock" 1949 | version = "0.2.5" 1950 | source = "registry+https://github.com/rust-lang/crates.io-index" 1951 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1952 | 1953 | [[package]] 1954 | name = "unicode-ident" 1955 | version = "1.0.18" 1956 | source = "registry+https://github.com/rust-lang/crates.io-index" 1957 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1958 | 1959 | [[package]] 1960 | name = "untrusted" 1961 | version = "0.9.0" 1962 | source = "registry+https://github.com/rust-lang/crates.io-index" 1963 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 1964 | 1965 | [[package]] 1966 | name = "url" 1967 | version = "2.5.4" 1968 | source = "registry+https://github.com/rust-lang/crates.io-index" 1969 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 1970 | dependencies = [ 1971 | "form_urlencoded", 1972 | "idna", 1973 | "percent-encoding", 1974 | "serde", 1975 | ] 1976 | 1977 | [[package]] 1978 | name = "utf16_iter" 1979 | version = "1.0.5" 1980 | source = "registry+https://github.com/rust-lang/crates.io-index" 1981 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 1982 | 1983 | [[package]] 1984 | name = "utf8_iter" 1985 | version = "1.0.4" 1986 | source = "registry+https://github.com/rust-lang/crates.io-index" 1987 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 1988 | 1989 | [[package]] 1990 | name = "utf8parse" 1991 | version = "0.2.2" 1992 | source = "registry+https://github.com/rust-lang/crates.io-index" 1993 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 1994 | 1995 | [[package]] 1996 | name = "vcpkg" 1997 | version = "0.2.15" 1998 | source = "registry+https://github.com/rust-lang/crates.io-index" 1999 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2000 | 2001 | [[package]] 2002 | name = "want" 2003 | version = "0.3.1" 2004 | source = "registry+https://github.com/rust-lang/crates.io-index" 2005 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2006 | dependencies = [ 2007 | "try-lock", 2008 | ] 2009 | 2010 | [[package]] 2011 | name = "wasi" 2012 | version = "0.11.0+wasi-snapshot-preview1" 2013 | source = "registry+https://github.com/rust-lang/crates.io-index" 2014 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2015 | 2016 | [[package]] 2017 | name = "wasi" 2018 | version = "0.13.3+wasi-0.2.2" 2019 | source = "registry+https://github.com/rust-lang/crates.io-index" 2020 | checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" 2021 | dependencies = [ 2022 | "wit-bindgen-rt", 2023 | ] 2024 | 2025 | [[package]] 2026 | name = "wasm-bindgen" 2027 | version = "0.2.100" 2028 | source = "registry+https://github.com/rust-lang/crates.io-index" 2029 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 2030 | dependencies = [ 2031 | "cfg-if", 2032 | "once_cell", 2033 | "rustversion", 2034 | "wasm-bindgen-macro", 2035 | ] 2036 | 2037 | [[package]] 2038 | name = "wasm-bindgen-backend" 2039 | version = "0.2.100" 2040 | source = "registry+https://github.com/rust-lang/crates.io-index" 2041 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 2042 | dependencies = [ 2043 | "bumpalo", 2044 | "log", 2045 | "proc-macro2", 2046 | "quote", 2047 | "syn", 2048 | "wasm-bindgen-shared", 2049 | ] 2050 | 2051 | [[package]] 2052 | name = "wasm-bindgen-futures" 2053 | version = "0.4.50" 2054 | source = "registry+https://github.com/rust-lang/crates.io-index" 2055 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 2056 | dependencies = [ 2057 | "cfg-if", 2058 | "js-sys", 2059 | "once_cell", 2060 | "wasm-bindgen", 2061 | "web-sys", 2062 | ] 2063 | 2064 | [[package]] 2065 | name = "wasm-bindgen-macro" 2066 | version = "0.2.100" 2067 | source = "registry+https://github.com/rust-lang/crates.io-index" 2068 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 2069 | dependencies = [ 2070 | "quote", 2071 | "wasm-bindgen-macro-support", 2072 | ] 2073 | 2074 | [[package]] 2075 | name = "wasm-bindgen-macro-support" 2076 | version = "0.2.100" 2077 | source = "registry+https://github.com/rust-lang/crates.io-index" 2078 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 2079 | dependencies = [ 2080 | "proc-macro2", 2081 | "quote", 2082 | "syn", 2083 | "wasm-bindgen-backend", 2084 | "wasm-bindgen-shared", 2085 | ] 2086 | 2087 | [[package]] 2088 | name = "wasm-bindgen-shared" 2089 | version = "0.2.100" 2090 | source = "registry+https://github.com/rust-lang/crates.io-index" 2091 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 2092 | dependencies = [ 2093 | "unicode-ident", 2094 | ] 2095 | 2096 | [[package]] 2097 | name = "web-sys" 2098 | version = "0.3.77" 2099 | source = "registry+https://github.com/rust-lang/crates.io-index" 2100 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 2101 | dependencies = [ 2102 | "js-sys", 2103 | "wasm-bindgen", 2104 | ] 2105 | 2106 | [[package]] 2107 | name = "web-time" 2108 | version = "1.1.0" 2109 | source = "registry+https://github.com/rust-lang/crates.io-index" 2110 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2111 | dependencies = [ 2112 | "js-sys", 2113 | "serde", 2114 | "wasm-bindgen", 2115 | ] 2116 | 2117 | [[package]] 2118 | name = "windows-core" 2119 | version = "0.52.0" 2120 | source = "registry+https://github.com/rust-lang/crates.io-index" 2121 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 2122 | dependencies = [ 2123 | "windows-targets", 2124 | ] 2125 | 2126 | [[package]] 2127 | name = "windows-link" 2128 | version = "0.1.0" 2129 | source = "registry+https://github.com/rust-lang/crates.io-index" 2130 | checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" 2131 | 2132 | [[package]] 2133 | name = "windows-registry" 2134 | version = "0.2.0" 2135 | source = "registry+https://github.com/rust-lang/crates.io-index" 2136 | checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" 2137 | dependencies = [ 2138 | "windows-result", 2139 | "windows-strings", 2140 | "windows-targets", 2141 | ] 2142 | 2143 | [[package]] 2144 | name = "windows-result" 2145 | version = "0.2.0" 2146 | source = "registry+https://github.com/rust-lang/crates.io-index" 2147 | checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" 2148 | dependencies = [ 2149 | "windows-targets", 2150 | ] 2151 | 2152 | [[package]] 2153 | name = "windows-strings" 2154 | version = "0.1.0" 2155 | source = "registry+https://github.com/rust-lang/crates.io-index" 2156 | checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" 2157 | dependencies = [ 2158 | "windows-result", 2159 | "windows-targets", 2160 | ] 2161 | 2162 | [[package]] 2163 | name = "windows-sys" 2164 | version = "0.52.0" 2165 | source = "registry+https://github.com/rust-lang/crates.io-index" 2166 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2167 | dependencies = [ 2168 | "windows-targets", 2169 | ] 2170 | 2171 | [[package]] 2172 | name = "windows-sys" 2173 | version = "0.59.0" 2174 | source = "registry+https://github.com/rust-lang/crates.io-index" 2175 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2176 | dependencies = [ 2177 | "windows-targets", 2178 | ] 2179 | 2180 | [[package]] 2181 | name = "windows-targets" 2182 | version = "0.52.6" 2183 | source = "registry+https://github.com/rust-lang/crates.io-index" 2184 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2185 | dependencies = [ 2186 | "windows_aarch64_gnullvm", 2187 | "windows_aarch64_msvc", 2188 | "windows_i686_gnu", 2189 | "windows_i686_gnullvm", 2190 | "windows_i686_msvc", 2191 | "windows_x86_64_gnu", 2192 | "windows_x86_64_gnullvm", 2193 | "windows_x86_64_msvc", 2194 | ] 2195 | 2196 | [[package]] 2197 | name = "windows_aarch64_gnullvm" 2198 | version = "0.52.6" 2199 | source = "registry+https://github.com/rust-lang/crates.io-index" 2200 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2201 | 2202 | [[package]] 2203 | name = "windows_aarch64_msvc" 2204 | version = "0.52.6" 2205 | source = "registry+https://github.com/rust-lang/crates.io-index" 2206 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2207 | 2208 | [[package]] 2209 | name = "windows_i686_gnu" 2210 | version = "0.52.6" 2211 | source = "registry+https://github.com/rust-lang/crates.io-index" 2212 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2213 | 2214 | [[package]] 2215 | name = "windows_i686_gnullvm" 2216 | version = "0.52.6" 2217 | source = "registry+https://github.com/rust-lang/crates.io-index" 2218 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2219 | 2220 | [[package]] 2221 | name = "windows_i686_msvc" 2222 | version = "0.52.6" 2223 | source = "registry+https://github.com/rust-lang/crates.io-index" 2224 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2225 | 2226 | [[package]] 2227 | name = "windows_x86_64_gnu" 2228 | version = "0.52.6" 2229 | source = "registry+https://github.com/rust-lang/crates.io-index" 2230 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2231 | 2232 | [[package]] 2233 | name = "windows_x86_64_gnullvm" 2234 | version = "0.52.6" 2235 | source = "registry+https://github.com/rust-lang/crates.io-index" 2236 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2237 | 2238 | [[package]] 2239 | name = "windows_x86_64_msvc" 2240 | version = "0.52.6" 2241 | source = "registry+https://github.com/rust-lang/crates.io-index" 2242 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2243 | 2244 | [[package]] 2245 | name = "wit-bindgen-rt" 2246 | version = "0.33.0" 2247 | source = "registry+https://github.com/rust-lang/crates.io-index" 2248 | checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" 2249 | dependencies = [ 2250 | "bitflags", 2251 | ] 2252 | 2253 | [[package]] 2254 | name = "write16" 2255 | version = "1.0.0" 2256 | source = "registry+https://github.com/rust-lang/crates.io-index" 2257 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 2258 | 2259 | [[package]] 2260 | name = "writeable" 2261 | version = "0.5.5" 2262 | source = "registry+https://github.com/rust-lang/crates.io-index" 2263 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 2264 | 2265 | [[package]] 2266 | name = "yoke" 2267 | version = "0.7.5" 2268 | source = "registry+https://github.com/rust-lang/crates.io-index" 2269 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 2270 | dependencies = [ 2271 | "serde", 2272 | "stable_deref_trait", 2273 | "yoke-derive", 2274 | "zerofrom", 2275 | ] 2276 | 2277 | [[package]] 2278 | name = "yoke-derive" 2279 | version = "0.7.5" 2280 | source = "registry+https://github.com/rust-lang/crates.io-index" 2281 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 2282 | dependencies = [ 2283 | "proc-macro2", 2284 | "quote", 2285 | "syn", 2286 | "synstructure", 2287 | ] 2288 | 2289 | [[package]] 2290 | name = "zerocopy" 2291 | version = "0.8.23" 2292 | source = "registry+https://github.com/rust-lang/crates.io-index" 2293 | checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" 2294 | dependencies = [ 2295 | "zerocopy-derive", 2296 | ] 2297 | 2298 | [[package]] 2299 | name = "zerocopy-derive" 2300 | version = "0.8.23" 2301 | source = "registry+https://github.com/rust-lang/crates.io-index" 2302 | checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" 2303 | dependencies = [ 2304 | "proc-macro2", 2305 | "quote", 2306 | "syn", 2307 | ] 2308 | 2309 | [[package]] 2310 | name = "zerofrom" 2311 | version = "0.1.6" 2312 | source = "registry+https://github.com/rust-lang/crates.io-index" 2313 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 2314 | dependencies = [ 2315 | "zerofrom-derive", 2316 | ] 2317 | 2318 | [[package]] 2319 | name = "zerofrom-derive" 2320 | version = "0.1.6" 2321 | source = "registry+https://github.com/rust-lang/crates.io-index" 2322 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 2323 | dependencies = [ 2324 | "proc-macro2", 2325 | "quote", 2326 | "syn", 2327 | "synstructure", 2328 | ] 2329 | 2330 | [[package]] 2331 | name = "zeroize" 2332 | version = "1.8.1" 2333 | source = "registry+https://github.com/rust-lang/crates.io-index" 2334 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 2335 | 2336 | [[package]] 2337 | name = "zerovec" 2338 | version = "0.10.4" 2339 | source = "registry+https://github.com/rust-lang/crates.io-index" 2340 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 2341 | dependencies = [ 2342 | "yoke", 2343 | "zerofrom", 2344 | "zerovec-derive", 2345 | ] 2346 | 2347 | [[package]] 2348 | name = "zerovec-derive" 2349 | version = "0.10.3" 2350 | source = "registry+https://github.com/rust-lang/crates.io-index" 2351 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 2352 | dependencies = [ 2353 | "proc-macro2", 2354 | "quote", 2355 | "syn", 2356 | ] 2357 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pr-summarizer" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Noel Bansikah tandapnoelbansikah@gmail.com"] 6 | description = "A GitHub Action that summarizes PRs and adds jokes" 7 | 8 | [dependencies] 9 | octocrab = "0.43.0" # GitHub API client 10 | tokio = { version = "1.44.0", features = ["full"] } # Async runtime 11 | serde = { version = "1.0.219", features = ["derive"] } # Serialization 12 | serde_json = "1.0" # JSON handling 13 | reqwest = { version = "0.12.11", features = ["json"] } # HTTP client 14 | anyhow = "1.0" # Error handling 15 | log = "0.4" # Logging 16 | env_logger = "0.11.7" # Logger implementation 17 | regex = "1.10.1" # Regular expressions 18 | itertools = "0.14.0" # Iterator utilities 19 | dotenv = "0.15" # Environment variable handling 20 | random-number = "0.1.9" 21 | 22 | [profile.release] 23 | opt-level = 3 # Optimize for speed 24 | lto = true # Link-time optimization 25 | codegen-units = 1 # More optimization 26 | panic = "abort" # Abort on panic in release mode 27 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.77-slim AS builder 2 | WORKDIR /usr/src/app 3 | COPY . . 4 | RUN cargo build --release 5 | 6 | FROM debian:12.10-slim 7 | COPY --from=builder /usr/src/app/target/release/pr-summarizer /usr/local/bin/pr-summarizer 8 | ENTRYPOINT ["pr-summarizer"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Noel Bansikah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PR Summarizer with Jokes 2 | 3 | ![GitHub Test Actions Status](https://github.com/bansikah22/pr-summarizer/actions/workflows/test.yml/badge.svg) 4 | ![GitHub Test Actions Status](https://github.com/bansikah22/pr-summarizer/actions/workflows/release.yml/badge.svg) 5 | ![GitHub Issues](https://img.shields.io/github/issues/bansikah22/pr-summarizer?color=red) 6 | ![Open Source](https://img.shields.io/github/license/bansikah22/pr-summarizer?color=green) 7 | 8 | A GitHub Action that automatically summarizes pull requests and adds a random programming joke to make code reviews more enjoyable. 9 | 10 | ## Features 11 | 12 | - 📝 **PR Change Analysis**: Detects modified, added, and deleted files 13 | - 📊 **Summary Generation**: Converts PR changes into short, meaningful descriptions 14 | - 💬 **GitHub Commenting**: Posts the summary as a comment on the PR 15 | - 😄 **Random Jokes**: Fetches and appends a programming joke to the comment 16 | - 🔄 **External Repository Support**: Can be used across multiple GitHub repositories 17 | 18 | ## Example Output 19 | 20 | ``` 21 | 🚀 PR Summary 22 | 📝 Changes Overview 23 | ✨ Implement user authentication system 24 | ✅ Added JWT token generation and validation 25 | ✅ Created user registration endpoint 26 | 🧪 Added tests for auth endpoints 27 | 📚 Updated API documentation 28 | 📂 Affected Files 29 | 30 | 🟢 [+] src/auth/jwt.rs 31 | 🟢 [+] src/auth/middleware.rs 32 | 🔵 [M] src/routes/users.rs 33 | 🔵 [M] src/models/user.rs 34 | 🟢 [+] tests/auth_tests.rs 35 | 🔵 [M] README.md 36 | 37 | 😄 Code Humor 38 | Why do programmers prefer dark mode? Because light attracts bugs! 🤓 39 | 40 | This summary was automatically generated by PR Summarizer ⚡ 41 | ``` 42 | 43 | ## Usage 44 | 45 | Add this to your repository's `.github/workflows/pr-summary.yml`: 46 | 47 | ```yaml 48 | name: PR Summarizer 49 | 50 | on: 51 | pull_request: 52 | types: [opened, synchronize, reopened] 53 | 54 | permissions: 55 | pull-requests: write # Required to comment on PRs 56 | issues: write # Required for PR comments via issues API 57 | 58 | jobs: 59 | summarize: 60 | runs-on: ubuntu-latest 61 | steps: 62 | - name: Checkout repository 63 | uses: actions/checkout@v4 64 | with: 65 | fetch-depth: 0 # Ensures full history for diff analysis 66 | 67 | - name: Run PR Summarizer 68 | uses: bansikah22/pr-summarizer@v1.0.0 # Uses the lastest actions tag 69 | with: 70 | github_token: ${{ secrets.GITHUB_TOKEN }} 71 | ``` 72 | 73 | You can also visit test repositories [Test PR Summarizer](https://github.com/bansikah22/test-pr-summarizer) so see how it works on external repositories. 74 | 75 | ## How It Works 76 | 77 | 1. When a pull request is opened or updated, the action is triggered 78 | 2. It analyzes the changes made in the PR 79 | 3. It generates a concise summary of the changes 80 | 4. It fetches a programming joke from several APIs 81 | 5. It posts a comment on the PR with the summary and joke 82 | 83 | ## Development 84 | 85 | ### Prerequisites 86 | 87 | - Rust 1.83.+ 88 | - Cargo 89 | 90 | ### Building 91 | 92 | ```bash 93 | cargo build --release 94 | ``` 95 | You can alos make use of the [ci-local.sh](./ci-local.sh) file to simulate ci locally 96 | 97 | ## 🤝 Contributors 98 | 99 | We appreciate the efforts of all contributors who help improve this project. 100 | 101 | | Contributor | Role | 102 | |-------------------|-----------------------------| 103 | | **Noel Bansikah** | Author & Maintainer | 104 | | **Synk** | Maintainer | 105 | | **Christian Yamele** | Rust Developer | 106 | 107 | Contributions are welcomed! 🎉 Feel free to submit issues, feature requests, or pull requests to help enhance this project. 108 | 109 | ## 📜 License 110 | 111 | [MIT](./LICENSE) License 112 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'PR Summarizer with Jokes' 2 | description: 'Automatically summarizes pull requests and adds a joke for fun' 3 | author: 'Noel Bansikah' 4 | branding: 5 | icon: 'message-square' 6 | color: 'purple' 7 | inputs: 8 | github_token: 9 | description: 'GitHub token for API access' 10 | required: true 11 | runs: 12 | using: 'composite' 13 | steps: 14 | - name: Download Precompiled Binary 15 | shell: bash 16 | run: | 17 | # Get the action version from the reference 18 | ACTION_VERSION="${{ github.action_ref }}" 19 | 20 | # Remove 'v' prefix if present 21 | VERSION="${ACTION_VERSION#v}" 22 | 23 | # As fallback, you can hardcode the latest version 24 | if [[ -z "$VERSION" ]]; then 25 | VERSION="1.0.0" 26 | echo "No version detected, using default: $VERSION" 27 | else 28 | echo "Using version: $VERSION" 29 | fi 30 | 31 | echo "Downloading from: https://github.com/bansikah22/pr-summarizer/releases/download/v${VERSION}/pr-summarizer-v${VERSION}.tar.gz" 32 | 33 | # Download with better error handling 34 | if ! curl -L -f -o pr-summarizer.tar.gz \ 35 | "https://github.com/bansikah22/pr-summarizer/releases/download/v${VERSION}/pr-summarizer-v${VERSION}.tar.gz"; then 36 | echo "Download failed! Check if release exists at: https://github.com/bansikah22/pr-summarizer/releases/tag/v${VERSION}" 37 | exit 1 38 | fi 39 | 40 | # Debug info 41 | ls -la pr-summarizer.tar.gz 42 | file pr-summarizer.tar.gz 43 | 44 | # Extract with error handling 45 | if ! tar -xzf pr-summarizer.tar.gz; then 46 | echo "Failed to extract archive. It may be corrupted or not a valid gzip file." 47 | exit 1 48 | fi 49 | 50 | chmod +x pr-summarizer 51 | env: 52 | GITHUB_TOKEN: ${{ inputs.github_token }} 53 | - name: Run PR Summarizer 54 | shell: bash 55 | run: ./pr-summarizer 56 | env: 57 | GITHUB_TOKEN: ${{ inputs.github_token }} 58 | GITHUB_REPOSITORY: ${{ github.repository }} 59 | GITHUB_EVENT_PATH: ${{ github.event_path }} -------------------------------------------------------------------------------- /ci-local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e # Exit immediately if a command exits with a non-zero status 4 | set -o pipefail # Exit if any command in a pipeline fails 5 | 6 | echo "🚀 Starting local CI simulation..." 7 | 8 | # Set environment variables 9 | export CARGO_TERM_COLOR=always 10 | export RUSTFLAGS="-D warnings" 11 | 12 | # Step 1: Check formatting 13 | echo "🔍 Checking code formatting..." 14 | cargo fmt --all -- --check 15 | 16 | # Step 2: Build the project 17 | echo "🔨 Building the project..." 18 | cargo build --workspace --all-features 19 | 20 | # Step 3: Run tests 21 | echo "🧪 Checking for tests..." 22 | if cargo test --no-run --workspace --all-targets --all-features 2>/dev/null | grep -q "running"; then 23 | echo "🧪 Running tests..." 24 | cargo nextest run --workspace --all-targets --all-features --no-fail-fast 25 | else 26 | echo "⚠️ No tests found, skipping test step..." 27 | fi 28 | 29 | # Step 4: Run linter checks 30 | echo "🔍 Running linter checks..." 31 | cargo clippy --workspace --all-targets --all-features -- -D warnings 32 | 33 | # Step 5: Check API documentation 34 | echo "📚 Checking API documentation..." 35 | cargo doc --workspace --all-features --no-deps 36 | 37 | echo "✅ Local CI simulation completed successfully!" -------------------------------------------------------------------------------- /docs/USAGE.md: -------------------------------------------------------------------------------- 1 | # Using the `ci-local.sh` Script Locally 2 | 3 | The `ci-local.sh` script simulates the CI pipeline locally. It performs the following steps: 4 | 1. Checks code formatting. 5 | 2. Builds the project. 6 | 3. Runs tests (if available). 7 | 4. Runs linter checks. 8 | 5. Generates API documentation. 9 | 10 | --- 11 | 12 | ## Prerequisites 13 | 14 | Ensure the following tools are installed: 15 | - **Rust toolchain**: Install via [rustup](https://rustup.rs/). 16 | - **Cargo tools**: 17 | - `cargo fmt` 18 | - `cargo clippy` 19 | - `cargo nextest` 20 | - **Bash shell**: Required to run the script. 21 | 22 | --- 23 | 24 | ## Steps to Run 25 | 26 | 1. **Navigate to the Project Directory**: 27 | ```bash 28 | cd /path/to/pr-summarizer 29 | ``` 30 | 2. Make the Script Executable: 31 | ```bash 32 | chmod +x ci-local.sh 33 | ``` 34 | 3. Run the Script: 35 | ```bash 36 | ./ci-local.sh 37 | ``` -------------------------------------------------------------------------------- /docs/architecture/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iinsys/pr-summarizer/4c0933b4833d7ff7b84268e368de4c1320337ec3/docs/architecture/flow.png -------------------------------------------------------------------------------- /docs/release/release-process.md: -------------------------------------------------------------------------------- 1 | ### Tag a Release 2 | - Decide on a version (e.g., v1.0.0). 3 | - Create and push a tag: 4 | ```bash 5 | git tag v1.0.0 # put release version 6 | git push origin v1.0.0 7 | ``` 8 | This triggers the Release workflow because it matches the v* pattern. -------------------------------------------------------------------------------- /docs/release/v1.md: -------------------------------------------------------------------------------- 1 | ## 📦 Dependencies 2 | 3 | | Dependency | Version | Purpose | 4 | |-------------|---------|--------------------------------| 5 | | `octocrab` | 0.42.0 | GitHub API client | 6 | | `tokio` | 1 | Async runtime | 7 | | `serde` | 1.0 | Serialization | 8 | | `serde_json`| 1.0 | JSON handling | 9 | | `reqwest` | 0.12.11 | HTTP client | 10 | | `anyhow` | 1.0 | Error handling | 11 | | `log` | 0.4 | Logging | 12 | | `env_logger`| 0.11.1 | Logger implementation | 13 | | `regex` | 1.10.1 | Regular expressions | 14 | | `itertools` | 0.7.7 | Iterator utilities | 15 | | `dotenv` | 0.15 | Environment variable handling | 16 | -------------------------------------------------------------------------------- /src/github.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use anyhow::{Context, Result}; 4 | use octocrab::Octocrab; 5 | 6 | #[allow(dead_code)] 7 | pub struct PrInfo { 8 | pub title: String, 9 | pub description: String, 10 | pub base_branch: String, 11 | pub head_branch: String, 12 | pub author: String, 13 | pub changed_files: Vec, 14 | } 15 | 16 | #[allow(dead_code)] 17 | pub struct ChangedFile { 18 | pub filename: String, 19 | pub status: FileStatus, 20 | pub additions: i32, 21 | pub deletions: i32, 22 | } 23 | 24 | #[derive(Debug)] 25 | pub enum FileStatus { 26 | Added, 27 | Modified, 28 | Removed, 29 | Renamed, 30 | } 31 | 32 | impl FromStr for FileStatus { 33 | type Err = (); 34 | fn from_str(s: &str) -> std::result::Result { 35 | match s { 36 | "added" => Ok(FileStatus::Added), 37 | "modified" => Ok(FileStatus::Modified), 38 | "removed" => Ok(FileStatus::Removed), 39 | "renamed" => Ok(FileStatus::Renamed), 40 | _ => Err(()), // Explicitly return an error for unrecognized statuses 41 | } 42 | } 43 | } 44 | 45 | pub fn create_github_client(token: &str) -> Result { 46 | Octocrab::builder() 47 | .personal_token(token.to_string()) 48 | .build() 49 | .context("Failed to build GitHub client") 50 | } 51 | 52 | pub async fn get_pr_info( 53 | client: &Octocrab, 54 | owner: &str, 55 | repo: &str, 56 | pr_number: u64, 57 | ) -> Result { 58 | // Get PR details 59 | let pr = client 60 | .pulls(owner, repo) 61 | .get(pr_number) 62 | .await 63 | .context("Failed to get PR details")?; 64 | 65 | // Get PR changed files 66 | let files = client 67 | .pulls(owner, repo) 68 | .list_files(pr_number) 69 | .await 70 | .context("Failed to get PR files")?; 71 | 72 | // Convert to our internal model 73 | let changed_files = files 74 | .into_iter() 75 | .filter_map(|file| { 76 | // Convert `DiffEntryStatus` to `&str` for parsing 77 | let status_str = format!("{:?}", file.status).to_lowercase(); // Convert to lowercase if needed 78 | if let Ok(status) = FileStatus::from_str(&status_str) { 79 | Some(ChangedFile { 80 | filename: file.filename, 81 | status, 82 | additions: file.additions as i32, 83 | deletions: file.deletions as i32, 84 | }) 85 | } else { 86 | // Use debug formatting for `file.status` 87 | log::warn!("Unrecognized file status: {:?}", file.status); 88 | None 89 | } 90 | }) 91 | .collect(); 92 | 93 | fn default() -> impl FnOnce() -> T { 94 | || T::default() 95 | } 96 | Ok(PrInfo { 97 | title: pr.title.unwrap_or_default(), 98 | description: pr.body.unwrap_or_default(), 99 | base_branch: pr 100 | .base 101 | .repo 102 | .as_ref() 103 | .map_or_else(default::(), |repo| { 104 | repo.owner 105 | .as_ref() 106 | .map_or_else(default::(), |owner| owner.login.clone()) 107 | }), 108 | head_branch: pr.head.ref_field, 109 | author: pr.user.unwrap().login, 110 | changed_files, 111 | }) 112 | } 113 | 114 | pub async fn post_pr_comment( 115 | client: &Octocrab, 116 | owner: &str, 117 | repo: &str, 118 | pr_number: u64, 119 | comment: &str, 120 | ) -> Result<()> { 121 | client 122 | .issues(owner, repo) 123 | .create_comment(pr_number, comment) 124 | .await 125 | .context("Failed to post comment")?; 126 | Ok(()) 127 | } 128 | -------------------------------------------------------------------------------- /src/joke.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use reqwest::Client; 3 | use serde::Deserialize; 4 | use std::time::Duration; 5 | 6 | #[derive(Deserialize)] 7 | struct JokeResponse { 8 | joke: String, 9 | } 10 | 11 | const JOKE_APIS: &[&str] = &[ 12 | "https://official-joke-api.appspot.com/jokes/programming/random", 13 | "https://v2.jokeapi.dev/joke/Programming?type=single&safe-mode", 14 | "https://icanhazdadjoke.com/", 15 | ]; 16 | 17 | // Collection of emojis to randomly append to jokes 18 | const JOKE_EMOJIS: &[&str] = &[ 19 | "😂", 20 | "🤣", 21 | "😆", 22 | "😅", 23 | "😄", 24 | "😁", 25 | "🙂", 26 | "😉", 27 | "🤪", 28 | "🤓", 29 | "👨‍💻", 30 | "👩‍💻", 31 | "💻", 32 | "⌨️", 33 | "🖥️", 34 | "🐛", 35 | "🔧", 36 | "🛠️", 37 | ]; 38 | 39 | pub async fn fetch_random_joke() -> Result { 40 | let client = Client::new(); 41 | 42 | // Try different joke APIs in sequence until one works 43 | for (index, &api_url) in JOKE_APIS.iter().enumerate() { 44 | match fetch_from_api(&client, api_url, index).await { 45 | Ok(joke) => return Ok(add_emoji_to_joke(&joke)), 46 | Err(e) => log::warn!("Failed to fetch joke from {}: {}", api_url, e), 47 | } 48 | } 49 | 50 | // If all APIs fail, return a fallback joke 51 | Ok(add_emoji_to_joke(&get_fallback_joke())) 52 | } 53 | 54 | fn add_emoji_to_joke(joke: &str) -> String { 55 | // Select a random emoji from the collection 56 | let range = 0..JOKE_EMOJIS.len(); 57 | let emoji_index = random_number::random_ranged(range); 58 | 59 | let emoji = JOKE_EMOJIS[emoji_index]; 60 | 61 | // Add emoji to the end of the joke 62 | format!("{} {}", joke, emoji) 63 | } 64 | 65 | async fn fetch_from_api(client: &Client, url: &str, api_index: usize) -> Result { 66 | let request = client 67 | .get(url) 68 | .timeout(Duration::from_secs(5)) 69 | .header("Accept", "application/json"); 70 | 71 | let response = request.send().await.context("Failed to send request")?; 72 | 73 | if !response.status().is_success() { 74 | return Err(anyhow::anyhow!( 75 | "API returned error status: {}", 76 | response.status() 77 | )); 78 | } 79 | 80 | let text = response 81 | .text() 82 | .await 83 | .context("Failed to read response body")?; 84 | 85 | // Parse response based on the API format 86 | match api_index { 87 | 0 => { 88 | // official-joke-api returns an array with one joke object 89 | let jokes: Vec = serde_json::from_str(&text)?; 90 | if jokes.is_empty() { 91 | return Err(anyhow::anyhow!("Empty joke response")); 92 | } 93 | 94 | let setup = jokes[0]["setup"].as_str().unwrap_or_default(); 95 | let punchline = jokes[0]["punchline"].as_str().unwrap_or_default(); 96 | 97 | if !setup.is_empty() && !punchline.is_empty() { 98 | Ok(format!("{} {}", setup, punchline)) 99 | } else { 100 | Err(anyhow::anyhow!("Invalid joke format")) 101 | } 102 | } 103 | 1 => { 104 | // jokeapi.dev returns a single joke object 105 | let joke: serde_json::Value = serde_json::from_str(&text)?; 106 | if let Some(joke_text) = joke["joke"].as_str() { 107 | Ok(joke_text.to_string()) 108 | } else { 109 | Err(anyhow::anyhow!("Invalid joke format")) 110 | } 111 | } 112 | 2 => { 113 | // icanhazdadjoke returns a single joke 114 | let joke: JokeResponse = serde_json::from_str(&text)?; 115 | Ok(joke.joke) 116 | } 117 | _ => Err(anyhow::anyhow!("Unknown API index")), 118 | } 119 | } 120 | 121 | // Function to get programming-related fallback jokes if APIs fail 122 | fn get_fallback_joke() -> String { 123 | let jokes = [ 124 | "Why do programmers prefer dark mode? Because light attracts bugs!", 125 | "Why did the developer go broke? Because he used up all his cache.", 126 | "How many programmers does it take to change a light bulb? None, that's a hardware problem.", 127 | "A SQL query walks into a bar, sees two tables and asks, 'Can I join you?'", 128 | "Debugging: Being the detective in a crime movie where you are also the murderer.", 129 | "The best thing about a Boolean is that even if you're wrong, you're only off by a bit.", 130 | "Programming is like writing a book... except if you miss a single comma on page 126, the whole thing makes no sense.", 131 | "Why do Java developers wear glasses? Because they don't C#!", 132 | "Why was the JavaScript developer sad? Because he didn't Node how to Express himself.", 133 | "I'd tell you a UDP joke, but you might not get it." 134 | ]; 135 | 136 | // Use a simple random selection (not cryptographically secure but good enough for jokes) 137 | let range = 0..jokes.len(); 138 | let joke_index = random_number::random_ranged(range); 139 | 140 | jokes[joke_index].to_string() 141 | } 142 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod github; 2 | mod joke; 3 | mod summarizer; 4 | mod utils; 5 | 6 | use anyhow::{Context, Result}; 7 | use log::info; 8 | use std::env; 9 | 10 | #[tokio::main] 11 | async fn main() -> Result<()> { 12 | // Initialize logger 13 | env_logger::init(); 14 | info!("Starting PR Summarizer"); 15 | 16 | // Load the GitHub event payload 17 | let event_path = 18 | env::var("GITHUB_EVENT_PATH").context("GITHUB_EVENT_PATH environment variable not set")?; 19 | 20 | let event_payload = 21 | utils::read_github_event(&event_path).context("Failed to read GitHub event payload")?; 22 | 23 | // Extract PR number and repository from the event 24 | let (repo_owner, repo_name) = 25 | utils::get_repository_info().context("Failed to get repository information")?; 26 | 27 | let pr_number = utils::extract_pr_number(&event_payload) 28 | .context("Failed to extract PR number from event payload")?; 29 | 30 | // Create GitHub client 31 | let token = env::var("GITHUB_TOKEN").context("GITHUB_TOKEN environment variable not set")?; 32 | 33 | let github_client = 34 | github::create_github_client(&token).context("Failed to create GitHub client")?; 35 | 36 | // Get PR information 37 | let pr_info = github::get_pr_info(&github_client, &repo_owner, &repo_name, pr_number) 38 | .await 39 | .context("Failed to get PR information")?; 40 | 41 | // Generate summary 42 | let summary = summarizer::generate_summary(&pr_info).context("Failed to generate summary")?; 43 | 44 | // Fetch a random joke 45 | let joke = joke::fetch_random_joke() 46 | .await 47 | .context("Failed to fetch random joke")?; 48 | 49 | // Combine summary and joke into a comment with emojis 50 | let comment = format!( 51 | "# 🚀 PR Summary\n\n## 📝 Changes Overview\n{}\n\n## 📂 Affected Files\n{}\n\n## 😄 Code Humor\n{}\n\n---\n*This summary was automatically generated by [PR Summarizer](https://github.com/{}/{})* ⚡", 52 | summary.description, 53 | summary.affected_files, 54 | joke, 55 | repo_owner, 56 | repo_name 57 | ); 58 | 59 | // Post comment to PR 60 | github::post_pr_comment(&github_client, &repo_owner, &repo_name, pr_number, &comment) 61 | .await 62 | .context("Failed to post PR comment")?; 63 | 64 | info!("Successfully posted PR summary with joke"); 65 | Ok(()) 66 | } 67 | -------------------------------------------------------------------------------- /src/summarizer.rs: -------------------------------------------------------------------------------- 1 | use crate::github::{FileStatus, PrInfo}; 2 | use anyhow::Result; 3 | use itertools::Itertools; 4 | 5 | pub struct Summary { 6 | pub description: String, 7 | pub affected_files: String, 8 | } 9 | 10 | pub fn generate_summary(pr_info: &PrInfo) -> Result { 11 | // Generate bullet points based on the PR description and changed files 12 | let mut description_points = Vec::new(); 13 | 14 | // If the PR has a title that's meaningful, add it 15 | if !pr_info.title.is_empty() { 16 | description_points.push(format!("✨ {}", pr_info.title)); 17 | } 18 | 19 | // Try to extract key points from the PR description 20 | if !pr_info.description.is_empty() { 21 | let extracted_points = extract_key_points(&pr_info.description); 22 | description_points.extend(extracted_points); 23 | } 24 | 25 | // If we still don't have enough points, infer from file changes 26 | if description_points.is_empty() || description_points.len() < 2 { 27 | let inferred_points = infer_changes_from_files(&pr_info.changed_files); 28 | for point in inferred_points { 29 | if !description_points.contains(&point) { 30 | description_points.push(point); 31 | } 32 | } 33 | } 34 | 35 | // Format affected files section 36 | let affected_files = format_affected_files(&pr_info.changed_files); 37 | 38 | // Join description points with newlines 39 | let description = description_points.join("\n"); 40 | 41 | Ok(Summary { 42 | description, 43 | affected_files, 44 | }) 45 | } 46 | 47 | fn extract_key_points(description: &str) -> Vec { 48 | let mut points = Vec::new(); 49 | 50 | // Split by lines and look for patterns that suggest bullet points 51 | for line in description.lines() { 52 | let trimmed = line.trim(); 53 | 54 | // Check if it's already a bullet point or numbered item 55 | if trimmed.starts_with('-') 56 | || trimmed.starts_with('*') 57 | || (trimmed.len() > 2 58 | && trimmed.chars().next().unwrap().is_numeric() 59 | && trimmed.chars().nth(1) == Some('.')) 60 | { 61 | // Clean up the bullet point 62 | let content = trimmed 63 | .trim_start_matches('-') 64 | .trim_start_matches('*') 65 | .trim_start_matches(|c: char| c.is_numeric() || c == '.') 66 | .trim(); 67 | 68 | if !content.is_empty() { 69 | points.push(format!("✅ {}", content)); 70 | } 71 | } 72 | } 73 | // Limit to 5 points max 74 | points.truncate(5); 75 | points 76 | } 77 | 78 | fn infer_changes_from_files(files: &[crate::github::ChangedFile]) -> Vec { 79 | let mut points = Vec::new(); 80 | 81 | // Group files by directory to understand component changes 82 | let files_by_dir = files 83 | .iter() 84 | .map(|file| { 85 | let parts: Vec<&str> = file.filename.split('/').collect(); 86 | let dir = if parts.len() > 1 { parts[0] } else { "" }; 87 | (dir, file) 88 | }) 89 | .into_group_map(); 90 | 91 | // Check for specific patterns 92 | let has_tests = files 93 | .iter() 94 | .any(|f| f.filename.contains("test") || f.filename.contains("spec")); 95 | if has_tests { 96 | points.push("🧪 Added or updated tests".to_string()); 97 | } 98 | 99 | let has_docs = files.iter().any(|f| { 100 | f.filename.ends_with(".md") 101 | || f.filename.ends_with(".rst") 102 | || f.filename.contains("doc") 103 | || f.filename.eq("README.md") 104 | }); 105 | if has_docs { 106 | points.push("📚 Updated documentation".to_string()); 107 | } 108 | 109 | // Look at file extensions to identify the primary changes 110 | let mut _file_extensions = files 111 | .iter() 112 | .filter_map(|f| { 113 | let parts: Vec<&str> = f.filename.split('.').collect(); 114 | if parts.len() > 1 { 115 | Some(parts.last().unwrap().to_string()) 116 | } else { 117 | None 118 | } 119 | }) 120 | .collect::>(); 121 | 122 | // Generate points based on file groups 123 | for (dir, dir_files) in files_by_dir { 124 | if dir.is_empty() || dir_files.len() < 2 { 125 | continue; 126 | } 127 | 128 | let added = dir_files 129 | .iter() 130 | .filter(|f| matches!(f.status, FileStatus::Added)) 131 | .count(); 132 | let modified = dir_files 133 | .iter() 134 | .filter(|f| matches!(f.status, FileStatus::Modified)) 135 | .count(); 136 | let removed = dir_files 137 | .iter() 138 | .filter(|f| matches!(f.status, FileStatus::Removed)) 139 | .count(); 140 | 141 | if added > 0 && added == dir_files.len() { 142 | points.push(format!("🆕 Added new {} component/module", dir)); 143 | } else if removed > 0 && removed == dir_files.len() { 144 | points.push(format!("🗑️ Removed {} component/module", dir)); 145 | } else if modified > 0 { 146 | points.push(format!("🔄 Updated {} component/module", dir)); 147 | } 148 | } 149 | 150 | // Ensure we have at least one point 151 | if points.is_empty() && !files.is_empty() { 152 | points.push(format!("📝 Modified {} files", files.len())); 153 | } 154 | 155 | points 156 | } 157 | 158 | fn format_affected_files(files: &[crate::github::ChangedFile]) -> String { 159 | let mut result = String::new(); 160 | 161 | for file in files { 162 | let (status_icon, status_text) = match file.status { 163 | FileStatus::Added => ("🟢", "[+]"), 164 | FileStatus::Modified => ("🔵", "[M]"), 165 | FileStatus::Removed => ("🔴", "[-]"), 166 | FileStatus::Renamed => ("🟡", "[R]"), 167 | }; 168 | 169 | result.push_str(&format!( 170 | "- {} {} {}\n", 171 | status_icon, status_text, file.filename 172 | )); 173 | } 174 | 175 | result 176 | } 177 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use serde_json::Value; 3 | use std::env; 4 | use std::fs; 5 | 6 | pub fn read_github_event(event_path: &str) -> Result { 7 | let content = 8 | fs::read_to_string(event_path).context(format!("Failed to read file: {}", event_path))?; 9 | 10 | let json: Value = serde_json::from_str(&content).context("Failed to parse event JSON")?; 11 | 12 | Ok(json) 13 | } 14 | 15 | pub fn extract_pr_number(event: &Value) -> Result { 16 | // Check if this is a pull_request event 17 | if let Some(pr_number) = event["pull_request"]["number"].as_u64() { 18 | return Ok(pr_number); 19 | } 20 | 21 | // Check if this is a pull_request_target event 22 | if let Some(pr_number) = event["pull_request_target"]["number"].as_u64() { 23 | return Ok(pr_number); 24 | } 25 | 26 | // Check if issue_comment on a PR 27 | if let Some(issue) = event["issue"].as_object() { 28 | if issue.contains_key("pull_request") { 29 | if let Some(number) = issue["number"].as_u64() { 30 | return Ok(number); 31 | } 32 | } 33 | } 34 | 35 | Err(anyhow::anyhow!("Could not find PR number in event payload")) 36 | } 37 | 38 | pub fn get_repository_info() -> Result<(String, String)> { 39 | let repo = 40 | env::var("GITHUB_REPOSITORY").context("GITHUB_REPOSITORY environment variable not set")?; 41 | 42 | let parts: Vec<&str> = repo.split('/').collect(); 43 | if parts.len() != 2 { 44 | return Err(anyhow::anyhow!("Invalid repository format: {}", repo)); 45 | } 46 | 47 | Ok((parts[0].to_string(), parts[1].to_string())) 48 | } 49 | -------------------------------------------------------------------------------- /test_resources/testfile.txt: -------------------------------------------------------------------------------- 1 | this is a test file --------------------------------------------------------------------------------