Author:
Hash:
Timestamp:
+3183 -1261 +/-162 browse
Kevin Schoon [me@kevinschoon.com]
6628b7b36b989c9e15331b1ab75f7b26d3f5b9e8
Sat, 27 Sep 2025 12:23:25 +0000 (1 month ago)
| 1 | diff --git a/.ayllu-build.json b/.ayllu-build.json |
| 2 | new file mode 100644 |
| 3 | index 0000000..9e90a84 |
| 4 | --- /dev/null |
| 5 | +++ b/.ayllu-build.json |
| 6 | @@ -0,0 +1,53 @@ |
| 7 | + { |
| 8 | + "workflows": [ |
| 9 | + { |
| 10 | + "name": "lint", |
| 11 | + "steps": [ |
| 12 | + { |
| 13 | + "name": "cargo-fmt", |
| 14 | + "input": "cargo fmt --check" |
| 15 | + } |
| 16 | + ] |
| 17 | + }, |
| 18 | + { |
| 19 | + "name": "test", |
| 20 | + "depends_on": [ |
| 21 | + "lint" |
| 22 | + ], |
| 23 | + "steps": [ |
| 24 | + { |
| 25 | + "name": "cargo-test", |
| 26 | + "input": "cargo test" |
| 27 | + }, |
| 28 | + { |
| 29 | + "name": "cargo-clippy", |
| 30 | + "input": "cargo clippy" |
| 31 | + } |
| 32 | + ] |
| 33 | + }, |
| 34 | + { |
| 35 | + "name": "build", |
| 36 | + "depends_on": [ |
| 37 | + "test" |
| 38 | + ], |
| 39 | + "steps": [ |
| 40 | + { |
| 41 | + "name": "cargo-build-ayllu", |
| 42 | + "input": "cargo build --package ayllu" |
| 43 | + }, |
| 44 | + { |
| 45 | + "name": "cargo-build-ayllu-shell", |
| 46 | + "input": "cargo build --package ayllu-shell" |
| 47 | + }, |
| 48 | + { |
| 49 | + "name": "cargo-build-ayllu-keys", |
| 50 | + "input": "cargo build --package ayllu-keys" |
| 51 | + }, |
| 52 | + { |
| 53 | + "name": "cargo-build-ayllu-build", |
| 54 | + "input": "cargo build --package ayllu-build" |
| 55 | + } |
| 56 | + ] |
| 57 | + } |
| 58 | + ] |
| 59 | + } |
| 60 | \ No newline at end of file |
| 61 | diff --git a/.ayllu/build/main.ncl b/.ayllu/build/main.ncl |
| 62 | deleted file mode 100644 |
| 63 | index ceb7bad..0000000 |
| 64 | --- a/.ayllu/build/main.ncl |
| 65 | +++ /dev/null |
| 66 | @@ -1,24 +0,0 @@ |
| 67 | - { |
| 68 | - workflows = [ |
| 69 | - { |
| 70 | - name = "Simple", |
| 71 | - steps = [ |
| 72 | - { |
| 73 | - name = "Format", |
| 74 | - shell = "/bin/sh", |
| 75 | - input = "cargo fmt --all --check", |
| 76 | - }, |
| 77 | - { |
| 78 | - name = "Clippy", |
| 79 | - shell = "/bin/sh", |
| 80 | - input = "cargo clippy --all -- --deny warnings", |
| 81 | - }, |
| 82 | - { |
| 83 | - name = "Run Tests", |
| 84 | - shell = "/bin/sh", |
| 85 | - input = "cargo test --all", |
| 86 | - } |
| 87 | - ] |
| 88 | - } |
| 89 | - ] |
| 90 | - } |
| 91 | diff --git a/Cargo.lock b/Cargo.lock |
| 92 | index 9272d64..b3a3ca9 100644 |
| 93 | --- a/Cargo.lock |
| 94 | +++ b/Cargo.lock |
| 95 | @@ -27,6 +27,12 @@ dependencies = [ |
| 96 | ] |
| 97 | |
| 98 | [[package]] |
| 99 | + name = "allocator-api2" |
| 100 | + version = "0.2.21" |
| 101 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 102 | + checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" |
| 103 | + |
| 104 | + [[package]] |
| 105 | name = "android-tzdata" |
| 106 | version = "0.1.1" |
| 107 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 108 | @@ -154,6 +160,15 @@ dependencies = [ |
| 109 | ] |
| 110 | |
| 111 | [[package]] |
| 112 | + name = "atoi" |
| 113 | + version = "2.0.0" |
| 114 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 115 | + checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" |
| 116 | + dependencies = [ |
| 117 | + "num-traits", |
| 118 | + ] |
| 119 | + |
| 120 | + [[package]] |
| 121 | name = "atom_syndication" |
| 122 | version = "0.12.7" |
| 123 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 124 | @@ -282,6 +297,7 @@ dependencies = [ |
| 125 | "ayllu_api", |
| 126 | "ayllu_cmd", |
| 127 | "ayllu_config", |
| 128 | + "ayllu_database", |
| 129 | "ayllu_git", |
| 130 | "ayllu_identity", |
| 131 | "bytes", |
| 132 | @@ -291,14 +307,16 @@ dependencies = [ |
| 133 | "git2", |
| 134 | "headers", |
| 135 | "httparse", |
| 136 | + "layout-rs", |
| 137 | "lazy_static", |
| 138 | "libloading", |
| 139 | "mime", |
| 140 | "mime_guess", |
| 141 | "nix", |
| 142 | "openssh-keys", |
| 143 | + "petgraph", |
| 144 | "quick-xml 0.38.0", |
| 145 | - "rand", |
| 146 | + "rand 0.9.2", |
| 147 | "rss", |
| 148 | "rustc_version", |
| 149 | "serde", |
| 150 | @@ -322,6 +340,27 @@ dependencies = [ |
| 151 | ] |
| 152 | |
| 153 | [[package]] |
| 154 | + name = "ayllu-build" |
| 155 | + version = "0.2.1" |
| 156 | + dependencies = [ |
| 157 | + "async-trait", |
| 158 | + "ayllu_api", |
| 159 | + "ayllu_config", |
| 160 | + "ayllu_database", |
| 161 | + "ayllu_git", |
| 162 | + "ayllu_logging", |
| 163 | + "clap", |
| 164 | + "clap_complete", |
| 165 | + "petgraph", |
| 166 | + "rand 0.9.2", |
| 167 | + "serde", |
| 168 | + "serde_json", |
| 169 | + "sysinfo", |
| 170 | + "tokio", |
| 171 | + "tracing", |
| 172 | + ] |
| 173 | + |
| 174 | + [[package]] |
| 175 | name = "ayllu-keys" |
| 176 | version = "0.5.1" |
| 177 | dependencies = [ |
| 178 | @@ -332,6 +371,19 @@ dependencies = [ |
| 179 | ] |
| 180 | |
| 181 | [[package]] |
| 182 | + name = "ayllu-migrate" |
| 183 | + version = "0.1.0" |
| 184 | + dependencies = [ |
| 185 | + "ayllu_cmd", |
| 186 | + "ayllu_config", |
| 187 | + "ayllu_database", |
| 188 | + "ayllu_logging", |
| 189 | + "serde", |
| 190 | + "tokio", |
| 191 | + "tracing", |
| 192 | + ] |
| 193 | + |
| 194 | + [[package]] |
| 195 | name = "ayllu-shell" |
| 196 | version = "0.5.1" |
| 197 | dependencies = [ |
| 198 | @@ -379,11 +431,24 @@ dependencies = [ |
| 199 | ] |
| 200 | |
| 201 | [[package]] |
| 202 | + name = "ayllu_database" |
| 203 | + version = "0.2.1" |
| 204 | + dependencies = [ |
| 205 | + "async-trait", |
| 206 | + "futures", |
| 207 | + "serde", |
| 208 | + "serde_json", |
| 209 | + "sqlx", |
| 210 | + "time", |
| 211 | + "tracing", |
| 212 | + ] |
| 213 | + |
| 214 | + [[package]] |
| 215 | name = "ayllu_git" |
| 216 | version = "0.2.1" |
| 217 | dependencies = [ |
| 218 | "git2", |
| 219 | - "rand", |
| 220 | + "rand 0.9.2", |
| 221 | "serde", |
| 222 | "tempfile", |
| 223 | "tokio", |
| 224 | @@ -435,6 +500,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 225 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" |
| 226 | |
| 227 | [[package]] |
| 228 | + name = "base64ct" |
| 229 | + version = "1.8.0" |
| 230 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 231 | + checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" |
| 232 | + |
| 233 | + [[package]] |
| 234 | name = "basic-toml" |
| 235 | version = "0.1.10" |
| 236 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 237 | @@ -448,6 +519,9 @@ name = "bitflags" |
| 238 | version = "2.9.1" |
| 239 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 240 | checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" |
| 241 | + dependencies = [ |
| 242 | + "serde", |
| 243 | + ] |
| 244 | |
| 245 | [[package]] |
| 246 | name = "block-buffer" |
| 247 | @@ -601,6 +675,15 @@ dependencies = [ |
| 248 | ] |
| 249 | |
| 250 | [[package]] |
| 251 | + name = "concurrent-queue" |
| 252 | + version = "2.5.0" |
| 253 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 254 | + checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" |
| 255 | + dependencies = [ |
| 256 | + "crossbeam-utils", |
| 257 | + ] |
| 258 | + |
| 259 | + [[package]] |
| 260 | name = "console" |
| 261 | version = "0.15.11" |
| 262 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 263 | @@ -614,6 +697,12 @@ dependencies = [ |
| 264 | ] |
| 265 | |
| 266 | [[package]] |
| 267 | + name = "const-oid" |
| 268 | + version = "0.9.6" |
| 269 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 270 | + checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" |
| 271 | + |
| 272 | + [[package]] |
| 273 | name = "convert_case" |
| 274 | version = "0.6.0" |
| 275 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 276 | @@ -659,6 +748,55 @@ dependencies = [ |
| 277 | ] |
| 278 | |
| 279 | [[package]] |
| 280 | + name = "crc" |
| 281 | + version = "3.3.0" |
| 282 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 283 | + checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" |
| 284 | + dependencies = [ |
| 285 | + "crc-catalog", |
| 286 | + ] |
| 287 | + |
| 288 | + [[package]] |
| 289 | + name = "crc-catalog" |
| 290 | + version = "2.4.0" |
| 291 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 292 | + checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" |
| 293 | + |
| 294 | + [[package]] |
| 295 | + name = "crossbeam-deque" |
| 296 | + version = "0.8.6" |
| 297 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 298 | + checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" |
| 299 | + dependencies = [ |
| 300 | + "crossbeam-epoch", |
| 301 | + "crossbeam-utils", |
| 302 | + ] |
| 303 | + |
| 304 | + [[package]] |
| 305 | + name = "crossbeam-epoch" |
| 306 | + version = "0.9.18" |
| 307 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 308 | + checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" |
| 309 | + dependencies = [ |
| 310 | + "crossbeam-utils", |
| 311 | + ] |
| 312 | + |
| 313 | + [[package]] |
| 314 | + name = "crossbeam-queue" |
| 315 | + version = "0.3.12" |
| 316 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 317 | + checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" |
| 318 | + dependencies = [ |
| 319 | + "crossbeam-utils", |
| 320 | + ] |
| 321 | + |
| 322 | + [[package]] |
| 323 | + name = "crossbeam-utils" |
| 324 | + version = "0.8.21" |
| 325 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 326 | + checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" |
| 327 | + |
| 328 | + [[package]] |
| 329 | name = "crypto-common" |
| 330 | version = "0.1.6" |
| 331 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 332 | @@ -704,6 +842,17 @@ dependencies = [ |
| 333 | ] |
| 334 | |
| 335 | [[package]] |
| 336 | + name = "der" |
| 337 | + version = "0.7.10" |
| 338 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 339 | + checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" |
| 340 | + dependencies = [ |
| 341 | + "const-oid", |
| 342 | + "pem-rfc7468", |
| 343 | + "zeroize", |
| 344 | + ] |
| 345 | + |
| 346 | + [[package]] |
| 347 | name = "deranged" |
| 348 | version = "0.4.0" |
| 349 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 350 | @@ -768,7 +917,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 351 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" |
| 352 | dependencies = [ |
| 353 | "block-buffer", |
| 354 | + "const-oid", |
| 355 | "crypto-common", |
| 356 | + "subtle", |
| 357 | ] |
| 358 | |
| 359 | [[package]] |
| 360 | @@ -801,12 +952,27 @@ dependencies = [ |
| 361 | ] |
| 362 | |
| 363 | [[package]] |
| 364 | + name = "dotenvy" |
| 365 | + version = "0.15.7" |
| 366 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 367 | + checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" |
| 368 | + |
| 369 | + [[package]] |
| 370 | name = "dyn-clone" |
| 371 | version = "1.0.19" |
| 372 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 373 | checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" |
| 374 | |
| 375 | [[package]] |
| 376 | + name = "either" |
| 377 | + version = "1.15.0" |
| 378 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 379 | + checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" |
| 380 | + dependencies = [ |
| 381 | + "serde", |
| 382 | + ] |
| 383 | + |
| 384 | + [[package]] |
| 385 | name = "encode_unicode" |
| 386 | version = "1.0.0" |
| 387 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 388 | @@ -844,6 +1010,28 @@ dependencies = [ |
| 389 | ] |
| 390 | |
| 391 | [[package]] |
| 392 | + name = "etcetera" |
| 393 | + version = "0.8.0" |
| 394 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 395 | + checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" |
| 396 | + dependencies = [ |
| 397 | + "cfg-if", |
| 398 | + "home", |
| 399 | + "windows-sys 0.48.0", |
| 400 | + ] |
| 401 | + |
| 402 | + [[package]] |
| 403 | + name = "event-listener" |
| 404 | + version = "5.4.1" |
| 405 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 406 | + checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" |
| 407 | + dependencies = [ |
| 408 | + "concurrent-queue", |
| 409 | + "parking", |
| 410 | + "pin-project-lite", |
| 411 | + ] |
| 412 | + |
| 413 | + [[package]] |
| 414 | name = "fastrand" |
| 415 | version = "2.3.0" |
| 416 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 417 | @@ -859,12 +1047,35 @@ dependencies = [ |
| 418 | ] |
| 419 | |
| 420 | [[package]] |
| 421 | + name = "fixedbitset" |
| 422 | + version = "0.4.2" |
| 423 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 424 | + checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" |
| 425 | + |
| 426 | + [[package]] |
| 427 | + name = "flume" |
| 428 | + version = "0.11.1" |
| 429 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 430 | + checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" |
| 431 | + dependencies = [ |
| 432 | + "futures-core", |
| 433 | + "futures-sink", |
| 434 | + "spin", |
| 435 | + ] |
| 436 | + |
| 437 | + [[package]] |
| 438 | name = "fnv" |
| 439 | version = "1.0.7" |
| 440 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 441 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" |
| 442 | |
| 443 | [[package]] |
| 444 | + name = "foldhash" |
| 445 | + version = "0.1.5" |
| 446 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 447 | + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" |
| 448 | + |
| 449 | + [[package]] |
| 450 | name = "foreign-types" |
| 451 | version = "0.3.2" |
| 452 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 453 | @@ -931,6 +1142,17 @@ dependencies = [ |
| 454 | ] |
| 455 | |
| 456 | [[package]] |
| 457 | + name = "futures-intrusive" |
| 458 | + version = "0.5.0" |
| 459 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 460 | + checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" |
| 461 | + dependencies = [ |
| 462 | + "futures-core", |
| 463 | + "lock_api", |
| 464 | + "parking_lot", |
| 465 | + ] |
| 466 | + |
| 467 | + [[package]] |
| 468 | name = "futures-io" |
| 469 | version = "0.3.31" |
| 470 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 471 | @@ -1059,6 +1281,20 @@ name = "hashbrown" |
| 472 | version = "0.15.4" |
| 473 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 474 | checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" |
| 475 | + dependencies = [ |
| 476 | + "allocator-api2", |
| 477 | + "equivalent", |
| 478 | + "foldhash", |
| 479 | + ] |
| 480 | + |
| 481 | + [[package]] |
| 482 | + name = "hashlink" |
| 483 | + version = "0.10.0" |
| 484 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 485 | + checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" |
| 486 | + dependencies = [ |
| 487 | + "hashbrown 0.15.4", |
| 488 | + ] |
| 489 | |
| 490 | [[package]] |
| 491 | name = "headers" |
| 492 | @@ -1097,6 +1333,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 493 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" |
| 494 | |
| 495 | [[package]] |
| 496 | + name = "hkdf" |
| 497 | + version = "0.12.4" |
| 498 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 499 | + checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" |
| 500 | + dependencies = [ |
| 501 | + "hmac", |
| 502 | + ] |
| 503 | + |
| 504 | + [[package]] |
| 505 | + name = "hmac" |
| 506 | + version = "0.12.1" |
| 507 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 508 | + checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" |
| 509 | + dependencies = [ |
| 510 | + "digest", |
| 511 | + ] |
| 512 | + |
| 513 | + [[package]] |
| 514 | + name = "home" |
| 515 | + version = "0.5.11" |
| 516 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 517 | + checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" |
| 518 | + dependencies = [ |
| 519 | + "windows-sys 0.59.0", |
| 520 | + ] |
| 521 | + |
| 522 | + [[package]] |
| 523 | name = "http" |
| 524 | version = "1.3.1" |
| 525 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 526 | @@ -1461,10 +1724,19 @@ dependencies = [ |
| 527 | ] |
| 528 | |
| 529 | [[package]] |
| 530 | + name = "layout-rs" |
| 531 | + version = "0.1.3" |
| 532 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 533 | + checksum = "5b8b38bc67665e362eb770c6b6ae88b48d040d94a0a10c4904c37bc79d263b95" |
| 534 | + |
| 535 | + [[package]] |
| 536 | name = "lazy_static" |
| 537 | version = "1.5.0" |
| 538 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 539 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" |
| 540 | + dependencies = [ |
| 541 | + "spin", |
| 542 | + ] |
| 543 | |
| 544 | [[package]] |
| 545 | name = "libc" |
| 546 | @@ -1495,6 +1767,34 @@ dependencies = [ |
| 547 | ] |
| 548 | |
| 549 | [[package]] |
| 550 | + name = "libm" |
| 551 | + version = "0.2.15" |
| 552 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 553 | + checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" |
| 554 | + |
| 555 | + [[package]] |
| 556 | + name = "libredox" |
| 557 | + version = "0.1.10" |
| 558 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 559 | + checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" |
| 560 | + dependencies = [ |
| 561 | + "bitflags", |
| 562 | + "libc", |
| 563 | + "redox_syscall", |
| 564 | + ] |
| 565 | + |
| 566 | + [[package]] |
| 567 | + name = "libsqlite3-sys" |
| 568 | + version = "0.30.1" |
| 569 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 570 | + checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" |
| 571 | + dependencies = [ |
| 572 | + "cc", |
| 573 | + "pkg-config", |
| 574 | + "vcpkg", |
| 575 | + ] |
| 576 | + |
| 577 | + [[package]] |
| 578 | name = "libz-sys" |
| 579 | version = "1.1.22" |
| 580 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 581 | @@ -1643,6 +1943,15 @@ dependencies = [ |
| 582 | ] |
| 583 | |
| 584 | [[package]] |
| 585 | + name = "ntapi" |
| 586 | + version = "0.4.1" |
| 587 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 588 | + checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" |
| 589 | + dependencies = [ |
| 590 | + "winapi", |
| 591 | + ] |
| 592 | + |
| 593 | + [[package]] |
| 594 | name = "nu-ansi-term" |
| 595 | version = "0.46.0" |
| 596 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 597 | @@ -1653,18 +1962,56 @@ dependencies = [ |
| 598 | ] |
| 599 | |
| 600 | [[package]] |
| 601 | + name = "num-bigint-dig" |
| 602 | + version = "0.8.4" |
| 603 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 604 | + checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" |
| 605 | + dependencies = [ |
| 606 | + "byteorder", |
| 607 | + "lazy_static", |
| 608 | + "libm", |
| 609 | + "num-integer", |
| 610 | + "num-iter", |
| 611 | + "num-traits", |
| 612 | + "rand 0.8.5", |
| 613 | + "smallvec", |
| 614 | + "zeroize", |
| 615 | + ] |
| 616 | + |
| 617 | + [[package]] |
| 618 | name = "num-conv" |
| 619 | version = "0.1.0" |
| 620 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 621 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" |
| 622 | |
| 623 | [[package]] |
| 624 | + name = "num-integer" |
| 625 | + version = "0.1.46" |
| 626 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 627 | + checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" |
| 628 | + dependencies = [ |
| 629 | + "num-traits", |
| 630 | + ] |
| 631 | + |
| 632 | + [[package]] |
| 633 | + name = "num-iter" |
| 634 | + version = "0.1.45" |
| 635 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 636 | + checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" |
| 637 | + dependencies = [ |
| 638 | + "autocfg", |
| 639 | + "num-integer", |
| 640 | + "num-traits", |
| 641 | + ] |
| 642 | + |
| 643 | + [[package]] |
| 644 | name = "num-traits" |
| 645 | version = "0.2.19" |
| 646 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 647 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" |
| 648 | dependencies = [ |
| 649 | "autocfg", |
| 650 | + "libm", |
| 651 | ] |
| 652 | |
| 653 | [[package]] |
| 654 | @@ -1776,6 +2123,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 655 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" |
| 656 | |
| 657 | [[package]] |
| 658 | + name = "parking" |
| 659 | + version = "2.2.1" |
| 660 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 661 | + checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" |
| 662 | + |
| 663 | + [[package]] |
| 664 | name = "parking_lot" |
| 665 | version = "0.12.4" |
| 666 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 667 | @@ -1799,12 +2152,33 @@ dependencies = [ |
| 668 | ] |
| 669 | |
| 670 | [[package]] |
| 671 | + name = "pem-rfc7468" |
| 672 | + version = "0.7.0" |
| 673 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 674 | + checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" |
| 675 | + dependencies = [ |
| 676 | + "base64ct", |
| 677 | + ] |
| 678 | + |
| 679 | + [[package]] |
| 680 | name = "percent-encoding" |
| 681 | version = "2.3.1" |
| 682 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 683 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" |
| 684 | |
| 685 | [[package]] |
| 686 | + name = "petgraph" |
| 687 | + version = "0.6.5" |
| 688 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 689 | + checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" |
| 690 | + dependencies = [ |
| 691 | + "fixedbitset", |
| 692 | + "indexmap 2.10.0", |
| 693 | + "serde", |
| 694 | + "serde_derive", |
| 695 | + ] |
| 696 | + |
| 697 | + [[package]] |
| 698 | name = "pin-project-lite" |
| 699 | version = "0.2.16" |
| 700 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 701 | @@ -1817,6 +2191,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 702 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" |
| 703 | |
| 704 | [[package]] |
| 705 | + name = "pkcs1" |
| 706 | + version = "0.7.5" |
| 707 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 708 | + checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" |
| 709 | + dependencies = [ |
| 710 | + "der", |
| 711 | + "pkcs8", |
| 712 | + "spki", |
| 713 | + ] |
| 714 | + |
| 715 | + [[package]] |
| 716 | + name = "pkcs8" |
| 717 | + version = "0.10.2" |
| 718 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 719 | + checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" |
| 720 | + dependencies = [ |
| 721 | + "der", |
| 722 | + "spki", |
| 723 | + ] |
| 724 | + |
| 725 | + [[package]] |
| 726 | name = "pkg-config" |
| 727 | version = "0.3.32" |
| 728 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 729 | @@ -1912,12 +2307,33 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" |
| 730 | |
| 731 | [[package]] |
| 732 | name = "rand" |
| 733 | + version = "0.8.5" |
| 734 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 735 | + checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" |
| 736 | + dependencies = [ |
| 737 | + "libc", |
| 738 | + "rand_chacha 0.3.1", |
| 739 | + "rand_core 0.6.4", |
| 740 | + ] |
| 741 | + |
| 742 | + [[package]] |
| 743 | + name = "rand" |
| 744 | version = "0.9.2" |
| 745 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 746 | checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" |
| 747 | dependencies = [ |
| 748 | - "rand_chacha", |
| 749 | - "rand_core", |
| 750 | + "rand_chacha 0.9.0", |
| 751 | + "rand_core 0.9.3", |
| 752 | + ] |
| 753 | + |
| 754 | + [[package]] |
| 755 | + name = "rand_chacha" |
| 756 | + version = "0.3.1" |
| 757 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 758 | + checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" |
| 759 | + dependencies = [ |
| 760 | + "ppv-lite86", |
| 761 | + "rand_core 0.6.4", |
| 762 | ] |
| 763 | |
| 764 | [[package]] |
| 765 | @@ -1927,7 +2343,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 766 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" |
| 767 | dependencies = [ |
| 768 | "ppv-lite86", |
| 769 | - "rand_core", |
| 770 | + "rand_core 0.9.3", |
| 771 | + ] |
| 772 | + |
| 773 | + [[package]] |
| 774 | + name = "rand_core" |
| 775 | + version = "0.6.4" |
| 776 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 777 | + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" |
| 778 | + dependencies = [ |
| 779 | + "getrandom 0.2.16", |
| 780 | ] |
| 781 | |
| 782 | [[package]] |
| 783 | @@ -1940,6 +2365,26 @@ dependencies = [ |
| 784 | ] |
| 785 | |
| 786 | [[package]] |
| 787 | + name = "rayon" |
| 788 | + version = "1.11.0" |
| 789 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 790 | + checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" |
| 791 | + dependencies = [ |
| 792 | + "either", |
| 793 | + "rayon-core", |
| 794 | + ] |
| 795 | + |
| 796 | + [[package]] |
| 797 | + name = "rayon-core" |
| 798 | + version = "1.13.0" |
| 799 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 800 | + checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" |
| 801 | + dependencies = [ |
| 802 | + "crossbeam-deque", |
| 803 | + "crossbeam-utils", |
| 804 | + ] |
| 805 | + |
| 806 | + [[package]] |
| 807 | name = "redox_syscall" |
| 808 | version = "0.5.16" |
| 809 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 810 | @@ -2073,6 +2518,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 811 | checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" |
| 812 | |
| 813 | [[package]] |
| 814 | + name = "rsa" |
| 815 | + version = "0.9.8" |
| 816 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 817 | + checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" |
| 818 | + dependencies = [ |
| 819 | + "const-oid", |
| 820 | + "digest", |
| 821 | + "num-bigint-dig", |
| 822 | + "num-integer", |
| 823 | + "num-traits", |
| 824 | + "pkcs1", |
| 825 | + "pkcs8", |
| 826 | + "rand_core 0.6.4", |
| 827 | + "signature", |
| 828 | + "spki", |
| 829 | + "subtle", |
| 830 | + "zeroize", |
| 831 | + ] |
| 832 | + |
| 833 | + [[package]] |
| 834 | name = "rss" |
| 835 | version = "2.0.12" |
| 836 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 837 | @@ -2393,6 +2858,16 @@ dependencies = [ |
| 838 | ] |
| 839 | |
| 840 | [[package]] |
| 841 | + name = "signature" |
| 842 | + version = "2.2.0" |
| 843 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 844 | + checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" |
| 845 | + dependencies = [ |
| 846 | + "digest", |
| 847 | + "rand_core 0.6.4", |
| 848 | + ] |
| 849 | + |
| 850 | + [[package]] |
| 851 | name = "slab" |
| 852 | version = "0.4.10" |
| 853 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 854 | @@ -2413,6 +2888,9 @@ name = "smallvec" |
| 855 | version = "1.15.1" |
| 856 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 857 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" |
| 858 | + dependencies = [ |
| 859 | + "serde", |
| 860 | + ] |
| 861 | |
| 862 | [[package]] |
| 863 | name = "socket2" |
| 864 | @@ -2425,6 +2903,213 @@ dependencies = [ |
| 865 | ] |
| 866 | |
| 867 | [[package]] |
| 868 | + name = "spin" |
| 869 | + version = "0.9.8" |
| 870 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 871 | + checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" |
| 872 | + dependencies = [ |
| 873 | + "lock_api", |
| 874 | + ] |
| 875 | + |
| 876 | + [[package]] |
| 877 | + name = "spki" |
| 878 | + version = "0.7.3" |
| 879 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 880 | + checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" |
| 881 | + dependencies = [ |
| 882 | + "base64ct", |
| 883 | + "der", |
| 884 | + ] |
| 885 | + |
| 886 | + [[package]] |
| 887 | + name = "sqlx" |
| 888 | + version = "0.8.6" |
| 889 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 890 | + checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" |
| 891 | + dependencies = [ |
| 892 | + "sqlx-core", |
| 893 | + "sqlx-macros", |
| 894 | + "sqlx-mysql", |
| 895 | + "sqlx-postgres", |
| 896 | + "sqlx-sqlite", |
| 897 | + ] |
| 898 | + |
| 899 | + [[package]] |
| 900 | + name = "sqlx-core" |
| 901 | + version = "0.8.6" |
| 902 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 903 | + checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" |
| 904 | + dependencies = [ |
| 905 | + "base64 0.22.1", |
| 906 | + "bytes", |
| 907 | + "crc", |
| 908 | + "crossbeam-queue", |
| 909 | + "either", |
| 910 | + "event-listener", |
| 911 | + "futures-core", |
| 912 | + "futures-intrusive", |
| 913 | + "futures-io", |
| 914 | + "futures-util", |
| 915 | + "hashbrown 0.15.4", |
| 916 | + "hashlink", |
| 917 | + "indexmap 2.10.0", |
| 918 | + "log", |
| 919 | + "memchr", |
| 920 | + "once_cell", |
| 921 | + "percent-encoding", |
| 922 | + "serde", |
| 923 | + "serde_json", |
| 924 | + "sha2", |
| 925 | + "smallvec", |
| 926 | + "thiserror 2.0.12", |
| 927 | + "tokio", |
| 928 | + "tokio-stream", |
| 929 | + "tracing", |
| 930 | + "url", |
| 931 | + ] |
| 932 | + |
| 933 | + [[package]] |
| 934 | + name = "sqlx-macros" |
| 935 | + version = "0.8.6" |
| 936 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 937 | + checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" |
| 938 | + dependencies = [ |
| 939 | + "proc-macro2", |
| 940 | + "quote", |
| 941 | + "sqlx-core", |
| 942 | + "sqlx-macros-core", |
| 943 | + "syn", |
| 944 | + ] |
| 945 | + |
| 946 | + [[package]] |
| 947 | + name = "sqlx-macros-core" |
| 948 | + version = "0.8.6" |
| 949 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 950 | + checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" |
| 951 | + dependencies = [ |
| 952 | + "dotenvy", |
| 953 | + "either", |
| 954 | + "heck", |
| 955 | + "hex", |
| 956 | + "once_cell", |
| 957 | + "proc-macro2", |
| 958 | + "quote", |
| 959 | + "serde", |
| 960 | + "serde_json", |
| 961 | + "sha2", |
| 962 | + "sqlx-core", |
| 963 | + "sqlx-mysql", |
| 964 | + "sqlx-postgres", |
| 965 | + "sqlx-sqlite", |
| 966 | + "syn", |
| 967 | + "tokio", |
| 968 | + "url", |
| 969 | + ] |
| 970 | + |
| 971 | + [[package]] |
| 972 | + name = "sqlx-mysql" |
| 973 | + version = "0.8.6" |
| 974 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 975 | + checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" |
| 976 | + dependencies = [ |
| 977 | + "atoi", |
| 978 | + "base64 0.22.1", |
| 979 | + "bitflags", |
| 980 | + "byteorder", |
| 981 | + "bytes", |
| 982 | + "crc", |
| 983 | + "digest", |
| 984 | + "dotenvy", |
| 985 | + "either", |
| 986 | + "futures-channel", |
| 987 | + "futures-core", |
| 988 | + "futures-io", |
| 989 | + "futures-util", |
| 990 | + "generic-array", |
| 991 | + "hex", |
| 992 | + "hkdf", |
| 993 | + "hmac", |
| 994 | + "itoa", |
| 995 | + "log", |
| 996 | + "md-5", |
| 997 | + "memchr", |
| 998 | + "once_cell", |
| 999 | + "percent-encoding", |
| 1000 | + "rand 0.8.5", |
| 1001 | + "rsa", |
| 1002 | + "serde", |
| 1003 | + "sha1", |
| 1004 | + "sha2", |
| 1005 | + "smallvec", |
| 1006 | + "sqlx-core", |
| 1007 | + "stringprep", |
| 1008 | + "thiserror 2.0.12", |
| 1009 | + "tracing", |
| 1010 | + "whoami", |
| 1011 | + ] |
| 1012 | + |
| 1013 | + [[package]] |
| 1014 | + name = "sqlx-postgres" |
| 1015 | + version = "0.8.6" |
| 1016 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1017 | + checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" |
| 1018 | + dependencies = [ |
| 1019 | + "atoi", |
| 1020 | + "base64 0.22.1", |
| 1021 | + "bitflags", |
| 1022 | + "byteorder", |
| 1023 | + "crc", |
| 1024 | + "dotenvy", |
| 1025 | + "etcetera", |
| 1026 | + "futures-channel", |
| 1027 | + "futures-core", |
| 1028 | + "futures-util", |
| 1029 | + "hex", |
| 1030 | + "hkdf", |
| 1031 | + "hmac", |
| 1032 | + "home", |
| 1033 | + "itoa", |
| 1034 | + "log", |
| 1035 | + "md-5", |
| 1036 | + "memchr", |
| 1037 | + "once_cell", |
| 1038 | + "rand 0.8.5", |
| 1039 | + "serde", |
| 1040 | + "serde_json", |
| 1041 | + "sha2", |
| 1042 | + "smallvec", |
| 1043 | + "sqlx-core", |
| 1044 | + "stringprep", |
| 1045 | + "thiserror 2.0.12", |
| 1046 | + "tracing", |
| 1047 | + "whoami", |
| 1048 | + ] |
| 1049 | + |
| 1050 | + [[package]] |
| 1051 | + name = "sqlx-sqlite" |
| 1052 | + version = "0.8.6" |
| 1053 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1054 | + checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" |
| 1055 | + dependencies = [ |
| 1056 | + "atoi", |
| 1057 | + "flume", |
| 1058 | + "futures-channel", |
| 1059 | + "futures-core", |
| 1060 | + "futures-executor", |
| 1061 | + "futures-intrusive", |
| 1062 | + "futures-util", |
| 1063 | + "libsqlite3-sys", |
| 1064 | + "log", |
| 1065 | + "percent-encoding", |
| 1066 | + "serde", |
| 1067 | + "serde_urlencoded", |
| 1068 | + "sqlx-core", |
| 1069 | + "thiserror 2.0.12", |
| 1070 | + "tracing", |
| 1071 | + "url", |
| 1072 | + ] |
| 1073 | + |
| 1074 | + [[package]] |
| 1075 | name = "stable_deref_trait" |
| 1076 | version = "1.2.0" |
| 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1078 | @@ -2437,6 +3122,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1079 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" |
| 1080 | |
| 1081 | [[package]] |
| 1082 | + name = "stringprep" |
| 1083 | + version = "0.1.5" |
| 1084 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1085 | + checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" |
| 1086 | + dependencies = [ |
| 1087 | + "unicode-bidi", |
| 1088 | + "unicode-normalization", |
| 1089 | + "unicode-properties", |
| 1090 | + ] |
| 1091 | + |
| 1092 | + [[package]] |
| 1093 | name = "strsim" |
| 1094 | version = "0.11.1" |
| 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1096 | @@ -2480,6 +3176,21 @@ dependencies = [ |
| 1097 | ] |
| 1098 | |
| 1099 | [[package]] |
| 1100 | + name = "sysinfo" |
| 1101 | + version = "0.29.11" |
| 1102 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1103 | + checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" |
| 1104 | + dependencies = [ |
| 1105 | + "cfg-if", |
| 1106 | + "core-foundation-sys", |
| 1107 | + "libc", |
| 1108 | + "ntapi", |
| 1109 | + "once_cell", |
| 1110 | + "rayon", |
| 1111 | + "winapi", |
| 1112 | + ] |
| 1113 | + |
| 1114 | + [[package]] |
| 1115 | name = "system-configuration" |
| 1116 | version = "0.6.1" |
| 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1118 | @@ -2908,6 +3619,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1119 | checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" |
| 1120 | |
| 1121 | [[package]] |
| 1122 | + name = "unicode-bidi" |
| 1123 | + version = "0.3.18" |
| 1124 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1125 | + checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" |
| 1126 | + |
| 1127 | + [[package]] |
| 1128 | name = "unicode-ident" |
| 1129 | version = "1.0.18" |
| 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1131 | @@ -2923,6 +3640,12 @@ dependencies = [ |
| 1132 | ] |
| 1133 | |
| 1134 | [[package]] |
| 1135 | + name = "unicode-properties" |
| 1136 | + version = "0.1.3" |
| 1137 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1138 | + checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" |
| 1139 | + |
| 1140 | + [[package]] |
| 1141 | name = "unicode-segmentation" |
| 1142 | version = "1.12.0" |
| 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1144 | @@ -3019,6 +3742,12 @@ dependencies = [ |
| 1145 | ] |
| 1146 | |
| 1147 | [[package]] |
| 1148 | + name = "wasite" |
| 1149 | + version = "0.1.0" |
| 1150 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1151 | + checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" |
| 1152 | + |
| 1153 | + [[package]] |
| 1154 | name = "wasm-bindgen" |
| 1155 | version = "0.2.100" |
| 1156 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1157 | @@ -3138,6 +3867,16 @@ dependencies = [ |
| 1158 | ] |
| 1159 | |
| 1160 | [[package]] |
| 1161 | + name = "whoami" |
| 1162 | + version = "1.6.1" |
| 1163 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1164 | + checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" |
| 1165 | + dependencies = [ |
| 1166 | + "libredox", |
| 1167 | + "wasite", |
| 1168 | + ] |
| 1169 | + |
| 1170 | + [[package]] |
| 1171 | name = "winapi" |
| 1172 | version = "0.3.9" |
| 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1174 | @@ -3231,6 +3970,15 @@ dependencies = [ |
| 1175 | |
| 1176 | [[package]] |
| 1177 | name = "windows-sys" |
| 1178 | + version = "0.48.0" |
| 1179 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1180 | + checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" |
| 1181 | + dependencies = [ |
| 1182 | + "windows-targets 0.48.5", |
| 1183 | + ] |
| 1184 | + |
| 1185 | + [[package]] |
| 1186 | + name = "windows-sys" |
| 1187 | version = "0.52.0" |
| 1188 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1189 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" |
| 1190 | @@ -3258,6 +4006,21 @@ dependencies = [ |
| 1191 | |
| 1192 | [[package]] |
| 1193 | name = "windows-targets" |
| 1194 | + version = "0.48.5" |
| 1195 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1196 | + checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" |
| 1197 | + dependencies = [ |
| 1198 | + "windows_aarch64_gnullvm 0.48.5", |
| 1199 | + "windows_aarch64_msvc 0.48.5", |
| 1200 | + "windows_i686_gnu 0.48.5", |
| 1201 | + "windows_i686_msvc 0.48.5", |
| 1202 | + "windows_x86_64_gnu 0.48.5", |
| 1203 | + "windows_x86_64_gnullvm 0.48.5", |
| 1204 | + "windows_x86_64_msvc 0.48.5", |
| 1205 | + ] |
| 1206 | + |
| 1207 | + [[package]] |
| 1208 | + name = "windows-targets" |
| 1209 | version = "0.52.6" |
| 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1211 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" |
| 1212 | @@ -3290,6 +4053,12 @@ dependencies = [ |
| 1213 | |
| 1214 | [[package]] |
| 1215 | name = "windows_aarch64_gnullvm" |
| 1216 | + version = "0.48.5" |
| 1217 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1218 | + checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" |
| 1219 | + |
| 1220 | + [[package]] |
| 1221 | + name = "windows_aarch64_gnullvm" |
| 1222 | version = "0.52.6" |
| 1223 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1224 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" |
| 1225 | @@ -3302,6 +4071,12 @@ checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" |
| 1226 | |
| 1227 | [[package]] |
| 1228 | name = "windows_aarch64_msvc" |
| 1229 | + version = "0.48.5" |
| 1230 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1231 | + checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" |
| 1232 | + |
| 1233 | + [[package]] |
| 1234 | + name = "windows_aarch64_msvc" |
| 1235 | version = "0.52.6" |
| 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1237 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" |
| 1238 | @@ -3314,6 +4089,12 @@ checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" |
| 1239 | |
| 1240 | [[package]] |
| 1241 | name = "windows_i686_gnu" |
| 1242 | + version = "0.48.5" |
| 1243 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1244 | + checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" |
| 1245 | + |
| 1246 | + [[package]] |
| 1247 | + name = "windows_i686_gnu" |
| 1248 | version = "0.52.6" |
| 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1250 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" |
| 1251 | @@ -3338,6 +4119,12 @@ checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" |
| 1252 | |
| 1253 | [[package]] |
| 1254 | name = "windows_i686_msvc" |
| 1255 | + version = "0.48.5" |
| 1256 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1257 | + checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" |
| 1258 | + |
| 1259 | + [[package]] |
| 1260 | + name = "windows_i686_msvc" |
| 1261 | version = "0.52.6" |
| 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1263 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" |
| 1264 | @@ -3350,6 +4137,12 @@ checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" |
| 1265 | |
| 1266 | [[package]] |
| 1267 | name = "windows_x86_64_gnu" |
| 1268 | + version = "0.48.5" |
| 1269 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1270 | + checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" |
| 1271 | + |
| 1272 | + [[package]] |
| 1273 | + name = "windows_x86_64_gnu" |
| 1274 | version = "0.52.6" |
| 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1276 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" |
| 1277 | @@ -3362,6 +4155,12 @@ checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" |
| 1278 | |
| 1279 | [[package]] |
| 1280 | name = "windows_x86_64_gnullvm" |
| 1281 | + version = "0.48.5" |
| 1282 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1283 | + checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" |
| 1284 | + |
| 1285 | + [[package]] |
| 1286 | + name = "windows_x86_64_gnullvm" |
| 1287 | version = "0.52.6" |
| 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1289 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" |
| 1290 | @@ -3374,6 +4173,12 @@ checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" |
| 1291 | |
| 1292 | [[package]] |
| 1293 | name = "windows_x86_64_msvc" |
| 1294 | + version = "0.48.5" |
| 1295 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1296 | + checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" |
| 1297 | + |
| 1298 | + [[package]] |
| 1299 | + name = "windows_x86_64_msvc" |
| 1300 | version = "0.52.6" |
| 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1302 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" |
| 1303 | diff --git a/Cargo.toml b/Cargo.toml |
| 1304 | index 5cf4932..bf76ee8 100644 |
| 1305 | --- a/Cargo.toml |
| 1306 | +++ b/Cargo.toml |
| 1307 | @@ -3,20 +3,19 @@ resolver = "2" |
| 1308 | members = [ |
| 1309 | "crates/api", |
| 1310 | "crates/config", |
| 1311 | + "crates/cmd", |
| 1312 | "crates/git", |
| 1313 | "crates/logging", |
| 1314 | - "crates/timeutil", |
| 1315 | "crates/identity", |
| 1316 | - # "crates/scheduler", |
| 1317 | - # "crates/database", |
| 1318 | + "crates/timeutil", |
| 1319 | + "crates/database", |
| 1320 | "ayllu", |
| 1321 | - # "ayllu-build", |
| 1322 | + "ayllu-build", |
| 1323 | # "ayllu-mail", |
| 1324 | "ayllu-shell", |
| 1325 | "ayllu-keys", |
| 1326 | - # "ayllu-jobs", |
| 1327 | - # "ayllu-xmpp", |
| 1328 | - "quipu", "crates/identity", "crates/cmd", "xtask", |
| 1329 | + "quipu", |
| 1330 | + "xtask", "ayllu-migrate", |
| 1331 | ] |
| 1332 | |
| 1333 | [workspace.dependencies] |
| 1334 | @@ -25,15 +24,19 @@ bytes = "1.10.1" |
| 1335 | clap = { version = "4.4.18", features = ["derive"] } |
| 1336 | clap_complete = { version = "4.4.10" } |
| 1337 | serde = { version = "1.0", features = ["derive"] } |
| 1338 | + serde_json = "1.0.108" |
| 1339 | + petgraph = { version = "0.6.4", features = ["serde-1"] } |
| 1340 | git2 = { version = "0.20.2", default-features = false, features = [] } |
| 1341 | rand = "0.9.1" |
| 1342 | thiserror = "2.0.12" |
| 1343 | tracing = { version = "0.1.41", features=["log"] } |
| 1344 | toml = "0.8.23" |
| 1345 | + time = "0.3.41" |
| 1346 | futures = "0.3.31" |
| 1347 | tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } |
| 1348 | openssh-keys = "0.6.4" |
| 1349 | url = { version = "2.5.4", features = ["serde"]} |
| 1350 | + sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite"] } |
| 1351 | |
| 1352 | tokio = { version = "1.46.1", features = ["full"] } |
| 1353 | tokio-util = { version = "0.7.15", features = ["io", "compat"] } |
| 1354 | diff --git a/ayllu-build/Cargo.toml b/ayllu-build/Cargo.toml |
| 1355 | index 0cdede2..83886cd 100644 |
| 1356 | --- a/ayllu-build/Cargo.toml |
| 1357 | +++ b/ayllu-build/Cargo.toml |
| 1358 | @@ -10,20 +10,18 @@ name = "ayllu-build" |
| 1359 | ayllu_api = {path = "../crates/api"} |
| 1360 | ayllu_config = {path = "../crates/config"} |
| 1361 | ayllu_database = {path = "../crates/database"} |
| 1362 | - ayllu_rpc = {path = "../crates/rpc"} |
| 1363 | + ayllu_logging = {path = "../crates/logging"} |
| 1364 | + # ayllu_rpc = {path = "../crates/rpc"} |
| 1365 | ayllu_git = {path = "../crates/git"} |
| 1366 | |
| 1367 | - anyhow = "1.0.75" |
| 1368 | - clap = "4.4.8" |
| 1369 | - nickel-lang-core = { version = "0.3.0", default-features = false } |
| 1370 | - petgraph = "0.6.4" |
| 1371 | - rand = "0.8.5" |
| 1372 | - serde = { version = "1.0", features = ["derive"] } |
| 1373 | - tracing = "0.1.40" |
| 1374 | - tracing-subscriber = "0.3.18" |
| 1375 | - async-trait = "0.1.74" |
| 1376 | - sqlx = { version = "0.7.3", features = ["sqlite", "macros"] } |
| 1377 | - tokio = { version = "1.34.0", features = ["full"] } |
| 1378 | + async-trait = { workspace = true } |
| 1379 | + clap = { workspace = true } |
| 1380 | + clap_complete = { workspace = true } |
| 1381 | + tracing = { workspace = true } |
| 1382 | + rand = { workspace = true } |
| 1383 | + serde = { workspace = true } |
| 1384 | + petgraph = { workspace = true } |
| 1385 | + tokio = { workspace = true } |
| 1386 | + |
| 1387 | sysinfo = "0.29.11" |
| 1388 | serde_json = "1.0.108" |
| 1389 | - clap_complete = "4.4.9" |
| 1390 | diff --git a/ayllu-build/migrations/20231204194038_init.sql b/ayllu-build/migrations/20231204194038_init.sql |
| 1391 | deleted file mode 100644 |
| 1392 | index e072e06..0000000 |
| 1393 | --- a/ayllu-build/migrations/20231204194038_init.sql |
| 1394 | +++ /dev/null |
| 1395 | @@ -1,54 +0,0 @@ |
| 1396 | - CREATE TABLE manifests ( |
| 1397 | - id INTEGER PRIMARY KEY, |
| 1398 | - repository_url TEXT NOT NULL, |
| 1399 | - git_hash TEXT NOT NULL, |
| 1400 | - created_at INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 1401 | - started_at INTEGER CHECK (started_at > 0), |
| 1402 | - duration INTEGER CHECK (duration > 0) |
| 1403 | - ) STRICT ; |
| 1404 | - |
| 1405 | - CREATE TABLE workflows ( |
| 1406 | - id INTEGER PRIMARY KEY, |
| 1407 | - manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 1408 | - name TEXT NOT NULL, |
| 1409 | - started_at INTEGER CHECK (started_at > 0), |
| 1410 | - duration INTEGER CHECK (duration > 0) |
| 1411 | - ) STRICT ; |
| 1412 | - |
| 1413 | - CREATE TABLE steps ( |
| 1414 | - id INTEGER PRIMARY KEY, |
| 1415 | - name TEXT NOT NULL, |
| 1416 | - workflow_id INTEGER REFERENCES workflows(id) ON DELETE CASCADE NOT NULL, |
| 1417 | - shell TEXT NOT NULL DEFAULT "/bin/sh", |
| 1418 | - environment_json TEXT, |
| 1419 | - input TEXT NOT NULL, |
| 1420 | - started_at INTEGER CHECK (started_at > 0), |
| 1421 | - duration INTEGER CHECK (duration > 0), |
| 1422 | - stdout TEXT, |
| 1423 | - stderr TEXT, |
| 1424 | - exit_code INTEGER |
| 1425 | - ) STRICT ; |
| 1426 | - |
| 1427 | - CREATE TABLE dags ( |
| 1428 | - id INTEGER PRIMARY KEY, |
| 1429 | - manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 1430 | - dot_content TEXT NOT NULL |
| 1431 | - ) STRICT ; |
| 1432 | - |
| 1433 | - CREATE TABLE samples ( |
| 1434 | - id INTEGER PRIMARY KEY, |
| 1435 | - manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 1436 | - timestamp INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 1437 | - load_1m INTEGER, |
| 1438 | - load_5m INTEGER, |
| 1439 | - load_15m INTEGER, |
| 1440 | - disk_total_bytes INTEGER, |
| 1441 | - disk_free_bytes INTEGER, |
| 1442 | - net_sent_bytes INTEGER, |
| 1443 | - net_received_bytes INTEGER, |
| 1444 | - net_sent_packets INTEGER, |
| 1445 | - net_received_packets INTEGER, |
| 1446 | - mem_total_bytes INTEGER, |
| 1447 | - mem_free_bytes INTEGER, |
| 1448 | - mem_available_bytes INTEGER |
| 1449 | - ) STRICT ; |
| 1450 | diff --git a/ayllu-build/queries/dags_create.sql b/ayllu-build/queries/dags_create.sql |
| 1451 | deleted file mode 100644 |
| 1452 | index 7214c60..0000000 |
| 1453 | --- a/ayllu-build/queries/dags_create.sql |
| 1454 | +++ /dev/null |
| 1455 | @@ -1,2 +0,0 @@ |
| 1456 | - INSERT INTO dags (manifest_id, dot_content) |
| 1457 | - VALUES (?, ?) RETURNING id |
| 1458 | diff --git a/ayllu-build/queries/manifests_create.sql b/ayllu-build/queries/manifests_create.sql |
| 1459 | deleted file mode 100644 |
| 1460 | index a7ded3e..0000000 |
| 1461 | --- a/ayllu-build/queries/manifests_create.sql |
| 1462 | +++ /dev/null |
| 1463 | @@ -1,2 +0,0 @@ |
| 1464 | - INSERT INTO manifests (repository_url, git_hash) |
| 1465 | - VALUES (?, ?) RETURNING id |
| 1466 | diff --git a/ayllu-build/queries/manifests_list.sql b/ayllu-build/queries/manifests_list.sql |
| 1467 | deleted file mode 100644 |
| 1468 | index af58a4e..0000000 |
| 1469 | --- a/ayllu-build/queries/manifests_list.sql |
| 1470 | +++ /dev/null |
| 1471 | @@ -1,11 +0,0 @@ |
| 1472 | - SELECT id, |
| 1473 | - repository_url, |
| 1474 | - git_hash, |
| 1475 | - created_at, |
| 1476 | - started_at, |
| 1477 | - finished_at, |
| 1478 | - success |
| 1479 | - FROM manifests |
| 1480 | - WHERE id = ? |
| 1481 | - LIMIT ? |
| 1482 | - OFFSET ? |
| 1483 | diff --git a/ayllu-build/queries/manifests_read.sql b/ayllu-build/queries/manifests_read.sql |
| 1484 | deleted file mode 100644 |
| 1485 | index 073fa75..0000000 |
| 1486 | --- a/ayllu-build/queries/manifests_read.sql |
| 1487 | +++ /dev/null |
| 1488 | @@ -1,10 +0,0 @@ |
| 1489 | - SELECT manifests.id, |
| 1490 | - repository_url, |
| 1491 | - git_hash, |
| 1492 | - created_at, |
| 1493 | - started_at, |
| 1494 | - duration, |
| 1495 | - dags.dot_content AS "dot_content!" |
| 1496 | - FROM manifests |
| 1497 | - LEFT JOIN dags ON dags.manifest_id = manifests.id |
| 1498 | - WHERE manifests.id = ? |
| 1499 | diff --git a/ayllu-build/queries/manifests_update_finish.sql b/ayllu-build/queries/manifests_update_finish.sql |
| 1500 | deleted file mode 100644 |
| 1501 | index 52f4016..0000000 |
| 1502 | --- a/ayllu-build/queries/manifests_update_finish.sql |
| 1503 | +++ /dev/null |
| 1504 | @@ -1,4 +0,0 @@ |
| 1505 | - UPDATE manifests |
| 1506 | - SET |
| 1507 | - duration = ? |
| 1508 | - WHERE id = ? |
| 1509 | diff --git a/ayllu-build/queries/manifests_update_start.sql b/ayllu-build/queries/manifests_update_start.sql |
| 1510 | deleted file mode 100644 |
| 1511 | index fc85a4d..0000000 |
| 1512 | --- a/ayllu-build/queries/manifests_update_start.sql |
| 1513 | +++ /dev/null |
| 1514 | @@ -1,3 +0,0 @@ |
| 1515 | - UPDATE manifests |
| 1516 | - SET started_at = UNIXEPOCH() |
| 1517 | - WHERE id = ? |
| 1518 | diff --git a/ayllu-build/queries/samples_create.sql b/ayllu-build/queries/samples_create.sql |
| 1519 | deleted file mode 100644 |
| 1520 | index 7fc297f..0000000 |
| 1521 | --- a/ayllu-build/queries/samples_create.sql |
| 1522 | +++ /dev/null |
| 1523 | @@ -1,18 +0,0 @@ |
| 1524 | - INSERT INTO samples |
| 1525 | - ( |
| 1526 | - manifest_id, |
| 1527 | - load_1m, |
| 1528 | - load_5m, |
| 1529 | - load_15m, |
| 1530 | - disk_total_bytes, |
| 1531 | - disk_free_bytes, |
| 1532 | - net_sent_bytes, |
| 1533 | - net_received_bytes, |
| 1534 | - net_sent_packets, |
| 1535 | - net_received_packets, |
| 1536 | - mem_total_bytes, |
| 1537 | - mem_free_bytes, |
| 1538 | - mem_available_bytes |
| 1539 | - ) |
| 1540 | - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) |
| 1541 | - RETURNING id |
| 1542 | diff --git a/ayllu-build/queries/samples_read.sql b/ayllu-build/queries/samples_read.sql |
| 1543 | deleted file mode 100644 |
| 1544 | index 6842939..0000000 |
| 1545 | --- a/ayllu-build/queries/samples_read.sql |
| 1546 | +++ /dev/null |
| 1547 | @@ -1,15 +0,0 @@ |
| 1548 | - SELECT id, |
| 1549 | - load_1m, |
| 1550 | - load_5m, |
| 1551 | - load_15m, |
| 1552 | - disk_total_bytes, |
| 1553 | - disk_free_bytes, |
| 1554 | - net_sent_bytes, |
| 1555 | - net_received_bytes, |
| 1556 | - net_sent_packets, |
| 1557 | - net_received_packets, |
| 1558 | - mem_total_bytes, |
| 1559 | - mem_free_bytes, |
| 1560 | - mem_available_bytes |
| 1561 | - FROM samples |
| 1562 | - WHERE manifest_id = ? |
| 1563 | diff --git a/ayllu-build/queries/steps_create.sql b/ayllu-build/queries/steps_create.sql |
| 1564 | deleted file mode 100644 |
| 1565 | index ababf23..0000000 |
| 1566 | --- a/ayllu-build/queries/steps_create.sql |
| 1567 | +++ /dev/null |
| 1568 | @@ -1,2 +0,0 @@ |
| 1569 | - INSERT INTO steps (workflow_id, name, input, shell, environment_json) |
| 1570 | - VALUES (?, ?, ?, ?, json_array(?)) RETURNING id |
| 1571 | diff --git a/ayllu-build/queries/steps_list.sql b/ayllu-build/queries/steps_list.sql |
| 1572 | deleted file mode 100644 |
| 1573 | index 7aa1ee7..0000000 |
| 1574 | --- a/ayllu-build/queries/steps_list.sql |
| 1575 | +++ /dev/null |
| 1576 | @@ -1,10 +0,0 @@ |
| 1577 | - SELECT id, |
| 1578 | - name, |
| 1579 | - input, |
| 1580 | - stdout, |
| 1581 | - stderr, |
| 1582 | - started_at, |
| 1583 | - duration, |
| 1584 | - exit_code |
| 1585 | - FROM steps |
| 1586 | - WHERE workflow_id = ? |
| 1587 | diff --git a/ayllu-build/queries/steps_read.sql b/ayllu-build/queries/steps_read.sql |
| 1588 | deleted file mode 100644 |
| 1589 | index efd3761..0000000 |
| 1590 | --- a/ayllu-build/queries/steps_read.sql |
| 1591 | +++ /dev/null |
| 1592 | @@ -1 +0,0 @@ |
| 1593 | - SELECT * FROM steps WHERE workflow_id = ? |
| 1594 | diff --git a/ayllu-build/queries/steps_update_finish.sql b/ayllu-build/queries/steps_update_finish.sql |
| 1595 | deleted file mode 100644 |
| 1596 | index 60293fc..0000000 |
| 1597 | --- a/ayllu-build/queries/steps_update_finish.sql |
| 1598 | +++ /dev/null |
| 1599 | @@ -1,8 +0,0 @@ |
| 1600 | - UPDATE steps |
| 1601 | - SET |
| 1602 | - duration = ?, |
| 1603 | - stdout = ?, |
| 1604 | - stderr = ?, |
| 1605 | - exit_code = ? |
| 1606 | - WHERE |
| 1607 | - id = ? |
| 1608 | diff --git a/ayllu-build/queries/steps_update_start.sql b/ayllu-build/queries/steps_update_start.sql |
| 1609 | deleted file mode 100644 |
| 1610 | index 387654b..0000000 |
| 1611 | --- a/ayllu-build/queries/steps_update_start.sql |
| 1612 | +++ /dev/null |
| 1613 | @@ -1,5 +0,0 @@ |
| 1614 | - UPDATE steps |
| 1615 | - SET |
| 1616 | - started_at = UNIXEPOCH() |
| 1617 | - WHERE |
| 1618 | - id = ? |
| 1619 | diff --git a/ayllu-build/queries/workflows_create.sql b/ayllu-build/queries/workflows_create.sql |
| 1620 | deleted file mode 100644 |
| 1621 | index 0063b5f..0000000 |
| 1622 | --- a/ayllu-build/queries/workflows_create.sql |
| 1623 | +++ /dev/null |
| 1624 | @@ -1,2 +0,0 @@ |
| 1625 | - INSERT INTO workflows (manifest_id, name) |
| 1626 | - VALUES (?, ?) RETURNING id |
| 1627 | diff --git a/ayllu-build/queries/workflows_list.sql b/ayllu-build/queries/workflows_list.sql |
| 1628 | deleted file mode 100644 |
| 1629 | index b0cb1fc..0000000 |
| 1630 | --- a/ayllu-build/queries/workflows_list.sql |
| 1631 | +++ /dev/null |
| 1632 | @@ -1,6 +0,0 @@ |
| 1633 | - SELECT id, |
| 1634 | - name, |
| 1635 | - started_at, |
| 1636 | - duration |
| 1637 | - FROM workflows |
| 1638 | - WHERE manifest_id = ? |
| 1639 | diff --git a/ayllu-build/queries/workflows_read.sql b/ayllu-build/queries/workflows_read.sql |
| 1640 | deleted file mode 100644 |
| 1641 | index 5752bfd..0000000 |
| 1642 | --- a/ayllu-build/queries/workflows_read.sql |
| 1643 | +++ /dev/null |
| 1644 | @@ -1 +0,0 @@ |
| 1645 | - SELECT * FROM workflows WHERE manifest_id = ? |
| 1646 | diff --git a/ayllu-build/queries/workflows_update_finish.sql b/ayllu-build/queries/workflows_update_finish.sql |
| 1647 | deleted file mode 100644 |
| 1648 | index d4d2476..0000000 |
| 1649 | --- a/ayllu-build/queries/workflows_update_finish.sql |
| 1650 | +++ /dev/null |
| 1651 | @@ -1,5 +0,0 @@ |
| 1652 | - UPDATE workflows |
| 1653 | - SET |
| 1654 | - duration = ? |
| 1655 | - WHERE |
| 1656 | - id = ? |
| 1657 | diff --git a/ayllu-build/queries/workflows_update_start.sql b/ayllu-build/queries/workflows_update_start.sql |
| 1658 | deleted file mode 100644 |
| 1659 | index 11be057..0000000 |
| 1660 | --- a/ayllu-build/queries/workflows_update_start.sql |
| 1661 | +++ /dev/null |
| 1662 | @@ -1,5 +0,0 @@ |
| 1663 | - UPDATE workflows |
| 1664 | - SET |
| 1665 | - started_at = UNIXEPOCH() |
| 1666 | - WHERE |
| 1667 | - id = ? |
| 1668 | diff --git a/ayllu-build/src/config.rs b/ayllu-build/src/config.rs |
| 1669 | index 7f34e57..eff7909 100644 |
| 1670 | --- a/ayllu-build/src/config.rs |
| 1671 | +++ b/ayllu-build/src/config.rs |
| 1672 | @@ -1,56 +1,44 @@ |
| 1673 | - use std::path::Path; |
| 1674 | + use std::path::{Path, PathBuf}; |
| 1675 | |
| 1676 | use serde::{Deserialize, Serialize}; |
| 1677 | |
| 1678 | - use ayllu_config::{data_dir, runtime_dir, Configurable, Error, Reader}; |
| 1679 | + use ayllu_config::{data_dir, runtime_dir, Configurable, Database, Error, Reader}; |
| 1680 | |
| 1681 | #[derive(Deserialize, Serialize, Clone, Debug)] |
| 1682 | - pub struct Database { |
| 1683 | - #[serde(default = "Database::path_default")] |
| 1684 | - pub path: String, |
| 1685 | - #[serde(default = "Database::migrate_default")] |
| 1686 | - pub migrate: bool, |
| 1687 | + pub struct Builder { |
| 1688 | + #[serde(default = "Builder::address_default")] |
| 1689 | + pub address: String, |
| 1690 | + #[serde(default = "Builder::log_path_default")] |
| 1691 | + pub log_path: PathBuf, |
| 1692 | } |
| 1693 | |
| 1694 | - impl Database { |
| 1695 | - fn path_default() -> String { |
| 1696 | - let mut data_path = data_dir(); |
| 1697 | - data_path.push("worker.db"); |
| 1698 | - String::from(data_path.to_str().unwrap()) |
| 1699 | + impl Builder { |
| 1700 | + fn address_default() -> String { |
| 1701 | + runtime_dir().to_str().unwrap().to_string() + "/ayllu-build.sock" |
| 1702 | } |
| 1703 | |
| 1704 | - fn migrate_default() -> bool { |
| 1705 | - true |
| 1706 | + fn log_path_default() -> PathBuf { |
| 1707 | + data_dir().join("worker_logs") |
| 1708 | } |
| 1709 | } |
| 1710 | |
| 1711 | - #[derive(Deserialize, Serialize, Clone, Debug)] |
| 1712 | - pub struct Builder { |
| 1713 | - #[serde(default = "Config::address_default")] |
| 1714 | - pub address: String, |
| 1715 | - pub database: Database, |
| 1716 | - #[serde(default = "Config::log_path")] |
| 1717 | - pub log_path: String, |
| 1718 | + impl Default for Builder { |
| 1719 | + fn default() -> Self { |
| 1720 | + Self { |
| 1721 | + address: Builder::address_default(), |
| 1722 | + log_path: Builder::log_path_default(), |
| 1723 | + } |
| 1724 | + } |
| 1725 | } |
| 1726 | |
| 1727 | #[derive(Deserialize, Serialize, Clone, Debug)] |
| 1728 | pub struct Config { |
| 1729 | - pub log_level: String, |
| 1730 | + #[serde(default = "Database::default")] |
| 1731 | + pub database: Database, |
| 1732 | + #[serde(default = "Builder::default")] |
| 1733 | pub builder: Builder, |
| 1734 | } |
| 1735 | |
| 1736 | - impl Config { |
| 1737 | - fn address_default() -> String { |
| 1738 | - runtime_dir().to_str().unwrap().to_string() + "/ayllu-build.sock" |
| 1739 | - } |
| 1740 | - |
| 1741 | - fn log_path() -> String { |
| 1742 | - let mut data_path = data_dir(); |
| 1743 | - data_path.push("worker_logs"); |
| 1744 | - data_path.to_str().unwrap().to_string() |
| 1745 | - } |
| 1746 | - } |
| 1747 | - |
| 1748 | impl Configurable for Config {} |
| 1749 | |
| 1750 | pub fn load(path: Option<&Path>) -> Result<Config, Error> { |
| 1751 | diff --git a/ayllu-build/src/error.rs b/ayllu-build/src/error.rs |
| 1752 | new file mode 100644 |
| 1753 | index 0000000..c91a359 |
| 1754 | --- /dev/null |
| 1755 | +++ b/ayllu-build/src/error.rs |
| 1756 | @@ -0,0 +1,44 @@ |
| 1757 | + use std::path::PathBuf; |
| 1758 | + |
| 1759 | + #[derive(Debug)] |
| 1760 | + pub enum Error { |
| 1761 | + CannotReadManifest { |
| 1762 | + path: PathBuf, |
| 1763 | + io_err: std::io::Error, |
| 1764 | + }, |
| 1765 | + InvalidManifest { |
| 1766 | + path: PathBuf, |
| 1767 | + json_err: serde_json::Error, |
| 1768 | + }, |
| 1769 | + EmptyWorkflow { |
| 1770 | + name: String, |
| 1771 | + }, |
| 1772 | + CycleDetected, |
| 1773 | + DuplicateStepNames { |
| 1774 | + name: String, |
| 1775 | + }, |
| 1776 | + DuplicateWorkflows, |
| 1777 | + // general io error during execution |
| 1778 | + Io(std::io::Error), |
| 1779 | + Db(ayllu_database::Error), |
| 1780 | + } |
| 1781 | + |
| 1782 | + impl std::fmt::Display for Error { |
| 1783 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 1784 | + todo!() |
| 1785 | + } |
| 1786 | + } |
| 1787 | + |
| 1788 | + impl std::error::Error for Error {} |
| 1789 | + |
| 1790 | + impl From<ayllu_database::Error> for Error { |
| 1791 | + fn from(value: ayllu_database::Error) -> Self { |
| 1792 | + Error::Db(value) |
| 1793 | + } |
| 1794 | + } |
| 1795 | + |
| 1796 | + impl From<std::io::Error> for Error { |
| 1797 | + fn from(value: std::io::Error) -> Self { |
| 1798 | + Error::Io(value) |
| 1799 | + } |
| 1800 | + } |
| 1801 | diff --git a/ayllu-build/src/evaluate.rs b/ayllu-build/src/evaluate.rs |
| 1802 | index 644b4d1..9c9e0eb 100644 |
| 1803 | --- a/ayllu-build/src/evaluate.rs |
| 1804 | +++ b/ayllu-build/src/evaluate.rs |
| 1805 | @@ -1,114 +1,27 @@ |
| 1806 | use std::collections::HashMap; |
| 1807 | - use std::fmt::Display; |
| 1808 | use std::fs::metadata; |
| 1809 | use std::path::PathBuf; |
| 1810 | - use std::time::Instant; |
| 1811 | |
| 1812 | - use anyhow::{format_err, Result}; |
| 1813 | use petgraph::{ |
| 1814 | algo::is_cyclic_directed, |
| 1815 | dot::Dot, |
| 1816 | graph::{Graph, NodeIndex}, |
| 1817 | visit::Topo, |
| 1818 | }; |
| 1819 | - use serde::Deserialize; |
| 1820 | - use tracing::log::{debug, info, warn}; |
| 1821 | |
| 1822 | - use crate::database_ext::BuildExt; |
| 1823 | - use crate::executor::{Context, Executor, Local}; |
| 1824 | - use crate::models::{Manifest, Step, Workflow}; |
| 1825 | - use ayllu_database::Wrapper as Database; |
| 1826 | - |
| 1827 | - type Ids<'a> = HashMap<&'a str, (i64, HashMap<&'a str, i64>)>; |
| 1828 | - |
| 1829 | - pub(crate) struct State<'a> { |
| 1830 | - start_time: Instant, |
| 1831 | - ids: Ids<'a>, |
| 1832 | - // active workflow |
| 1833 | - workflow: Option<(String, Instant)>, |
| 1834 | - // active step |
| 1835 | - step: Option<(String, Instant)>, |
| 1836 | - } |
| 1837 | - |
| 1838 | - impl<'a> State<'a> { |
| 1839 | - pub fn new(ids: Ids<'a>) -> Self { |
| 1840 | - State { |
| 1841 | - start_time: Instant::now(), |
| 1842 | - ids, |
| 1843 | - workflow: None, |
| 1844 | - step: None, |
| 1845 | - } |
| 1846 | - } |
| 1847 | - |
| 1848 | - pub fn id(&self, unit: &Unit) -> i64 { |
| 1849 | - match unit { |
| 1850 | - Unit::Step(step) => match &self.workflow { |
| 1851 | - Some(current) => self.ids[current.0.as_str()].1[step.name.as_str()], |
| 1852 | - None => unreachable!(), |
| 1853 | - }, |
| 1854 | - Unit::Workflow(workflow) => self.ids[workflow.name.as_str()].0, |
| 1855 | - } |
| 1856 | - } |
| 1857 | - |
| 1858 | - pub fn start(&mut self, unit: &Unit) { |
| 1859 | - match unit { |
| 1860 | - Unit::Step(step) => { |
| 1861 | - self.step = Some((step.name.to_string(), Instant::now())); |
| 1862 | - } |
| 1863 | - Unit::Workflow(workflow) => { |
| 1864 | - self.workflow = Some((workflow.name.to_string(), Instant::now())); |
| 1865 | - } |
| 1866 | - } |
| 1867 | - } |
| 1868 | - |
| 1869 | - pub fn current_workflow(&self) -> Option<(i64, i64)> { |
| 1870 | - match &self.workflow { |
| 1871 | - Some(current) => { |
| 1872 | - let id = self.ids[current.0.as_str()].0; |
| 1873 | - let duration = Instant::now().duration_since(current.1).as_millis() as i64; |
| 1874 | - Some((id, duration)) |
| 1875 | - } |
| 1876 | - None => None, |
| 1877 | - } |
| 1878 | - } |
| 1879 | - |
| 1880 | - pub fn current_step(&self) -> Option<(i64, i64)> { |
| 1881 | - match &self.step { |
| 1882 | - Some(current_step) => match &self.workflow { |
| 1883 | - Some(current_workflow) => { |
| 1884 | - let id = self.ids[current_workflow.0.as_str()].1[current_step.0.as_str()]; |
| 1885 | - let duration = Instant::now().duration_since(current_step.1).as_millis() as i64; |
| 1886 | - Some((id, duration)) |
| 1887 | - } |
| 1888 | - None => unreachable!(), |
| 1889 | - }, |
| 1890 | - None => todo!(), |
| 1891 | - } |
| 1892 | - } |
| 1893 | - |
| 1894 | - pub fn runtime(&self) -> i64 { |
| 1895 | - Instant::now().duration_since(self.start_time).as_millis() as i64 |
| 1896 | - } |
| 1897 | - } |
| 1898 | + use crate::models::{Manifest, Step}; |
| 1899 | + use crate::{ |
| 1900 | + error::Error, |
| 1901 | + executor::{Context, Executor, Local}, |
| 1902 | + }; |
| 1903 | + use ayllu_database::{ |
| 1904 | + build::{BuildExt, BuildTx}, |
| 1905 | + Tx, Wrapper as Database, |
| 1906 | + }; |
| 1907 | |
| 1908 | - #[derive(Deserialize, Debug, Clone)] |
| 1909 | - pub enum Unit { |
| 1910 | - Step(Step), |
| 1911 | - Workflow(Workflow), |
| 1912 | - } |
| 1913 | + use ayllu_api::build::Unit; |
| 1914 | |
| 1915 | - impl Display for Unit { |
| 1916 | - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 1917 | - match self { |
| 1918 | - Unit::Step(step) => { |
| 1919 | - write!(f, "Step: {}", step.name) |
| 1920 | - } |
| 1921 | - Unit::Workflow(workflow) => { |
| 1922 | - write!(f, "Workflow: {}", workflow.name) |
| 1923 | - } |
| 1924 | - } |
| 1925 | - } |
| 1926 | - } |
| 1927 | + pub type BuildGraph = Graph<Unit, u8>; |
| 1928 | |
| 1929 | #[derive(Clone)] |
| 1930 | #[allow(dead_code)] |
| 1931 | @@ -121,63 +34,17 @@ pub enum Source { |
| 1932 | Clone((String, String)), |
| 1933 | } |
| 1934 | |
| 1935 | - #[derive(Default)] |
| 1936 | - pub struct RuntimeBuilder { |
| 1937 | - parallelism: bool, |
| 1938 | - tee_output: bool, |
| 1939 | - log_dir: Option<PathBuf>, |
| 1940 | - source: Option<Source>, |
| 1941 | - db: Option<Database>, |
| 1942 | - } |
| 1943 | - |
| 1944 | - impl RuntimeBuilder { |
| 1945 | - pub fn database(mut self, db: Database) -> RuntimeBuilder { |
| 1946 | - self.db = Some(db); |
| 1947 | - self |
| 1948 | - } |
| 1949 | - |
| 1950 | - pub fn source(mut self, source: Source) -> RuntimeBuilder { |
| 1951 | - self.source = Some(source); |
| 1952 | - self |
| 1953 | - } |
| 1954 | - |
| 1955 | - pub fn log_dir(mut self, log_dir: PathBuf) -> RuntimeBuilder { |
| 1956 | - self.log_dir = Some(log_dir); |
| 1957 | - self |
| 1958 | - } |
| 1959 | - |
| 1960 | - pub fn tee_output(mut self, tee_output: bool) -> RuntimeBuilder { |
| 1961 | - self.tee_output = tee_output; |
| 1962 | - self |
| 1963 | - } |
| 1964 | - |
| 1965 | - #[allow(dead_code)] |
| 1966 | - pub fn enable_parallelism(self, _enabled: bool) -> RuntimeBuilder { |
| 1967 | - todo!(); |
| 1968 | - } |
| 1969 | - |
| 1970 | - pub fn build(&self) -> Runtime { |
| 1971 | - Runtime { |
| 1972 | - parallelism: self.parallelism, |
| 1973 | - tee_output: self.tee_output, |
| 1974 | - db: self.db.clone(), |
| 1975 | - source: self.source.clone().unwrap(), |
| 1976 | - log_dir: self.log_dir.clone().unwrap_or(String::from("/tmp").into()), |
| 1977 | - } |
| 1978 | - } |
| 1979 | - } |
| 1980 | - |
| 1981 | #[allow(dead_code)] |
| 1982 | pub(crate) struct Runtime { |
| 1983 | - parallelism: bool, |
| 1984 | - tee_output: bool, |
| 1985 | - db: Option<Database>, |
| 1986 | - source: Source, |
| 1987 | - log_dir: PathBuf, |
| 1988 | + // parallelism: bool, |
| 1989 | + pub tee_output: bool, |
| 1990 | + pub db: Database, |
| 1991 | + pub source: Source, |
| 1992 | + pub log_dir: PathBuf, |
| 1993 | } |
| 1994 | |
| 1995 | impl Runtime { |
| 1996 | - fn setup(&self) -> Result<Manifest> { |
| 1997 | + fn setup(&self) -> Result<Manifest, Error> { |
| 1998 | match &self.source { |
| 1999 | Source::Manifest(manifest) => Ok(manifest.clone()), |
| 2000 | Source::Path(path) => { |
| 2001 | @@ -189,7 +56,10 @@ impl Runtime { |
| 2002 | Manifest::from_dir(path) |
| 2003 | } |
| 2004 | } |
| 2005 | - Err(err) => Err(err.into()), |
| 2006 | + Err(err) => Err(Error::CannotReadManifest { |
| 2007 | + path: path.to_path_buf(), |
| 2008 | + io_err: err, |
| 2009 | + }), |
| 2010 | } |
| 2011 | // let manifest = Manifest::from_path(path)?; |
| 2012 | } |
| 2013 | @@ -197,26 +67,56 @@ impl Runtime { |
| 2014 | } |
| 2015 | } |
| 2016 | |
| 2017 | - pub fn plan(&self) -> Result<Graph<Unit, i32>> { |
| 2018 | + // FIXME: Fundementally broken, assumes everything is a git repo with fragile paths |
| 2019 | + fn git_information(&self) -> Result<(String, String, String), ayllu_git::Error> { |
| 2020 | + let manifest_path = match &self.source { |
| 2021 | + Source::Manifest(_) => todo!(), |
| 2022 | + Source::Path(path_buf) => std::fs::canonicalize(path_buf).unwrap(), |
| 2023 | + Source::Clone(_) => todo!(), |
| 2024 | + }; |
| 2025 | + let repo_path = manifest_path.parent().unwrap(); |
| 2026 | + let (collection, name) = ayllu_git::collection_and_name(repo_path); |
| 2027 | + let repository = ayllu_git::Wrapper::new(repo_path)?; |
| 2028 | + let latest_hash = repository.latest_hash()?.unwrap(); |
| 2029 | + Ok((collection, name, latest_hash)) |
| 2030 | + } |
| 2031 | + |
| 2032 | + /// Allocate the manifest in the database along with it's DAG |
| 2033 | + async fn allocate(&self, tx: &mut Tx) -> Result<(i64, BuildGraph), Error> { |
| 2034 | let manifest = self.setup()?; |
| 2035 | + manifest.validate()?; |
| 2036 | + let (collection, name, git_hash) = self.git_information().unwrap(); |
| 2037 | + let manifest_id = tx.create_manifest(&collection, &name, &git_hash).await?; |
| 2038 | let mut workflows_by_name: HashMap<String, NodeIndex> = HashMap::new(); |
| 2039 | let mut steps_by_name: HashMap<String, HashMap<String, NodeIndex>> = HashMap::new(); |
| 2040 | - let mut graph: Graph<Unit, i32> = Graph::new(); |
| 2041 | + let mut graph: BuildGraph = Graph::new(); |
| 2042 | + // Allocate components into the database |
| 2043 | for workflow in manifest.workflows.iter() { |
| 2044 | if workflow.steps.is_empty() { |
| 2045 | - return Err(format_err!("workflow {} contains no steps", workflow.name)); |
| 2046 | + return Err(Error::EmptyWorkflow { |
| 2047 | + name: workflow.name.clone(), |
| 2048 | + }); |
| 2049 | } |
| 2050 | + let workflow_id = tx.create_workflow(manifest_id, &workflow.name).await?; |
| 2051 | workflows_by_name.insert( |
| 2052 | workflow.name.clone(), |
| 2053 | - graph.add_node(Unit::Workflow(workflow.clone())), |
| 2054 | + graph.add_node(Unit::Workflow(workflow_id)), |
| 2055 | ); |
| 2056 | let mut by_name: HashMap<String, NodeIndex> = HashMap::new(); |
| 2057 | for step in workflow.steps.iter() { |
| 2058 | - by_name.insert(step.name.clone(), graph.add_node(Unit::Step(step.clone()))); |
| 2059 | + let step_id = tx |
| 2060 | + .create_step( |
| 2061 | + workflow_id, |
| 2062 | + &step.name, |
| 2063 | + &step.input, |
| 2064 | + &step.shell, |
| 2065 | + step.environment.clone(), |
| 2066 | + ) |
| 2067 | + .await?; |
| 2068 | + by_name.insert(step.name.clone(), graph.add_node(Unit::Step(step_id))); |
| 2069 | } |
| 2070 | steps_by_name.insert(workflow.name.clone(), by_name); |
| 2071 | } |
| 2072 | - |
| 2073 | // set edges for steps from each workflow |
| 2074 | for workflow in manifest.workflows.iter() { |
| 2075 | let workflow_steps = steps_by_name.get(&workflow.name).unwrap(); |
| 2076 | @@ -228,6 +128,7 @@ impl Runtime { |
| 2077 | } |
| 2078 | } |
| 2079 | } |
| 2080 | + |
| 2081 | for workflow in manifest.workflows.iter() { |
| 2082 | let workflow_index = workflows_by_name.get(&workflow.name).unwrap(); |
| 2083 | let steps_with_no_dependencies: Vec<&Step> = workflow |
| 2084 | @@ -254,82 +155,64 @@ impl Runtime { |
| 2085 | } |
| 2086 | |
| 2087 | if is_cyclic_directed(&graph) { |
| 2088 | - return Err(format_err!("graph contains a cycle")); |
| 2089 | + return Err(Error::CycleDetected); |
| 2090 | } |
| 2091 | |
| 2092 | - Ok(graph) |
| 2093 | - } |
| 2094 | + let dag_json = serde_json::ser::to_string(&graph).unwrap(); |
| 2095 | + |
| 2096 | + tx.create_dag(manifest_id, &dag_json).await?; |
| 2097 | |
| 2098 | - pub fn to_dot(&self, graph: &Graph<Unit, i32>) -> Result<String> { |
| 2099 | - Ok(Dot::to_string(&Dot::with_config(graph, &[]))) |
| 2100 | + Ok((manifest_id, graph)) |
| 2101 | } |
| 2102 | |
| 2103 | - pub async fn eval(&self) -> Result<()> { |
| 2104 | - // TODO: samples |
| 2105 | - let manifest = self.setup()?; |
| 2106 | - let job_graph = self.plan()?; |
| 2107 | - let db = self.db.as_ref().unwrap(); |
| 2108 | - let manifest_id = db.create_manifest("todo", "todo").await?; |
| 2109 | - let graph = self.plan()?; |
| 2110 | - let dag_content = self.to_dot(&graph)?; |
| 2111 | - let dag_id = db.create_dag(manifest_id, &dag_content).await?; |
| 2112 | - info!( |
| 2113 | + /// Allocate a job graph and then execute it sequentially |
| 2114 | + pub async fn evaluate(&self) -> Result<i64, Error> { |
| 2115 | + let mut tx = self.db.begin().await?; |
| 2116 | + let (manifest_id, graph) = match self.allocate(&mut tx).await { |
| 2117 | + Ok(db_op) => { |
| 2118 | + tx.commit().await?; |
| 2119 | + db_op |
| 2120 | + } |
| 2121 | + Err(e) => { |
| 2122 | + tracing::error!("Failed to allocate graph: {e:?}"); |
| 2123 | + tx.rollback().await?; |
| 2124 | + // FIXME rollback but how |
| 2125 | + return Err(e); |
| 2126 | + } |
| 2127 | + }; |
| 2128 | + let dot_string = Dot::new(&graph).to_string(); |
| 2129 | + tracing::info!( |
| 2130 | "evaluating DAG [{}] [n_nodes={}]:\n{}", |
| 2131 | - dag_id, |
| 2132 | - job_graph.node_count(), |
| 2133 | - dag_content |
| 2134 | + manifest_id, |
| 2135 | + graph.node_count(), |
| 2136 | + dot_string |
| 2137 | ); |
| 2138 | - debug!("created manifest: {}", manifest_id); |
| 2139 | - let mut ids: Ids = HashMap::new(); |
| 2140 | - for workflow in manifest.workflows.iter() { |
| 2141 | - let workflow_id = db.create_workflow(manifest_id, &workflow.name).await?; |
| 2142 | - debug!("created workflow {}", workflow_id); |
| 2143 | - let mut step_ids: HashMap<&str, i64> = HashMap::new(); |
| 2144 | - for step in workflow.steps.iter() { |
| 2145 | - let step_id = db |
| 2146 | - .create_step( |
| 2147 | - workflow_id, |
| 2148 | - &step.name, |
| 2149 | - &step.input, |
| 2150 | - &step.shell, |
| 2151 | - step.environment.clone(), |
| 2152 | - ) |
| 2153 | - .await?; |
| 2154 | - debug!("created step {}", step_id); |
| 2155 | - step_ids.insert(step.name.as_str(), step_id); |
| 2156 | - } |
| 2157 | - ids.insert(workflow.name.as_str(), (workflow_id, step_ids)); |
| 2158 | - } |
| 2159 | - |
| 2160 | - db.update_manifest_start(manifest_id).await?; |
| 2161 | - let mut state = State::new(ids); |
| 2162 | - |
| 2163 | + self.db.update_manifest_start(manifest_id).await?; |
| 2164 | // TODO: Currently no parallelism is supported, need to implement the |
| 2165 | // options in the manifest and then break steps into asynchronous chunks |
| 2166 | // that can be run in parallel where appropriate. |
| 2167 | - let mut topo = Topo::new(&job_graph); |
| 2168 | - while let Some(nx) = topo.next(&job_graph) { |
| 2169 | - let unit = &job_graph[nx]; |
| 2170 | + let mut topo = Topo::new(&graph); |
| 2171 | + let mut current_workflow: Option<i64> = None; |
| 2172 | + while let Some(nx) = topo.next(&graph) { |
| 2173 | + let unit = &graph[nx]; |
| 2174 | match unit { |
| 2175 | - Unit::Workflow(workflow) => { |
| 2176 | - info!("starting workflow {}", workflow.name); |
| 2177 | - match state.current_workflow() { |
| 2178 | - Some((current_workflow_id, duration)) => { |
| 2179 | - db.update_workflow_finish(current_workflow_id, duration) |
| 2180 | - .await?; |
| 2181 | - state.start(unit); |
| 2182 | - db.update_workflow_start(state.id(unit)).await?; |
| 2183 | + Unit::Workflow(next_workflow_id) => { |
| 2184 | + let next_workflow = self.db.read_workflow(*next_workflow_id).await?; |
| 2185 | + tracing::info!("starting workflow {}", next_workflow.name); |
| 2186 | + match current_workflow.as_ref() { |
| 2187 | + Some(current_workflow_id) => { |
| 2188 | + self.db.update_workflow_finish(*current_workflow_id).await?; |
| 2189 | } |
| 2190 | None => { |
| 2191 | - state.start(unit); |
| 2192 | - db.update_workflow_start(state.id(unit)).await?; |
| 2193 | + self.db.update_workflow_start(next_workflow.id).await?; |
| 2194 | } |
| 2195 | - } |
| 2196 | + }; |
| 2197 | + current_workflow = Some(*next_workflow_id); |
| 2198 | } |
| 2199 | - Unit::Step(step) => { |
| 2200 | - info!("starting step: {}", step.name); |
| 2201 | - state.start(unit); |
| 2202 | - db.update_step_start(state.id(unit)).await?; |
| 2203 | + Unit::Step(next_step_id) => { |
| 2204 | + let next_step = self.db.read_step(*next_step_id).await?; |
| 2205 | + tracing::info!("starting step: {}", next_step.name); |
| 2206 | + self.db.update_step_start(next_step.id).await?; |
| 2207 | let executor = Local { |
| 2208 | temp_dir: self.log_dir.clone(), |
| 2209 | tee_output: self.tee_output, |
| 2210 | @@ -338,102 +221,102 @@ impl Runtime { |
| 2211 | // TODO: more context |
| 2212 | let ctx = Context { |
| 2213 | manifest_id, |
| 2214 | - workflow_id: state.current_workflow().unwrap().0, |
| 2215 | + workflow_id: current_workflow.unwrap(), |
| 2216 | ..Default::default() |
| 2217 | }; |
| 2218 | |
| 2219 | - let (stdout, stderr, exit_code) = executor.execute(step, ctx)?; |
| 2220 | + let (stdout, stderr, exit_code) = executor.execute(&next_step, ctx)?; |
| 2221 | if !exit_code.success() { |
| 2222 | - warn!("step {} has failed: {:?}", step.name, exit_code); |
| 2223 | + tracing::warn!("step {} has failed: {:?}", next_step.name, exit_code); |
| 2224 | } |
| 2225 | - let (step_id, duration) = state.current_step().unwrap(); |
| 2226 | - db.update_step_finish( |
| 2227 | - step_id, |
| 2228 | - duration, |
| 2229 | - &stdout, |
| 2230 | - &stderr, |
| 2231 | - exit_code.code().unwrap() as i8, |
| 2232 | - ) |
| 2233 | - .await?; |
| 2234 | + // let (step_id, duration) = state.current_step().unwrap(); |
| 2235 | + self.db |
| 2236 | + .update_step_finish( |
| 2237 | + *next_step_id, |
| 2238 | + &stdout, |
| 2239 | + &stderr, |
| 2240 | + exit_code.code().unwrap() as i8, |
| 2241 | + ) |
| 2242 | + .await?; |
| 2243 | } |
| 2244 | } |
| 2245 | } |
| 2246 | // clean up last workflow |
| 2247 | - if let Some((id, duration)) = state.current_workflow() { |
| 2248 | - db.update_workflow_finish(id, duration).await?; |
| 2249 | + if let Some(id) = current_workflow { |
| 2250 | + self.db.update_workflow_finish(id).await?; |
| 2251 | } |
| 2252 | |
| 2253 | - db.update_manifest_finish(manifest_id, state.runtime()) |
| 2254 | - .await?; |
| 2255 | - Ok(()) |
| 2256 | + self.db.update_manifest_finish(manifest_id).await?; |
| 2257 | + |
| 2258 | + Ok(manifest_id) |
| 2259 | } |
| 2260 | } |
| 2261 | |
| 2262 | #[cfg(test)] |
| 2263 | mod tests { |
| 2264 | |
| 2265 | - use super::*; |
| 2266 | - use std::path::Path; |
| 2267 | - |
| 2268 | - use ayllu_database::Builder; |
| 2269 | - |
| 2270 | - #[tokio::test] |
| 2271 | - async fn test_manifest_simple() { |
| 2272 | - let db = Builder::default() |
| 2273 | - .migrations("./migrations") |
| 2274 | - .build() |
| 2275 | - .await |
| 2276 | - .expect("failed to setup db"); |
| 2277 | - let rt = RuntimeBuilder::default() |
| 2278 | - .source(Source::Path(PathBuf::from("tests/simple.ncl"))) |
| 2279 | - .log_dir(Path::new("logs").to_path_buf()) |
| 2280 | - .database(db.clone()) |
| 2281 | - .build(); |
| 2282 | - rt.eval().await.expect("failed to evaluate manifest"); |
| 2283 | - let normalized = db |
| 2284 | - .read_manifest(1) |
| 2285 | - .await |
| 2286 | - .expect("failed to retreive manifest"); |
| 2287 | - assert!(normalized.manifest.id == 1); |
| 2288 | - let workflow = normalized |
| 2289 | - .workflows |
| 2290 | - .first() |
| 2291 | - .expect("first workflow is missing"); |
| 2292 | - assert!(workflow.name == "Simple"); |
| 2293 | - assert!(workflow.duration.is_some_and(|duration| duration > 0)); |
| 2294 | - let steps = normalized |
| 2295 | - .steps |
| 2296 | - .first() |
| 2297 | - .expect("missing first set of steps"); |
| 2298 | - let step_1 = steps.first().expect("first step is missing"); |
| 2299 | - assert!(step_1.id == 1); |
| 2300 | - assert!(step_1.name == "Hello"); |
| 2301 | - assert!(step_1 |
| 2302 | - .stdout |
| 2303 | - .as_ref() |
| 2304 | - .is_some_and(|output| output == "Hello")); |
| 2305 | - let step_2 = steps.get(1).expect("second step is missing"); |
| 2306 | - assert!(step_2.id == 2); |
| 2307 | - assert!(step_2.name == "World"); |
| 2308 | - assert!(step_2 |
| 2309 | - .stdout |
| 2310 | - .as_ref() |
| 2311 | - .is_some_and(|output| output == "World")); |
| 2312 | - } |
| 2313 | - |
| 2314 | - #[tokio::test] |
| 2315 | - async fn test_manifest_complex() { |
| 2316 | - let db = Builder::default() |
| 2317 | - .migrations("./migrations") |
| 2318 | - .build() |
| 2319 | - .await |
| 2320 | - .expect("failed to setup db"); |
| 2321 | - let rt = RuntimeBuilder::default() |
| 2322 | - .source(Source::Path(PathBuf::from("tests/complex.ncl"))) |
| 2323 | - .log_dir(Path::new("logs").to_path_buf()) |
| 2324 | - .database(db.clone()) |
| 2325 | - .build(); |
| 2326 | - rt.eval().await.expect("failed to evaluate manifest"); |
| 2327 | - // TODO order of evaluation needs to be preserved and tested |
| 2328 | - } |
| 2329 | + // use super::*; |
| 2330 | + // use std::path::Path; |
| 2331 | + |
| 2332 | + // use ayllu_database::Builder; |
| 2333 | + |
| 2334 | + // #[tokio::test] |
| 2335 | + // async fn test_manifest_simple() { |
| 2336 | + // let db = Builder::default() |
| 2337 | + // .migrations(Path::new("./migrations")) |
| 2338 | + // .build() |
| 2339 | + // .await |
| 2340 | + // .expect("failed to setup db"); |
| 2341 | + // let rt = RuntimeBuilder::default() |
| 2342 | + // .source(Source::Path(PathBuf::from("tests/simple.json"))) |
| 2343 | + // .log_dir(Path::new("logs").to_path_buf()) |
| 2344 | + // .database(db.clone()) |
| 2345 | + // .build(); |
| 2346 | + // rt.eval().await.expect("failed to evaluate manifest"); |
| 2347 | + // let normalized = db |
| 2348 | + // .read_manifest(1) |
| 2349 | + // .await |
| 2350 | + // .expect("failed to retreive manifest"); |
| 2351 | + // assert!(normalized.manifest.id == 1); |
| 2352 | + // let workflow = normalized |
| 2353 | + // .workflows |
| 2354 | + // .first() |
| 2355 | + // .expect("first workflow is missing"); |
| 2356 | + // assert!(workflow.name == "Simple"); |
| 2357 | + // assert!(workflow.duration.is_some_and(|duration| duration > 0)); |
| 2358 | + // let steps = normalized |
| 2359 | + // .steps |
| 2360 | + // .first() |
| 2361 | + // .expect("missing first set of steps"); |
| 2362 | + // let step_1 = steps.first().expect("first step is missing"); |
| 2363 | + // assert!(step_1.id == 1); |
| 2364 | + // assert!(step_1.name == "Hello"); |
| 2365 | + // assert!(step_1 |
| 2366 | + // .stdout |
| 2367 | + // .as_ref() |
| 2368 | + // .is_some_and(|output| output == "Hello")); |
| 2369 | + // let step_2 = steps.get(1).expect("second step is missing"); |
| 2370 | + // assert!(step_2.id == 2); |
| 2371 | + // assert!(step_2.name == "World"); |
| 2372 | + // assert!(step_2 |
| 2373 | + // .stdout |
| 2374 | + // .as_ref() |
| 2375 | + // .is_some_and(|output| output == "World")); |
| 2376 | + // } |
| 2377 | + |
| 2378 | + // #[tokio::test] |
| 2379 | + // async fn test_manifest_complex() { |
| 2380 | + // let db = Builder::default() |
| 2381 | + // .migrations("./migrations") |
| 2382 | + // .build() |
| 2383 | + // .await |
| 2384 | + // .expect("failed to setup db"); |
| 2385 | + // let rt = RuntimeBuilder::default() |
| 2386 | + // .source(Source::Path(PathBuf::from("tests/complex.ncl"))) |
| 2387 | + // .log_dir(Path::new("logs").to_path_buf()) |
| 2388 | + // .database(db.clone()) |
| 2389 | + // .build(); |
| 2390 | + // rt.eval().await.expect("failed to evaluate manifest"); |
| 2391 | + // // TODO order of evaluation needs to be preserved and tested |
| 2392 | + // } |
| 2393 | } |
| 2394 | diff --git a/ayllu-build/src/executor.rs b/ayllu-build/src/executor.rs |
| 2395 | index 56371aa..a97e2d7 100644 |
| 2396 | --- a/ayllu-build/src/executor.rs |
| 2397 | +++ b/ayllu-build/src/executor.rs |
| 2398 | @@ -10,11 +10,11 @@ use std::{ |
| 2399 | io::{Read, Write}, |
| 2400 | }; |
| 2401 | |
| 2402 | - use anyhow::Result; |
| 2403 | + use ayllu_database::build::Step; |
| 2404 | use serde::Deserialize; |
| 2405 | use tracing::log::{debug, info}; |
| 2406 | |
| 2407 | - use crate::models::Step; |
| 2408 | + use crate::error::Error; |
| 2409 | |
| 2410 | /// standard stream when logging output |
| 2411 | enum Output { |
| 2412 | @@ -42,12 +42,14 @@ pub struct Context { |
| 2413 | pub workflow_id: i64, |
| 2414 | pub git_hash: String, |
| 2415 | pub repo_url: String, |
| 2416 | + pub environment: HashMap<String, Option<String>>, |
| 2417 | } |
| 2418 | |
| 2419 | // An executor runs the step in a process container of some kind. Currently |
| 2420 | // the only executor that exists is the Local exector. |
| 2421 | pub trait Executor { |
| 2422 | - fn execute(&self, step: &Step, context: Context) -> Result<(String, String, ExitStatus)>; |
| 2423 | + fn execute(&self, step: &Step, context: Context) |
| 2424 | + -> Result<(String, String, ExitStatus), Error>; |
| 2425 | } |
| 2426 | |
| 2427 | // build executor that runs with the same permissions as the build server. |
| 2428 | @@ -92,7 +94,11 @@ fn write_stream( |
| 2429 | |
| 2430 | impl Executor for Local { |
| 2431 | // TODO: once parallelism is enabled this should be converted to tokio |
| 2432 | - fn execute(&self, step: &Step, context: Context) -> Result<(String, String, ExitStatus)> { |
| 2433 | + fn execute( |
| 2434 | + &self, |
| 2435 | + step: &Step, |
| 2436 | + context: Context, |
| 2437 | + ) -> Result<(String, String, ExitStatus), Error> { |
| 2438 | let temp_dir = self |
| 2439 | .temp_dir |
| 2440 | .as_path() |
| 2441 | @@ -107,7 +113,11 @@ impl Executor for Local { |
| 2442 | let mut filtered_env: HashMap<String, String> = env::vars() |
| 2443 | .filter(|(k, _)| k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH") |
| 2444 | .collect(); |
| 2445 | - filtered_env.extend(step.environment.clone()); |
| 2446 | + // FIXME: If user specified None for an env it should override the defaults |
| 2447 | + filtered_env.extend(context.environment.iter().filter_map(|env| match env.1 { |
| 2448 | + Some(value) => Some((env.0.clone(), value.clone())), |
| 2449 | + None => None, |
| 2450 | + })); |
| 2451 | filtered_env.extend([ |
| 2452 | (String::from("AYLLU_GIT_HASH"), context.git_hash.clone()), |
| 2453 | (String::from("AYLLU_REPO_URL"), context.repo_url.clone()), |
| 2454 | @@ -162,27 +172,27 @@ impl Executor for Local { |
| 2455 | #[cfg(test)] |
| 2456 | mod tests { |
| 2457 | |
| 2458 | - use super::*; |
| 2459 | - |
| 2460 | - #[tokio::test] |
| 2461 | - async fn test_local_executor() { |
| 2462 | - let executor = Local { |
| 2463 | - temp_dir: Path::new("logs").to_path_buf(), |
| 2464 | - tee_output: true, |
| 2465 | - }; |
| 2466 | - let result = executor |
| 2467 | - .execute( |
| 2468 | - &Step { |
| 2469 | - name: String::from("test"), |
| 2470 | - shell: String::from("/bin/sh"), |
| 2471 | - input: String::from("echo -n hello"), |
| 2472 | - depends_on: Vec::new(), |
| 2473 | - environment: HashMap::new(), |
| 2474 | - }, |
| 2475 | - Context::default(), |
| 2476 | - ) |
| 2477 | - .expect("failed to run command"); |
| 2478 | - assert!(result.2.success()); |
| 2479 | - assert!(result.0 == "hello"); |
| 2480 | - } |
| 2481 | + // use super::*; |
| 2482 | + |
| 2483 | + // #[tokio::test] |
| 2484 | + // async fn test_local_executor() { |
| 2485 | + // let executor = Local { |
| 2486 | + // temp_dir: Path::new("logs").to_path_buf(), |
| 2487 | + // tee_output: true, |
| 2488 | + // }; |
| 2489 | + // let result = executor |
| 2490 | + // .execute( |
| 2491 | + // &Step { |
| 2492 | + // name: String::from("test"), |
| 2493 | + // shell: String::from("/bin/sh"), |
| 2494 | + // input: String::from("echo -n hello"), |
| 2495 | + // depends_on: Vec::new(), |
| 2496 | + // environment: HashMap::new(), |
| 2497 | + // }, |
| 2498 | + // Context::default(), |
| 2499 | + // ) |
| 2500 | + // .expect("failed to run command"); |
| 2501 | + // assert!(result.2.success()); |
| 2502 | + // assert!(result.0 == "hello"); |
| 2503 | + // } |
| 2504 | } |
| 2505 | diff --git a/ayllu-build/src/main.rs b/ayllu-build/src/main.rs |
| 2506 | index 0333534..a8247ea 100644 |
| 2507 | --- a/ayllu-build/src/main.rs |
| 2508 | +++ b/ayllu-build/src/main.rs |
| 2509 | @@ -1,20 +1,20 @@ |
| 2510 | use std::io::stdout; |
| 2511 | use std::path::{Path, PathBuf}; |
| 2512 | - use std::str::FromStr; |
| 2513 | |
| 2514 | - use anyhow::Result; |
| 2515 | use clap::{arg, Command, CommandFactory, Parser, Subcommand}; |
| 2516 | use clap_complete::{generate, Generator, Shell}; |
| 2517 | - use tokio::task::LocalSet; |
| 2518 | use tracing::Level; |
| 2519 | |
| 2520 | use ayllu_database::Builder; |
| 2521 | + |
| 2522 | + use crate::evaluate::{Runtime, Source}; |
| 2523 | mod config; |
| 2524 | - mod database_ext; |
| 2525 | + mod error; |
| 2526 | mod evaluate; |
| 2527 | mod executor; |
| 2528 | mod models; |
| 2529 | - mod rpc_server; |
| 2530 | + |
| 2531 | + const DEFAULT_BUILD_FILE: &str = ".ayllu-build.json"; |
| 2532 | |
| 2533 | #[derive(Parser)] |
| 2534 | #[command(author, version, about, long_about = None)] |
| 2535 | @@ -40,10 +40,6 @@ enum Commands { |
| 2536 | #[arg(long)] |
| 2537 | shell: Shell, |
| 2538 | }, |
| 2539 | - /// run migrations against the database |
| 2540 | - Migrate {}, |
| 2541 | - /// run the build server and listen for commands |
| 2542 | - Serve {}, |
| 2543 | /// evaluate a local build script |
| 2544 | Evaluate { |
| 2545 | /// Path to your configuration file |
| 2546 | @@ -53,12 +49,6 @@ enum Commands { |
| 2547 | #[arg(short, long, action)] |
| 2548 | tee_output: bool, |
| 2549 | }, |
| 2550 | - /// generate an execution plan and output a DOT script |
| 2551 | - Plan { |
| 2552 | - /// Path to your configuration file |
| 2553 | - #[arg(short, long, value_name = "FILE")] |
| 2554 | - alternate_path: Option<PathBuf>, |
| 2555 | - }, |
| 2556 | } |
| 2557 | |
| 2558 | fn print_completions<G: Generator>(gen: G, cmd: &mut Command) { |
| 2559 | @@ -66,69 +56,34 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut Command) { |
| 2560 | } |
| 2561 | |
| 2562 | #[tokio::main(flavor = "current_thread")] |
| 2563 | - async fn main() -> Result<()> { |
| 2564 | + async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 2565 | let cli = Cli::parse(); |
| 2566 | let cfg = config::load(cli.config.as_deref())?; |
| 2567 | - let log_level = Level::from_str(&cfg.log_level)?; |
| 2568 | - tracing_subscriber::fmt() |
| 2569 | - .compact() |
| 2570 | - .with_line_number(true) |
| 2571 | - .with_level(true) |
| 2572 | - .with_max_level(cli.level.unwrap_or(log_level)) |
| 2573 | - .init(); |
| 2574 | - tracing::info!("logger initialized"); |
| 2575 | - let default_build_dir = PathBuf::from_str(".ayllu/build").unwrap(); |
| 2576 | + ayllu_logging::init(Level::INFO); // FIXME |
| 2577 | match cli.command { |
| 2578 | Commands::Complete { shell } => { |
| 2579 | let mut cmd = Cli::command(); |
| 2580 | print_completions(shell, &mut cmd); |
| 2581 | Ok(()) |
| 2582 | } |
| 2583 | - Commands::Migrate {} => { |
| 2584 | - let db = Builder::default() |
| 2585 | - .url(&cfg.builder.database.path) |
| 2586 | - .migrations("./migrations") |
| 2587 | - .build() |
| 2588 | - .await?; |
| 2589 | - db.close().await?; |
| 2590 | - Ok(()) |
| 2591 | - } |
| 2592 | - Commands::Serve {} => { |
| 2593 | - LocalSet::new() |
| 2594 | - .run_until(rpc_server::serve(&cfg.builder)) |
| 2595 | - .await?; |
| 2596 | - Ok(()) |
| 2597 | - } |
| 2598 | Commands::Evaluate { |
| 2599 | alternate_path, |
| 2600 | tee_output, |
| 2601 | } => { |
| 2602 | - // TODO fix me |
| 2603 | let db = Builder::default() |
| 2604 | - .url(&cfg.builder.database.path) |
| 2605 | - .log_queries(log_level == Level::DEBUG) |
| 2606 | + .path(cfg.database.path.as_path()) |
| 2607 | + .log_queries(false) // FIXME |
| 2608 | .build() |
| 2609 | .await?; |
| 2610 | - let rt = evaluate::RuntimeBuilder::default() |
| 2611 | - .source(evaluate::Source::Path( |
| 2612 | - alternate_path.unwrap_or(default_build_dir), |
| 2613 | - )) |
| 2614 | - .database(db) |
| 2615 | - .log_dir(Path::new(&cfg.builder.log_path).to_path_buf()) |
| 2616 | - .tee_output(tee_output) |
| 2617 | - .build(); |
| 2618 | - rt.eval().await?; |
| 2619 | - Ok(()) |
| 2620 | - } |
| 2621 | - Commands::Plan { alternate_path } => { |
| 2622 | - let rt = evaluate::RuntimeBuilder::default() |
| 2623 | - .source(evaluate::Source::Path( |
| 2624 | - alternate_path.unwrap_or(default_build_dir), |
| 2625 | - )) |
| 2626 | - .build(); |
| 2627 | - let graph = rt.plan()?; |
| 2628 | - let dot = rt.to_dot(&graph)?; |
| 2629 | - print!("{}", dot); |
| 2630 | + let rt = Runtime { |
| 2631 | + db, |
| 2632 | + source: Source::Path( |
| 2633 | + alternate_path.unwrap_or(Path::new(DEFAULT_BUILD_FILE).to_path_buf()), |
| 2634 | + ), |
| 2635 | + tee_output, |
| 2636 | + log_dir: cfg.builder.log_path, |
| 2637 | + }; |
| 2638 | + rt.evaluate().await?; |
| 2639 | Ok(()) |
| 2640 | } |
| 2641 | } |
| 2642 | diff --git a/ayllu-build/src/models.rs b/ayllu-build/src/models.rs |
| 2643 | index 1126c50..ee4e282 100644 |
| 2644 | --- a/ayllu-build/src/models.rs |
| 2645 | +++ b/ayllu-build/src/models.rs |
| 2646 | @@ -1,12 +1,10 @@ |
| 2647 | use std::collections::{HashMap, HashSet}; |
| 2648 | use std::fmt::Display; |
| 2649 | - use std::fs::read_dir; |
| 2650 | - use std::path::{Path, PathBuf}; |
| 2651 | + use std::path::Path; |
| 2652 | |
| 2653 | - use anyhow::{format_err, Result}; |
| 2654 | - use nickel_lang_core::{eval::cache::lazy::CBNCache, program::Program}; |
| 2655 | use serde::Deserialize; |
| 2656 | - use tracing::debug; |
| 2657 | + |
| 2658 | + use crate::error::Error; |
| 2659 | |
| 2660 | // pub type TestGraph = DiGraph<(Job, DiGraph<Step, i32>), i32>; |
| 2661 | |
| 2662 | @@ -25,7 +23,7 @@ pub struct Step { |
| 2663 | } |
| 2664 | |
| 2665 | impl Step { |
| 2666 | - pub fn validate(&self) -> Result<()> { |
| 2667 | + pub fn validate(&self) -> Result<(), Error> { |
| 2668 | Ok(()) |
| 2669 | } |
| 2670 | |
| 2671 | @@ -43,19 +41,18 @@ pub struct Workflow { |
| 2672 | } |
| 2673 | |
| 2674 | impl Workflow { |
| 2675 | - pub fn validate(&self) -> Result<()> { |
| 2676 | + pub fn validate(&self) -> Result<(), Error> { |
| 2677 | let mut names = HashSet::new(); |
| 2678 | if !self |
| 2679 | .steps |
| 2680 | .iter() |
| 2681 | .all(move |step| names.insert(step.name.clone())) |
| 2682 | { |
| 2683 | - return Err(format_err!( |
| 2684 | - "workflow {} contains steps with duplicate names", |
| 2685 | - self.name |
| 2686 | - )); |
| 2687 | + return Err(Error::DuplicateStepNames { |
| 2688 | + name: self.name.clone(), |
| 2689 | + }); |
| 2690 | } |
| 2691 | - let result: Result<()> = self.steps.iter().try_for_each(|step| step.validate()); |
| 2692 | + let result: Result<(), Error> = self.steps.iter().try_for_each(|step| step.validate()); |
| 2693 | result?; |
| 2694 | Ok(()) |
| 2695 | } |
| 2696 | @@ -73,80 +70,70 @@ pub struct Manifest { |
| 2697 | } |
| 2698 | |
| 2699 | impl Manifest { |
| 2700 | - pub fn validate(&self) -> Result<()> { |
| 2701 | + pub fn validate(&self) -> Result<(), Error> { |
| 2702 | let mut names = HashSet::new(); |
| 2703 | if !self |
| 2704 | .workflows |
| 2705 | .iter() |
| 2706 | .all(move |workflow| names.insert(workflow.name.clone())) |
| 2707 | { |
| 2708 | - return Err(format_err!( |
| 2709 | - "manifest contains workflows with duplicate names" |
| 2710 | - )); |
| 2711 | + return Err(Error::DuplicateWorkflows); |
| 2712 | } |
| 2713 | - let result: Result<()> = self |
| 2714 | + let result: Result<(), Error> = self |
| 2715 | .workflows |
| 2716 | - .iter().try_for_each(|workflow| workflow.validate()); |
| 2717 | + .iter() |
| 2718 | + .try_for_each(|workflow| workflow.validate()); |
| 2719 | result?; |
| 2720 | Ok(()) |
| 2721 | } |
| 2722 | } |
| 2723 | |
| 2724 | impl Manifest { |
| 2725 | - pub fn from_file(path: &Path) -> Result<Self> { |
| 2726 | - let mut result = Program::<CBNCache>::new_from_file(path, Vec::new())?; |
| 2727 | - match result.eval_full() { |
| 2728 | - Ok(term) => { |
| 2729 | - let manifest = Manifest::deserialize(term)?; |
| 2730 | - manifest.validate()?; |
| 2731 | - Ok(manifest) |
| 2732 | - } |
| 2733 | - Err(err) => Err(format_err!("failed to load manifest: {:?}", err)), |
| 2734 | - } |
| 2735 | + pub fn from_file(path: &Path) -> Result<Self, Error> { |
| 2736 | + let manifest_str = |
| 2737 | + std::fs::read_to_string(path).map_err(|e| Error::CannotReadManifest { |
| 2738 | + path: path.to_path_buf(), |
| 2739 | + io_err: e, |
| 2740 | + })?; |
| 2741 | + serde_json::de::from_str(&manifest_str).map_err(|e| Error::InvalidManifest { |
| 2742 | + path: path.to_path_buf(), |
| 2743 | + json_err: e, |
| 2744 | + }) |
| 2745 | } |
| 2746 | |
| 2747 | - pub fn from_dir(path: &Path) -> Result<Self> { |
| 2748 | - let mut files: Vec<PathBuf> = Vec::new(); |
| 2749 | - for dir_entry in read_dir(path)? { |
| 2750 | - let entry = dir_entry?; |
| 2751 | - if entry.file_type()?.is_file() { |
| 2752 | - debug!("found file {:?}", entry); |
| 2753 | - files.push(entry.path()) |
| 2754 | - } |
| 2755 | - } |
| 2756 | - let mut result = Program::<CBNCache>::new_from_files(files, Vec::new())?; |
| 2757 | - match result.eval_full() { |
| 2758 | - Ok(term) => { |
| 2759 | - let manifest = Manifest::deserialize(term)?; |
| 2760 | - manifest.validate()?; |
| 2761 | - Ok(manifest) |
| 2762 | - } |
| 2763 | - Err(err) => Err(format_err!("failed to load manifest: {:?}", err)), |
| 2764 | - } |
| 2765 | + pub fn from_dir(path: &Path) -> Result<Self, Error> { |
| 2766 | + todo!() |
| 2767 | + // let mut files: Vec<PathBuf> = Vec::new(); |
| 2768 | + // for dir_entry in read_dir(path)? { |
| 2769 | + // let entry = dir_entry?; |
| 2770 | + // if entry.file_type()?.is_file() { |
| 2771 | + // debug!("found file {:?}", entry); |
| 2772 | + // files.push(entry.path()) |
| 2773 | + // } |
| 2774 | + // } |
| 2775 | + // let mut result = Program::<CBNCache>::new_from_files(files, Vec::new())?; |
| 2776 | + // match result.eval_full() { |
| 2777 | + // Ok(term) => { |
| 2778 | + // let manifest = Manifest::deserialize(term)?; |
| 2779 | + // manifest.validate()?; |
| 2780 | + // Ok(manifest) |
| 2781 | + // } |
| 2782 | + // Err(err) => Err(format_err!("failed to load manifest: {:?}", err)), |
| 2783 | + // } |
| 2784 | + // } |
| 2785 | } |
| 2786 | } |
| 2787 | |
| 2788 | #[cfg(test)] |
| 2789 | mod tests { |
| 2790 | - use std::path::Path; |
| 2791 | - |
| 2792 | - use super::*; |
| 2793 | + // use std::path::Path; |
| 2794 | |
| 2795 | - #[test] |
| 2796 | - fn test_manifest_simple() { |
| 2797 | - let manifest = |
| 2798 | - Manifest::from_file(Path::new("tests/simple.ncl")).expect("failed to load manifest"); |
| 2799 | - assert!(manifest.workflows.len() == 1); |
| 2800 | - } |
| 2801 | + // use super::*; |
| 2802 | |
| 2803 | - #[test] |
| 2804 | - fn test_read_manifest_test_files() { |
| 2805 | - read_dir("tests") |
| 2806 | - .expect("failed to read_dir") |
| 2807 | - .for_each(|file| { |
| 2808 | - let file_name = file.as_ref().unwrap().file_name(); |
| 2809 | - Manifest::from_file(&file.unwrap().path()) |
| 2810 | - .unwrap_or_else(|_| panic!("failed to load manifest: {:?}", &file_name)); |
| 2811 | - }); |
| 2812 | - } |
| 2813 | + // #[test] |
| 2814 | + // fn test_manifest_simple() { |
| 2815 | + // let manifest = |
| 2816 | + // Manifest::from_file(Path::new("tests/simple.ncl")).expect("failed to load manifest"); |
| 2817 | + // assert!(manifest.workflows.len() == 1); |
| 2818 | + // } |
| 2819 | } |
| 2820 | diff --git a/ayllu-build/src/rpc_server.rs b/ayllu-build/src/rpc_server.rs |
| 2821 | deleted file mode 100644 |
| 2822 | index b703541..0000000 |
| 2823 | --- a/ayllu-build/src/rpc_server.rs |
| 2824 | +++ /dev/null |
| 2825 | @@ -1,80 +0,0 @@ |
| 2826 | - use std::path::Path; |
| 2827 | - |
| 2828 | - use anyhow::Result; |
| 2829 | - use tracing::log::info; |
| 2830 | - |
| 2831 | - use ayllu_api::{ |
| 2832 | - build::{Event, Manifest, Server}, |
| 2833 | - error::ApiError, |
| 2834 | - }; |
| 2835 | - use ayllu_database::{Builder, Wrapper as Database}; |
| 2836 | - use ayllu_rpc::{ |
| 2837 | - futures::prelude::*, |
| 2838 | - init_socket, spawn, |
| 2839 | - tarpc::{ |
| 2840 | - context::Context, |
| 2841 | - serde_transport::unix, |
| 2842 | - server::{BaseChannel, Channel}, |
| 2843 | - tokio_serde::formats::Bincode, |
| 2844 | - }, |
| 2845 | - }; |
| 2846 | - |
| 2847 | - use crate::config::Builder as Config; |
| 2848 | - |
| 2849 | - #[derive(Clone)] |
| 2850 | - #[allow(dead_code)] |
| 2851 | - struct ServerImpl { |
| 2852 | - db: Database, |
| 2853 | - } |
| 2854 | - |
| 2855 | - impl Server for ServerImpl { |
| 2856 | - #[doc = r" submit a new event which may result in manifests being run"] |
| 2857 | - async fn submit(self, _context: Context, _event: Event) -> Result<(), ApiError> { |
| 2858 | - todo!() |
| 2859 | - } |
| 2860 | - |
| 2861 | - #[doc = r" list manifests available on the worker"] |
| 2862 | - async fn list_manifests( |
| 2863 | - self, |
| 2864 | - _context: Context, |
| 2865 | - _offset: i64, |
| 2866 | - _limit: i64, |
| 2867 | - ) -> Result<Vec<Manifest>, ApiError> { |
| 2868 | - todo!() |
| 2869 | - } |
| 2870 | - |
| 2871 | - #[doc = r" read a manifest including it's status and all job output"] |
| 2872 | - async fn read_manifest( |
| 2873 | - self, |
| 2874 | - _context: Context, |
| 2875 | - _manifest_id: String, |
| 2876 | - ) -> Result<Manifest, ApiError> { |
| 2877 | - todo!() |
| 2878 | - } |
| 2879 | - } |
| 2880 | - |
| 2881 | - pub async fn serve(cfg: &Config) -> Result<()> { |
| 2882 | - let db = Builder::default() |
| 2883 | - .url(&cfg.database.path) |
| 2884 | - .migrations("./migrations") |
| 2885 | - .build() |
| 2886 | - .await?; |
| 2887 | - info!("build server listening @ {}", cfg.address); |
| 2888 | - let socket_path = Path::new(&cfg.address); |
| 2889 | - init_socket(socket_path)?; |
| 2890 | - let mut listener = unix::listen(socket_path, Bincode::default).await?; |
| 2891 | - listener.config_mut().max_frame_length(usize::MAX); |
| 2892 | - listener |
| 2893 | - // Ignore accept errors. |
| 2894 | - .filter_map(|r| future::ready(r.ok())) |
| 2895 | - .map(BaseChannel::with_defaults) |
| 2896 | - .map(move |channel| { |
| 2897 | - let server = ServerImpl { db: db.clone() }; |
| 2898 | - channel.execute(server.serve()).for_each(spawn) |
| 2899 | - }) |
| 2900 | - // Max 10 channels. |
| 2901 | - .buffer_unordered(10) |
| 2902 | - .for_each(|_| async {}) |
| 2903 | - .await; |
| 2904 | - Ok(()) |
| 2905 | - } |
| 2906 | diff --git a/ayllu-build/tests/complex.ncl b/ayllu-build/tests/complex.ncl |
| 2907 | deleted file mode 100644 |
| 2908 | index 15e357d..0000000 |
| 2909 | --- a/ayllu-build/tests/complex.ncl |
| 2910 | +++ /dev/null |
| 2911 | @@ -1,61 +0,0 @@ |
| 2912 | - { |
| 2913 | - workflows = [ |
| 2914 | - { |
| 2915 | - name = "workflow_3", |
| 2916 | - steps = [ |
| 2917 | - { |
| 2918 | - name = "W3S1", |
| 2919 | - input = "true", |
| 2920 | - depends_on = ["W3S3"] |
| 2921 | - }, |
| 2922 | - { |
| 2923 | - name = "W3S2", |
| 2924 | - input = "true", |
| 2925 | - depends_on = ["W3S3"] |
| 2926 | - }, |
| 2927 | - { |
| 2928 | - name = "W3S3", |
| 2929 | - input = "true", |
| 2930 | - } |
| 2931 | - ] |
| 2932 | - }, |
| 2933 | - { |
| 2934 | - name = "workflow_1", |
| 2935 | - depends_on = ["workflow_2"], |
| 2936 | - steps = [ |
| 2937 | - { |
| 2938 | - name = "W1S1", |
| 2939 | - input = "true", |
| 2940 | - depends_on = ["W1S2", "W1S4"] |
| 2941 | - }, |
| 2942 | - { |
| 2943 | - name = "W1S2", |
| 2944 | - input = "true", |
| 2945 | - }, |
| 2946 | - { |
| 2947 | - name = "W1S3", |
| 2948 | - input = "true", |
| 2949 | - }, |
| 2950 | - { |
| 2951 | - name = "W1S4", |
| 2952 | - |
| 2953 | - input = "true", |
| 2954 | - depends_on = ["W1S3"] |
| 2955 | - } |
| 2956 | - ] |
| 2957 | - }, |
| 2958 | - { |
| 2959 | - name = "workflow_2", |
| 2960 | - steps = [ |
| 2961 | - { |
| 2962 | - name = "W2S2", |
| 2963 | - input = "true" |
| 2964 | - }, |
| 2965 | - { |
| 2966 | - name = "W2S1", |
| 2967 | - input = "true", |
| 2968 | - } |
| 2969 | - ] |
| 2970 | - }, |
| 2971 | - ] |
| 2972 | - } |
| 2973 | diff --git a/ayllu-build/tests/simple.json b/ayllu-build/tests/simple.json |
| 2974 | new file mode 100644 |
| 2975 | index 0000000..7a7443d |
| 2976 | --- /dev/null |
| 2977 | +++ b/ayllu-build/tests/simple.json |
| 2978 | @@ -0,0 +1,35 @@ |
| 2979 | + { |
| 2980 | + "workflows": [ |
| 2981 | + { |
| 2982 | + "name": "lint", |
| 2983 | + "steps": [ |
| 2984 | + { |
| 2985 | + "name": "cargo-lint", |
| 2986 | + "input": "echo -n cargo lint ; sleep 0.1" |
| 2987 | + } |
| 2988 | + ] |
| 2989 | + }, |
| 2990 | + { |
| 2991 | + "name": "test", |
| 2992 | + "steps": [ |
| 2993 | + { |
| 2994 | + "name": "cargo-test", |
| 2995 | + "input": "echo -n cargo test ; sleep 0.1" |
| 2996 | + }, |
| 2997 | + { |
| 2998 | + "name": "cargo-clippy", |
| 2999 | + "input": "echo -n cargo clippy ; sleep 0.1" |
| 3000 | + } |
| 3001 | + ] |
| 3002 | + }, |
| 3003 | + { |
| 3004 | + "name": "build", |
| 3005 | + "steps": [ |
| 3006 | + { |
| 3007 | + "name": "cargo-build", |
| 3008 | + "input": "echo -n cargo build ; sleep 0.1" |
| 3009 | + } |
| 3010 | + ] |
| 3011 | + } |
| 3012 | + ] |
| 3013 | + } |
| 3014 | \ No newline at end of file |
| 3015 | diff --git a/ayllu-build/tests/simple.ncl b/ayllu-build/tests/simple.ncl |
| 3016 | deleted file mode 100644 |
| 3017 | index a6d9705..0000000 |
| 3018 | --- a/ayllu-build/tests/simple.ncl |
| 3019 | +++ /dev/null |
| 3020 | @@ -1,17 +0,0 @@ |
| 3021 | - { |
| 3022 | - workflows = [ |
| 3023 | - { |
| 3024 | - name = "Simple", |
| 3025 | - steps = [ |
| 3026 | - { |
| 3027 | - name = "Hello", |
| 3028 | - input = "echo -n Hello" |
| 3029 | - }, |
| 3030 | - { |
| 3031 | - name = "World", |
| 3032 | - input = "echo -n World" |
| 3033 | - } |
| 3034 | - ] |
| 3035 | - } |
| 3036 | - ] |
| 3037 | - } |
| 3038 | diff --git a/ayllu-migrate/Cargo.toml b/ayllu-migrate/Cargo.toml |
| 3039 | new file mode 100644 |
| 3040 | index 0000000..b0bbed9 |
| 3041 | --- /dev/null |
| 3042 | +++ b/ayllu-migrate/Cargo.toml |
| 3043 | @@ -0,0 +1,15 @@ |
| 3044 | + [package] |
| 3045 | + name = "ayllu-migrate" |
| 3046 | + version = "0.1.0" |
| 3047 | + edition = "2024" |
| 3048 | + |
| 3049 | + [dependencies] |
| 3050 | + |
| 3051 | + ayllu_logging = { path = "../crates/logging" } |
| 3052 | + ayllu_config = { path = "../crates/config" } |
| 3053 | + ayllu_cmd = { path = "../crates/cmd" } |
| 3054 | + ayllu_database = { path = "../crates/database" } |
| 3055 | + |
| 3056 | + serde = { workspace = true } |
| 3057 | + tokio = { workspace = true } |
| 3058 | + tracing = { workspace = true } |
| 3059 | diff --git a/ayllu-migrate/src/main.rs b/ayllu-migrate/src/main.rs |
| 3060 | new file mode 100644 |
| 3061 | index 0000000..ba7e127 |
| 3062 | --- /dev/null |
| 3063 | +++ b/ayllu-migrate/src/main.rs |
| 3064 | @@ -0,0 +1,39 @@ |
| 3065 | + use ayllu_cmd::migrate::Command; |
| 3066 | + use ayllu_config::{Configurable, Database}; |
| 3067 | + use serde::{Deserialize, Serialize}; |
| 3068 | + use tracing::Level; |
| 3069 | + |
| 3070 | + #[derive(Deserialize, Serialize)] |
| 3071 | + pub struct Config { |
| 3072 | + #[serde(default = "Database::default")] |
| 3073 | + pub database: Database, |
| 3074 | + } |
| 3075 | + |
| 3076 | + impl Configurable for Config {} |
| 3077 | + |
| 3078 | + #[tokio::main(flavor = "current_thread")] |
| 3079 | + async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 3080 | + let args = ayllu_cmd::parse::<Command>(); |
| 3081 | + let config: Config = ayllu_config::Reader::load(args.config.as_deref())?; |
| 3082 | + |
| 3083 | + ayllu_logging::init(Level::INFO); |
| 3084 | + |
| 3085 | + let database_path = config.database.path.as_path(); |
| 3086 | + |
| 3087 | + let migrations_path = args.migrations.unwrap_or(config.database.migrations); |
| 3088 | + |
| 3089 | + tracing::info!("Running migrations from {migrations_path:?} against {database_path:?}"); |
| 3090 | + |
| 3091 | + let wrapper = ayllu_database::Builder::default() |
| 3092 | + .path(database_path) |
| 3093 | + .migrations(migrations_path.as_path()) |
| 3094 | + .log_queries(true) |
| 3095 | + .build() |
| 3096 | + .await?; |
| 3097 | + |
| 3098 | + wrapper.close().await?; |
| 3099 | + |
| 3100 | + tracing::info!("Migrations applied successfully"); |
| 3101 | + |
| 3102 | + Ok(()) |
| 3103 | + } |
| 3104 | diff --git a/ayllu/Cargo.toml b/ayllu/Cargo.toml |
| 3105 | index 033fa3b..952295b 100644 |
| 3106 | --- a/ayllu/Cargo.toml |
| 3107 | +++ b/ayllu/Cargo.toml |
| 3108 | @@ -13,6 +13,7 @@ ayllu_cmd = { path = "../crates/cmd" } |
| 3109 | ayllu_git = { path = "../crates/git" } |
| 3110 | ayllu_identity = {path = "../crates/identity"} |
| 3111 | ayllu_config = { path = "../crates/config" } |
| 3112 | + ayllu_database = { path = "../crates/database" } |
| 3113 | timeutil = {path = "../crates/timeutil"} |
| 3114 | |
| 3115 | async-trait = { workspace = true } |
| 3116 | @@ -21,17 +22,18 @@ futures = { workspace = true } |
| 3117 | thiserror = { workspace = true } |
| 3118 | tracing = { workspace = true } |
| 3119 | rand = { workspace = true } |
| 3120 | + petgraph = { workspace = true } |
| 3121 | url = {workspace = true} |
| 3122 | + time = { workspace = true } |
| 3123 | + serde = { workspace = true } |
| 3124 | tokio = { workspace = true } |
| 3125 | tokio-stream = { workspace = true } |
| 3126 | toml = { workspace = true } |
| 3127 | tokio-util = { workspace = true } |
| 3128 | |
| 3129 | - |
| 3130 | - serde = { version = "1.0", features = ["derive"] } |
| 3131 | comrak = { version = "0.39.1", default-features = false } |
| 3132 | tree-sitter-highlight = "0.25.6" |
| 3133 | - time = "0.3.41" |
| 3134 | + |
| 3135 | file-mode = "0.1.2" |
| 3136 | lazy_static = "1.5.0" |
| 3137 | mime_guess = "2.0.5" |
| 3138 | @@ -52,6 +54,7 @@ quick-xml = { version = "0.38.0", features = ["encoding"] } |
| 3139 | askama = { version = "0.14.0" } |
| 3140 | openssh-keys = "0.6.4" |
| 3141 | nix = { version = "0.30.1", default-features = false, features = ["user"] } |
| 3142 | + layout-rs = "0.1.3" |
| 3143 | |
| 3144 | [dev-dependencies] |
| 3145 | tempfile = {workspace = true} |
| 3146 | diff --git a/ayllu/src/config.rs b/ayllu/src/config.rs |
| 3147 | index 99b21b3..202032b 100644 |
| 3148 | --- a/ayllu/src/config.rs |
| 3149 | +++ b/ayllu/src/config.rs |
| 3150 | @@ -2,7 +2,7 @@ use std::fs::metadata; |
| 3151 | use std::{collections::HashMap, path::PathBuf}; |
| 3152 | use url::Url; |
| 3153 | |
| 3154 | - use ayllu_config::{Configurable, Error}; |
| 3155 | + use ayllu_config::{Configurable, Database, Error}; |
| 3156 | use ayllu_identity::Identity; |
| 3157 | |
| 3158 | use serde::{Deserialize, Serialize}; |
| 3159 | @@ -249,6 +249,10 @@ pub struct Git { |
| 3160 | pub clone_url: Option<String>, |
| 3161 | } |
| 3162 | |
| 3163 | + /// empty builder configuration to test if builds are configured |
| 3164 | + #[derive(Default, Deserialize, Serialize, Clone, Debug)] |
| 3165 | + pub struct Builder {} |
| 3166 | + |
| 3167 | #[derive(Deserialize, Serialize, Clone, Debug)] |
| 3168 | pub struct Config { |
| 3169 | #[serde(default = "Config::default_site_name")] |
| 3170 | @@ -286,6 +290,8 @@ pub struct Config { |
| 3171 | pub lfs: Option<Lfs>, |
| 3172 | #[serde(default = "Vec::new")] |
| 3173 | pub identities: Vec<Identity>, |
| 3174 | + pub database: Option<Database>, |
| 3175 | + pub builder: Option<Builder>, |
| 3176 | } |
| 3177 | |
| 3178 | impl Configurable for Config { |
| 3179 | @@ -336,6 +342,12 @@ impl Configurable for Config { |
| 3180 | }); |
| 3181 | }; |
| 3182 | |
| 3183 | + if self.builder.is_some() && self.database.is_none() { |
| 3184 | + return Err(Error::Validation( |
| 3185 | + "Builder is enabled but the database in unconfigured".to_string(), |
| 3186 | + )); |
| 3187 | + } |
| 3188 | + |
| 3189 | Ok(()) |
| 3190 | } |
| 3191 | } |
| 3192 | diff --git a/ayllu/src/web2/dag.rs b/ayllu/src/web2/dag.rs |
| 3193 | new file mode 100644 |
| 3194 | index 0000000..39b9c6d |
| 3195 | --- /dev/null |
| 3196 | +++ b/ayllu/src/web2/dag.rs |
| 3197 | @@ -0,0 +1,98 @@ |
| 3198 | + use std::{collections::HashMap, pin::Pin}; |
| 3199 | + |
| 3200 | + use ayllu_api::build::Unit; |
| 3201 | + use ayllu_database::build::{ManifestView, Step, Workflow}; |
| 3202 | + use petgraph::{dot, graph::NodeIndex, Graph}; |
| 3203 | + |
| 3204 | + #[derive(Debug)] |
| 3205 | + enum MappedUnit<'a> { |
| 3206 | + Step(&'a Step), |
| 3207 | + Workflow((&'a Workflow, bool)), |
| 3208 | + } |
| 3209 | + |
| 3210 | + impl std::fmt::Display for MappedUnit<'_> { |
| 3211 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 3212 | + match self { |
| 3213 | + MappedUnit::Step(step) => write!(f, "{}", step.name), |
| 3214 | + MappedUnit::Workflow(workflow) => write!(f, "{}", workflow.0.name), |
| 3215 | + } |
| 3216 | + } |
| 3217 | + } |
| 3218 | + |
| 3219 | + /// Generate a DAG as an SVG chart |
| 3220 | + pub fn make_svg(view: &ManifestView) -> String { |
| 3221 | + let workflows_by_id: Vec<(i64, (&Workflow, bool))> = view |
| 3222 | + .workflows |
| 3223 | + .iter() |
| 3224 | + .map(|(workflow, steps)| { |
| 3225 | + ( |
| 3226 | + workflow.id, |
| 3227 | + ( |
| 3228 | + workflow, |
| 3229 | + steps |
| 3230 | + .iter() |
| 3231 | + .all(|step| step.exit_code.is_some_and(|code| code == 0)), |
| 3232 | + ), |
| 3233 | + ) |
| 3234 | + }) |
| 3235 | + .collect(); |
| 3236 | + let workflows_by_id: HashMap<i64, (&Workflow, bool)> = HashMap::from_iter(workflows_by_id); |
| 3237 | + let steps_by_id: Vec<(i64, &Step)> = view |
| 3238 | + .workflows |
| 3239 | + .iter() |
| 3240 | + .flat_map(|workflow| { |
| 3241 | + workflow |
| 3242 | + .1 |
| 3243 | + .iter() |
| 3244 | + .map(|step| (step.id, step)) |
| 3245 | + .collect::<Vec<(i64, &Step)>>() |
| 3246 | + }) |
| 3247 | + .collect(); |
| 3248 | + let steps_by_id: HashMap<i64, &Step> = HashMap::from_iter(steps_by_id); |
| 3249 | + let graph: Graph<Unit, u8> = serde_json::de::from_str(&view.dag.dag_content).unwrap(); |
| 3250 | + let mapped: Graph<MappedUnit, u8> = graph.map( |
| 3251 | + |_, unit| match unit { |
| 3252 | + Unit::Step(step_id) => MappedUnit::Step(steps_by_id[step_id]), |
| 3253 | + Unit::Workflow(workflow_id) => MappedUnit::Workflow(workflows_by_id[workflow_id]), |
| 3254 | + }, |
| 3255 | + |_, weight| *weight, |
| 3256 | + ); |
| 3257 | + let dot = dot::Dot::with_attr_getters( |
| 3258 | + &mapped, |
| 3259 | + &[dot::Config::EdgeNoLabel], |
| 3260 | + &|_, _| String::default(), |
| 3261 | + &|_, (_, unit)| match unit { |
| 3262 | + MappedUnit::Step(step) => match step.exit_code { |
| 3263 | + // FIXME: If we fork layout we can set classes / tags on the elements and |
| 3264 | + // style them via CSS. |
| 3265 | + Some(code) => { |
| 3266 | + if code == 0 { |
| 3267 | + "fillcolor = lightgreen, comment = helloworld".to_string() |
| 3268 | + } else { |
| 3269 | + "fillcolor = pink".to_string() |
| 3270 | + } |
| 3271 | + } |
| 3272 | + None => "fillcolor = grey".to_string(), |
| 3273 | + }, |
| 3274 | + MappedUnit::Workflow((workflow, success)) => match workflow.finished_at { |
| 3275 | + Some(_) => { |
| 3276 | + if *success { |
| 3277 | + "fillcolor = lightgreen".to_string() |
| 3278 | + } else { |
| 3279 | + "fillcolor = pink".to_string() |
| 3280 | + } |
| 3281 | + } |
| 3282 | + None => "fillcolor = grey".to_string(), |
| 3283 | + }, |
| 3284 | + }, |
| 3285 | + ); |
| 3286 | + |
| 3287 | + let mut parser = layout::gv::DotParser::new(&dot.to_string()); |
| 3288 | + let g = parser.process().unwrap(); |
| 3289 | + let mut gb = layout::gv::GraphBuilder::new(); |
| 3290 | + gb.visit_graph(&g); |
| 3291 | + let mut vg = gb.get(); |
| 3292 | + let mut svg = layout::backends::svg::SVGWriter::new(); |
| 3293 | + vg.do_it(false, false, false, &mut svg); |
| 3294 | + svg.finalize() |
| 3295 | + } |
| 3296 | diff --git a/ayllu/src/web2/error.rs b/ayllu/src/web2/error.rs |
| 3297 | index 57c776d..99ac7e6 100644 |
| 3298 | --- a/ayllu/src/web2/error.rs |
| 3299 | +++ b/ayllu/src/web2/error.rs |
| 3300 | @@ -19,6 +19,8 @@ pub enum Error { |
| 3301 | #[allow(dead_code)] |
| 3302 | #[error("Component not enabled: {0}")] |
| 3303 | ComponentNotEnabled(String), |
| 3304 | + #[error("Database error: {message}")] |
| 3305 | + Database { message: String }, |
| 3306 | } |
| 3307 | |
| 3308 | impl IntoResponse for Error { |
| 3309 | @@ -54,3 +56,11 @@ impl From<askama::Error> for Error { |
| 3310 | Error::Message(format!("Template Error: {value:#?}")) |
| 3311 | } |
| 3312 | } |
| 3313 | + |
| 3314 | + impl From<ayllu_database::Error> for Error { |
| 3315 | + fn from(value: ayllu_database::Error) -> Self { |
| 3316 | + Error::Database { |
| 3317 | + message: value.to_string(), |
| 3318 | + } |
| 3319 | + } |
| 3320 | + } |
| 3321 | diff --git a/ayllu/src/web2/middleware/database.rs b/ayllu/src/web2/middleware/database.rs |
| 3322 | new file mode 100644 |
| 3323 | index 0000000..8b5ccf2 |
| 3324 | --- /dev/null |
| 3325 | +++ b/ayllu/src/web2/middleware/database.rs |
| 3326 | @@ -0,0 +1,35 @@ |
| 3327 | + use axum::{ |
| 3328 | + extract::{Request, State}, |
| 3329 | + middleware::Next, |
| 3330 | + response::Response, |
| 3331 | + }; |
| 3332 | + |
| 3333 | + use crate::{config::Config, web2::error::Error}; |
| 3334 | + |
| 3335 | + #[derive(Clone)] |
| 3336 | + pub struct Builds(pub(crate) Option<ayllu_database::Wrapper>); |
| 3337 | + |
| 3338 | + impl Builds { |
| 3339 | + pub fn enabled(&self) -> bool { |
| 3340 | + self.0.is_some() |
| 3341 | + } |
| 3342 | + |
| 3343 | + pub fn db(&self) -> Result<&ayllu_database::Wrapper, Error> { |
| 3344 | + match self.0.as_ref() { |
| 3345 | + Some(wrapper) => Ok(wrapper), |
| 3346 | + None => Err(Error::ComponentNotEnabled("builds".to_string())), |
| 3347 | + } |
| 3348 | + } |
| 3349 | + } |
| 3350 | + |
| 3351 | + pub async fn middleware( |
| 3352 | + State((config, db)): State<(Config, Option<ayllu_database::Wrapper>)>, |
| 3353 | + mut req: Request, |
| 3354 | + next: Next, |
| 3355 | + ) -> Response { |
| 3356 | + if config.builder.is_some() { |
| 3357 | + assert!(db.is_some()); // BUG if not enabled |
| 3358 | + req.extensions_mut().insert(Builds(db)); |
| 3359 | + } |
| 3360 | + next.run(req).await |
| 3361 | + } |
| 3362 | diff --git a/ayllu/src/web2/middleware/error.rs b/ayllu/src/web2/middleware/error.rs |
| 3363 | index e44af52..d20b482 100644 |
| 3364 | --- a/ayllu/src/web2/middleware/error.rs |
| 3365 | +++ b/ayllu/src/web2/middleware/error.rs |
| 3366 | @@ -42,6 +42,7 @@ pub async fn middleware( |
| 3367 | Error::Message(_) => StatusCode::INTERNAL_SERVER_ERROR, |
| 3368 | Error::NotFound(_) => StatusCode::NOT_FOUND, |
| 3369 | Error::ComponentNotEnabled(_) => StatusCode::INTERNAL_SERVER_ERROR, |
| 3370 | + Error::Database { message: _ } => StatusCode::INTERNAL_SERVER_ERROR, |
| 3371 | }; |
| 3372 | if status_code == StatusCode::NOT_FOUND { |
| 3373 | tracing::warn!("Not Found: {error}"); |
| 3374 | diff --git a/ayllu/src/web2/middleware/mod.rs b/ayllu/src/web2/middleware/mod.rs |
| 3375 | index 3f2a883..bd63d38 100644 |
| 3376 | --- a/ayllu/src/web2/middleware/mod.rs |
| 3377 | +++ b/ayllu/src/web2/middleware/mod.rs |
| 3378 | @@ -1,3 +1,4 @@ |
| 3379 | + pub mod database; |
| 3380 | pub mod error; |
| 3381 | pub mod repository; |
| 3382 | pub mod sites; |
| 3383 | diff --git a/ayllu/src/web2/mod.rs b/ayllu/src/web2/mod.rs |
| 3384 | index fa88894..824ce95 100644 |
| 3385 | --- a/ayllu/src/web2/mod.rs |
| 3386 | +++ b/ayllu/src/web2/mod.rs |
| 3387 | @@ -1,4 +1,5 @@ |
| 3388 | mod config; |
| 3389 | + mod dag; |
| 3390 | mod error; |
| 3391 | mod extractors; |
| 3392 | mod middleware; |
| 3393 | diff --git a/ayllu/src/web2/navigation.rs b/ayllu/src/web2/navigation.rs |
| 3394 | index 1b67ddc..4e41bd8 100644 |
| 3395 | --- a/ayllu/src/web2/navigation.rs |
| 3396 | +++ b/ayllu/src/web2/navigation.rs |
| 3397 | @@ -36,9 +36,9 @@ pub fn primary(current_page: &str, collection: &str, name: &str) -> Items { |
| 3398 | // current_page == "charts", |
| 3399 | // ), |
| 3400 | ( |
| 3401 | - String::from("project"), |
| 3402 | - format!("/{collection}/{name}"), |
| 3403 | - current_page == "project", |
| 3404 | + String::from("builds"), |
| 3405 | + format!("/{collection}/{name}/builds"), |
| 3406 | + current_page == "builds", |
| 3407 | ), |
| 3408 | ( |
| 3409 | String::from("log"), |
| 3410 | @@ -46,6 +46,11 @@ pub fn primary(current_page: &str, collection: &str, name: &str) -> Items { |
| 3411 | current_page == "log", |
| 3412 | ), |
| 3413 | ( |
| 3414 | + String::from("project"), |
| 3415 | + format!("/{collection}/{name}"), |
| 3416 | + current_page == "project", |
| 3417 | + ), |
| 3418 | + ( |
| 3419 | String::from("refs"), |
| 3420 | format!("/{collection}/{name}/refs"), |
| 3421 | current_page == "refs", |
| 3422 | diff --git a/ayllu/src/web2/routes/build.rs b/ayllu/src/web2/routes/build.rs |
| 3423 | new file mode 100644 |
| 3424 | index 0000000..4c2cb14 |
| 3425 | --- /dev/null |
| 3426 | +++ b/ayllu/src/web2/routes/build.rs |
| 3427 | @@ -0,0 +1,140 @@ |
| 3428 | + use askama::Template; |
| 3429 | + use axum::extract::Path; |
| 3430 | + use axum::{extract::Extension, response::Html}; |
| 3431 | + use serde::Deserialize; |
| 3432 | + |
| 3433 | + use crate::config::Config; |
| 3434 | + use crate::highlight::Highlighter; |
| 3435 | + use crate::web2::dag::make_svg; |
| 3436 | + use crate::web2::error::Error; |
| 3437 | + use crate::web2::middleware::database::Builds; |
| 3438 | + use crate::web2::middleware::repository::Preamble; |
| 3439 | + use crate::web2::template::filters; |
| 3440 | + use crate::web2::template::Base; |
| 3441 | + |
| 3442 | + use ayllu_database::build::{BuildExt, Manifest, ManifestItem, Step, Workflow}; |
| 3443 | + |
| 3444 | + #[derive(Deserialize)] |
| 3445 | + pub struct BuildParams { |
| 3446 | + pub manifest_id: i64, |
| 3447 | + pub workflow_id: Option<i64>, |
| 3448 | + pub step_id: Option<i64>, |
| 3449 | + } |
| 3450 | + |
| 3451 | + #[derive(askama::Template)] |
| 3452 | + #[template(path = "build.html")] |
| 3453 | + struct BuildTemplate<'a> { |
| 3454 | + pub base: Base, |
| 3455 | + pub collection: &'a str, |
| 3456 | + pub name: &'a str, |
| 3457 | + pub manifest: Manifest, |
| 3458 | + pub workflows: Vec<(Workflow, Vec<Step>)>, |
| 3459 | + pub dag_svg: String, |
| 3460 | + pub current_workflow: i64, |
| 3461 | + pub current_step: Option<(i64, Step)>, |
| 3462 | + pub step_output: Option<String>, |
| 3463 | + } |
| 3464 | + |
| 3465 | + pub async fn build( |
| 3466 | + Extension(cfg): Extension<Config>, |
| 3467 | + Extension(builds): Extension<Builds>, |
| 3468 | + Extension(preamble): Extension<Preamble>, |
| 3469 | + Extension(highlighter): Extension<Highlighter>, |
| 3470 | + Extension(mut base): Extension<Base>, |
| 3471 | + Path(BuildParams { |
| 3472 | + manifest_id, |
| 3473 | + workflow_id, |
| 3474 | + step_id, |
| 3475 | + }): Path<BuildParams>, |
| 3476 | + ) -> Result<Html<String>, Error> { |
| 3477 | + let db = builds.db()?; |
| 3478 | + let view = db |
| 3479 | + .read_manifest(&preamble.collection_name, &preamble.repo_name, manifest_id) |
| 3480 | + .await?; |
| 3481 | + |
| 3482 | + let current_step = if let Some(step_id) = step_id { |
| 3483 | + view.workflows.iter().find_map(|wf| { |
| 3484 | + wf.1.iter() |
| 3485 | + .find(|step| step.id == step_id) |
| 3486 | + .map(|step| (wf.0.id, step.clone())) |
| 3487 | + }) |
| 3488 | + } else { |
| 3489 | + None |
| 3490 | + }; |
| 3491 | + |
| 3492 | + let step_output = match ¤t_step { |
| 3493 | + Some((_, step)) => { |
| 3494 | + // FIXME: We need to change the db representaiton of log lines and merge |
| 3495 | + // them together here with stdout/stderr highlighting. For now I concat |
| 3496 | + // them together which is excessively stupid / annoying. |
| 3497 | + let stdout = step.stdout.as_ref().cloned().unwrap_or_default(); |
| 3498 | + let stderr = step.stderr.as_ref().cloned().unwrap_or_default(); |
| 3499 | + let combined = format!("{stdout}\n{stderr}"); |
| 3500 | + let (_, highlighted) = highlighter.highlight(&combined, None, None, None, true); |
| 3501 | + Some(highlighted) |
| 3502 | + } |
| 3503 | + None => None, |
| 3504 | + }; |
| 3505 | + |
| 3506 | + base.nav_elements = |
| 3507 | + crate::web2::navigation::primary("builds", &preamble.collection_name, &preamble.repo_name); |
| 3508 | + base.current_time = timeutil::timestamp(); |
| 3509 | + |
| 3510 | + let dag_svg = make_svg(&view); |
| 3511 | + |
| 3512 | + Ok(Html( |
| 3513 | + BuildTemplate { |
| 3514 | + base, |
| 3515 | + collection: &preamble.collection_name, |
| 3516 | + name: &preamble.repo_name, |
| 3517 | + manifest: view.manifest, |
| 3518 | + workflows: view.workflows, |
| 3519 | + dag_svg, |
| 3520 | + current_workflow: workflow_id.unwrap_or(-1), |
| 3521 | + current_step, |
| 3522 | + step_output, |
| 3523 | + } |
| 3524 | + .render()?, |
| 3525 | + )) |
| 3526 | + } |
| 3527 | + |
| 3528 | + #[derive(askama::Template)] |
| 3529 | + #[template(path = "builds.html")] |
| 3530 | + struct BuildsTemplate<'a> { |
| 3531 | + pub base: Base, |
| 3532 | + pub collection: &'a str, |
| 3533 | + pub name: &'a str, |
| 3534 | + pub items: Vec<ManifestItem>, |
| 3535 | + } |
| 3536 | + |
| 3537 | + pub async fn builds( |
| 3538 | + Extension(cfg): Extension<Config>, |
| 3539 | + Extension(builds): Extension<Builds>, |
| 3540 | + Extension(preamble): Extension<Preamble>, |
| 3541 | + Extension(mut base): Extension<Base>, |
| 3542 | + ) -> Result<Html<String>, Error> { |
| 3543 | + let db = builds.db()?; |
| 3544 | + let items = db |
| 3545 | + .list_manifest( |
| 3546 | + Some(&preamble.collection_name), |
| 3547 | + Some(&preamble.repo_name), |
| 3548 | + None, |
| 3549 | + 9999999, |
| 3550 | + 0, |
| 3551 | + ) |
| 3552 | + .await?; |
| 3553 | + // FIXME |
| 3554 | + // let manifests = db.list_manifest(999999, 0).await?; |
| 3555 | + base.nav_elements = |
| 3556 | + crate::web2::navigation::primary("builds", &preamble.collection_name, &preamble.repo_name); |
| 3557 | + base.current_time = timeutil::timestamp(); |
| 3558 | + Ok(Html( |
| 3559 | + BuildsTemplate { |
| 3560 | + base, |
| 3561 | + items, |
| 3562 | + collection: &preamble.collection_name, |
| 3563 | + name: &preamble.repo_name, |
| 3564 | + } |
| 3565 | + .render()?, |
| 3566 | + )) |
| 3567 | + } |
| 3568 | diff --git a/ayllu/src/web2/routes/mod.rs b/ayllu/src/web2/routes/mod.rs |
| 3569 | index f2dca6f..7572af5 100644 |
| 3570 | --- a/ayllu/src/web2/routes/mod.rs |
| 3571 | +++ b/ayllu/src/web2/routes/mod.rs |
| 3572 | @@ -1,6 +1,7 @@ |
| 3573 | pub mod about; |
| 3574 | pub mod assets; |
| 3575 | pub mod blob; |
| 3576 | + pub mod build; |
| 3577 | pub mod commit; |
| 3578 | pub mod config; |
| 3579 | pub mod finger; |
| 3580 | diff --git a/ayllu/src/web2/routes/repo.rs b/ayllu/src/web2/routes/repo.rs |
| 3581 | index b32c723..68e2f3f 100644 |
| 3582 | --- a/ayllu/src/web2/routes/repo.rs |
| 3583 | +++ b/ayllu/src/web2/routes/repo.rs |
| 3584 | @@ -6,7 +6,10 @@ use serde::Serialize; |
| 3585 | |
| 3586 | use crate::{ |
| 3587 | config::Config, |
| 3588 | - web2::template::{Base, DEFAULT_ANCHOR_SYMBOL}, |
| 3589 | + web2::{ |
| 3590 | + middleware::database::Builds, |
| 3591 | + template::{Base, DEFAULT_ANCHOR_SYMBOL}, |
| 3592 | + }, |
| 3593 | with_preamble, |
| 3594 | }; |
| 3595 | |
| 3596 | @@ -91,6 +94,7 @@ pub async fn serve( |
| 3597 | Extension(cfg): Extension<Config>, |
| 3598 | Extension(preamble): Extension<Preamble>, |
| 3599 | Extension(adapter): Extension<TreeSitterAdapter>, |
| 3600 | + Extension(builds): Extension<Builds>, |
| 3601 | Extension(mut base): Extension<Base>, |
| 3602 | ) -> Result<Html<String>, Error> { |
| 3603 | let repository = Wrapper::new(preamble.repo_path.as_path())?; |
| 3604 | diff --git a/ayllu/src/web2/server.rs b/ayllu/src/web2/server.rs |
| 3605 | index 946e7ec..7f957cd 100644 |
| 3606 | --- a/ayllu/src/web2/server.rs |
| 3607 | +++ b/ayllu/src/web2/server.rs |
| 3608 | @@ -17,12 +17,14 @@ use tracing::{Level, Span}; |
| 3609 | |
| 3610 | use crate::highlight::{Highlighter, Loader, TreeSitterAdapter}; |
| 3611 | use crate::languages::{Hint, LANGUAGE_TABLE}; |
| 3612 | + use crate::web2::middleware::database as db; |
| 3613 | use crate::web2::middleware::error; |
| 3614 | use crate::web2::middleware::repository; |
| 3615 | use crate::web2::middleware::sites; |
| 3616 | use crate::web2::routes::about; |
| 3617 | use crate::web2::routes::assets; |
| 3618 | use crate::web2::routes::blob; |
| 3619 | + use crate::web2::routes::build; |
| 3620 | use crate::web2::routes::commit; |
| 3621 | use crate::web2::routes::config; |
| 3622 | use crate::web2::routes::finger; |
| 3623 | @@ -82,6 +84,24 @@ pub async fn serve(cfg: &Config) -> Result<(), Box<dyn Error>> { |
| 3624 | Vec::new() |
| 3625 | }; |
| 3626 | |
| 3627 | + let mut database: Option<ayllu_database::Wrapper> = None; |
| 3628 | + |
| 3629 | + if cfg.builder.is_some() { |
| 3630 | + tracing::info!("Builder is enabled thus the database is configured"); |
| 3631 | + database = Some( |
| 3632 | + ayllu_database::Builder::default() |
| 3633 | + .path(cfg.database.as_ref().unwrap().path.as_path()) |
| 3634 | + .read_only(true) |
| 3635 | + .log_queries(false) // FIXME |
| 3636 | + .build() |
| 3637 | + .await?, |
| 3638 | + ); |
| 3639 | + } |
| 3640 | + |
| 3641 | + if database.is_some() { |
| 3642 | + tracing::info!("SQLite Database is serving"); |
| 3643 | + } |
| 3644 | + |
| 3645 | let address: SocketAddrV4 = cfg.http.address.parse()?; |
| 3646 | let app = NormalizePathLayer::trim_trailing_slash().layer( |
| 3647 | Router::new() |
| 3648 | @@ -132,6 +152,16 @@ pub async fn serve(cfg: &Config) -> Result<(), Box<dyn Error>> { |
| 3649 | .route("/refs", routing::get(refs::refs)) |
| 3650 | .route("/refs/tag/{tag_id}", routing::get(refs::tag)) |
| 3651 | .route("/refs/archive/{ref_id}", routing::get(refs::archive)) |
| 3652 | + .route("/builds", routing::get(build::builds)) |
| 3653 | + .route("/builds/{manifest_id}", routing::get(build::build)) |
| 3654 | + .route( |
| 3655 | + "/builds/{manifest_id}/{workflow_id}", |
| 3656 | + routing::get(build::build), |
| 3657 | + ) |
| 3658 | + .route( |
| 3659 | + "/builds/{manifest_id}/{workflow_id}/{step_id}", |
| 3660 | + routing::get(build::build), |
| 3661 | + ) |
| 3662 | // git smart http clone |
| 3663 | // /(HEAD|info/refs|objects/info/.*|git-upload-pack).*$ |
| 3664 | .route("/HEAD", routing::get(git::handle)) |
| 3665 | @@ -159,6 +189,7 @@ pub async fn serve(cfg: &Config) -> Result<(), Box<dyn Error>> { |
| 3666 | .layer(Extension(cfg.clone())) |
| 3667 | .layer(Extension(highlighter)) |
| 3668 | .layer(Extension(adapter)) |
| 3669 | + .layer(from_fn_with_state((cfg.clone(), database), db::middleware)) |
| 3670 | .layer(from_fn_with_state(cfg.clone(), template::middleware)) |
| 3671 | // error handling |
| 3672 | .layer(from_fn_with_state(Arc::new(cfg.clone()), error::middleware)) |
| 3673 | diff --git a/ayllu/src/web2/template.rs b/ayllu/src/web2/template.rs |
| 3674 | index eecfcaf..28a865c 100644 |
| 3675 | --- a/ayllu/src/web2/template.rs |
| 3676 | +++ b/ayllu/src/web2/template.rs |
| 3677 | @@ -104,6 +104,16 @@ pub mod filters { |
| 3678 | Ok(timeutil::friendly(*epoch as u64)) |
| 3679 | } |
| 3680 | |
| 3681 | + pub fn friendly_time_maybe( |
| 3682 | + epoch: &Option<i64>, |
| 3683 | + values: &dyn askama::Values, |
| 3684 | + ) -> askama::Result<String> { |
| 3685 | + match epoch { |
| 3686 | + Some(value) => friendly_time(value, values), |
| 3687 | + None => Ok("?".to_string()), |
| 3688 | + } |
| 3689 | + } |
| 3690 | + |
| 3691 | pub fn format_epoch(epoch: &i64, _: &dyn askama::Values) -> askama::Result<String> { |
| 3692 | let ts = OffsetDateTime::from_unix_timestamp(*epoch).unwrap(); |
| 3693 | let formatted = ts.format(&well_known::Rfc2822).unwrap(); |
| 3694 | @@ -123,14 +133,27 @@ pub mod filters { |
| 3695 | Ok(util::human_bytes(*bytes as f64)) |
| 3696 | } |
| 3697 | |
| 3698 | + pub fn friendly_duration_i64( |
| 3699 | + input: &Option<i64>, |
| 3700 | + _: &dyn askama::Values, |
| 3701 | + ) -> askama::Result<String> { |
| 3702 | + match input { |
| 3703 | + Some(value) => Ok(format!( |
| 3704 | + "{:?}", |
| 3705 | + std::time::Duration::from_millis(*value as u64) |
| 3706 | + )), |
| 3707 | + None => Ok("?".to_string()), |
| 3708 | + } |
| 3709 | + } |
| 3710 | + |
| 3711 | pub fn verified_class_name( |
| 3712 | verified: &Option<bool>, |
| 3713 | _: &dyn askama::Values, |
| 3714 | ) -> askama::Result<String> { |
| 3715 | - if verified.is_some_and(|verified| verified) { |
| 3716 | - Ok(String::from("positive")) |
| 3717 | - } else { |
| 3718 | - Ok(String::from("negative")) |
| 3719 | + match verified { |
| 3720 | + Some(true) => Ok(String::from("positive")), |
| 3721 | + Some(false) => Ok(String::from("negative")), |
| 3722 | + None => Ok(String::from("unknown")), |
| 3723 | } |
| 3724 | } |
| 3725 | |
| 3726 | diff --git a/ayllu/templates/build.html b/ayllu/templates/build.html |
| 3727 | new file mode 100644 |
| 3728 | index 0000000..4c9ad9d |
| 3729 | --- /dev/null |
| 3730 | +++ b/ayllu/templates/build.html |
| 3731 | @@ -0,0 +1,92 @@ |
| 3732 | + {% extends "base.html" %} |
| 3733 | + {% block content %} |
| 3734 | + <section id="builds" class="scrollable raised"> |
| 3735 | + <section class="info-bar"> |
| 3736 | + <section class="title"><a href="/{{collection}}/{{name}}/builds/{{manifest.id}}">Build for {{collection}}/{{name}}: {{manifest.id}}</a></section> |
| 3737 | + </section> |
| 3738 | + <section class="raised lower-half"> |
| 3739 | + <section class="dag scrollable"> |
| 3740 | + {{ dag_svg | safe }} |
| 3741 | + </section> |
| 3742 | + {% for workflow in workflows %} |
| 3743 | + <section class="scrollable"> |
| 3744 | + <section class="info-bar flex-group"> |
| 3745 | + <section class="title"> |
| 3746 | + <a href="/{{collection}}/{{name}}/builds/{{manifest.id}}/{{workflow.0.id}}">{{ workflow.0.name }} {%- if workflow.0.id == current_workflow %} <{%- endif -%}</a> |
| 3747 | + </section> |
| 3748 | + <section> Workflow </section> |
| 3749 | + </section> |
| 3750 | + <table class="data-table lower-half"> |
| 3751 | + <thead> |
| 3752 | + <tr> |
| 3753 | + <th>ID</th> |
| 3754 | + <th>Name</th> |
| 3755 | + <th>StartedAt</th> |
| 3756 | + <!-- <th>Duration</th> --> |
| 3757 | + <th>ExitCode</th> |
| 3758 | + </tr> |
| 3759 | + </thead> |
| 3760 | + <tbody> |
| 3761 | + {% for step in workflow.1 %} |
| 3762 | + {%- if let Some(current_step) = current_step -%} |
| 3763 | + {%- if current_step.1.id == step.id -%} |
| 3764 | + <tr class="selected"> |
| 3765 | + {%- else -%} |
| 3766 | + <tr> |
| 3767 | + {%- endif -%} |
| 3768 | + {%- else -%} |
| 3769 | + <tr> |
| 3770 | + {%- endif -%} |
| 3771 | + <td><a href="/{{collection}}/{{name}}/builds/{{manifest.id}}/{{workflow.0.id}}/{{step.id}}"> |
| 3772 | + {{step.id}} |
| 3773 | + </td> |
| 3774 | + <td>{{step.name}}</td> |
| 3775 | + <td>{{step.started_at | friendly_time_maybe }}</td> |
| 3776 | + <td>{%- if let Some(exit_code) = step.exit_code -%} {{ exit_code }} {%- else -%} ? {%- endif -%}</td> |
| 3777 | + </tr> |
| 3778 | + {% endfor %} |
| 3779 | + </tbody> |
| 3780 | + </table> |
| 3781 | + {%- if let Some(current_step) = current_step -%} |
| 3782 | + {%- if current_step.0 == workflow.0.id -%} |
| 3783 | + <section class="scrollable raised inner"> |
| 3784 | + <section class="info-bar flex-group selected"> |
| 3785 | + <section class="title"> |
| 3786 | + {{ current_step.1.name }} |
| 3787 | + </section> |
| 3788 | + </section> |
| 3789 | + <section class="lower-half"> |
| 3790 | + <table class="data-table"> |
| 3791 | + <thead> |
| 3792 | + <tr> |
| 3793 | + <th>Name</th> |
| 3794 | + <th>Value</th> |
| 3795 | + </tr> |
| 3796 | + </thead> |
| 3797 | + <tbody> |
| 3798 | + <tr> |
| 3799 | + <td> Shell </td> |
| 3800 | + <td> {{ current_step.1.shell }} </td> |
| 3801 | + </tr> |
| 3802 | + <tr> |
| 3803 | + <td> Command </td> |
| 3804 | + <td><code>{{ current_step.1.input }}</code></td> |
| 3805 | + </tr> |
| 3806 | + </tbody> |
| 3807 | + </table> |
| 3808 | + |
| 3809 | + {%- if let Some(step_output) = step_output -%} |
| 3810 | + <section id="code-viewer" class="scrollable"> |
| 3811 | + {{ step_output | safe}} |
| 3812 | + </section> |
| 3813 | + {%- endif -%} |
| 3814 | + |
| 3815 | + </section> |
| 3816 | + </section> |
| 3817 | + {%- endif -%} |
| 3818 | + {%- endif -%} |
| 3819 | + </section> |
| 3820 | + {% endfor %} |
| 3821 | + </section> |
| 3822 | + </section> |
| 3823 | + {% endblock %} |
| 3824 | diff --git a/ayllu/templates/builds.html b/ayllu/templates/builds.html |
| 3825 | new file mode 100644 |
| 3826 | index 0000000..01ab8d8 |
| 3827 | --- /dev/null |
| 3828 | +++ b/ayllu/templates/builds.html |
| 3829 | @@ -0,0 +1,42 @@ |
| 3830 | + {% extends "base.html" %} |
| 3831 | + {% block content %} |
| 3832 | + <section id="builds" class="scrollable raised"> |
| 3833 | + <section class="info-bar"> |
| 3834 | + <section class="title">Builds</section> |
| 3835 | + </section> |
| 3836 | + <table class="data-table lower-half"> |
| 3837 | + <thead> |
| 3838 | + <tr> |
| 3839 | + <th>ID</th> |
| 3840 | + <th>Status</th> |
| 3841 | + <th>CreatedAt</th> |
| 3842 | + <!-- <th>Duration</th> --> |
| 3843 | + </tr> |
| 3844 | + </thead> |
| 3845 | + <tbody> |
| 3846 | + {% for item in items %} |
| 3847 | + <tr class="build"> |
| 3848 | + <td> |
| 3849 | + <div class="name"> |
| 3850 | + <a href="/{{collection}}/{{name}}/builds/{{item.manifest.id}}">{{item.manifest.id}}</a> |
| 3851 | + </div> |
| 3852 | + </td> |
| 3853 | + <td> |
| 3854 | + {%- for workflow in item.workflows -%} |
| 3855 | + <span class="workflow"> |
| 3856 | + <a href="/{{collection}}/{{name}}/builds/{{item.manifest.id}}/{{- workflow.0 -}}">{{- workflow.1 -}}:</a> |
| 3857 | + {%- for step in workflow.2 -%} |
| 3858 | + <span class="step {{step.2 | verified_class_name }}"> |
| 3859 | + <a href="/{{collection}}/{{name}}/builds/{{item.manifest.id}}/{{- workflow.0 -}}/{{- step.0 -}}">{{- step.1 -}}</a> |
| 3860 | + </span> |
| 3861 | + {%- endfor -%} |
| 3862 | + </span> |
| 3863 | + {%- endfor -%} |
| 3864 | + </td> |
| 3865 | + <td>{{ item.manifest.created_at | friendly_time }}</td> |
| 3866 | + </tr> |
| 3867 | + {% endfor %} |
| 3868 | + </tbody> |
| 3869 | + </table> |
| 3870 | + </section> |
| 3871 | + {% endblock %} |
| 3872 | diff --git a/ayllu/templates/step.html b/ayllu/templates/step.html |
| 3873 | new file mode 100644 |
| 3874 | index 0000000..2b93aa4 |
| 3875 | --- /dev/null |
| 3876 | +++ b/ayllu/templates/step.html |
| 3877 | @@ -0,0 +1,10 @@ |
| 3878 | + {% extends "base.html" %} |
| 3879 | + {% block content %} |
| 3880 | + <section id="builds" class="scrollable raised"> |
| 3881 | + <section class="info-bar"> |
| 3882 | + <section class="title">Step {{ step.id }}</section> |
| 3883 | + </section> |
| 3884 | + <section class="raised lower-half"> |
| 3885 | + </section> |
| 3886 | + </section> |
| 3887 | + {% endblock %} |
| 3888 | diff --git a/ayllu/templates/workflow.html b/ayllu/templates/workflow.html |
| 3889 | new file mode 100644 |
| 3890 | index 0000000..bf1a8f0 |
| 3891 | --- /dev/null |
| 3892 | +++ b/ayllu/templates/workflow.html |
| 3893 | @@ -0,0 +1,34 @@ |
| 3894 | + {% extends "base.html" %} |
| 3895 | + {% block content %} |
| 3896 | + <section id="builds" class="scrollable raised"> |
| 3897 | + <section class="info-bar"> |
| 3898 | + <section class="title">Workflow: {{manifest_id}}/{{workflow.id}}</section> |
| 3899 | + </section> |
| 3900 | + <section class="raised lower-half"> |
| 3901 | + <section class="info-bar"> |
| 3902 | + <section class="title">Workflow: <a href="/{{collection}}/{{name}}/builds/{{manifest_id}}/{{workflow.id}}">{{ workflow.name }}</a></section> |
| 3903 | + </section> |
| 3904 | + <table class="data-table lower-half"> |
| 3905 | + <thead> |
| 3906 | + <tr> |
| 3907 | + <th>ID</th> |
| 3908 | + <th>Name</th> |
| 3909 | + <th>StartedAt</th> |
| 3910 | + <!-- <th>Duration</th> --> |
| 3911 | + <th>ExitCode</th> |
| 3912 | + </tr> |
| 3913 | + </thead> |
| 3914 | + <tbody> |
| 3915 | + {% for step in steps %} |
| 3916 | + <tr> |
| 3917 | + <td><a href="/{{collection}}/{{name}}/builds/{{manifest_id}}/{{workflow.id}}/{{step.id}}">{{step.id}}</td> |
| 3918 | + <td>{{step.name}}</td> |
| 3919 | + <td>{{step.started_at | friendly_time_maybe }}</td> |
| 3920 | + <td>{%- if let Some(exit_code) = step.exit_code -%} {{ exit_code }} {%- else -%} ? {%- endif -%}</td> |
| 3921 | + </tr> |
| 3922 | + {% endfor %} |
| 3923 | + </tbody> |
| 3924 | + </table> |
| 3925 | + </section> |
| 3926 | + </section> |
| 3927 | + {% endblock %} |
| 3928 | diff --git a/ayllu/themes/base.css b/ayllu/themes/base.css |
| 3929 | index 7b2a607..cf04145 100644 |
| 3930 | --- a/ayllu/themes/base.css |
| 3931 | +++ b/ayllu/themes/base.css |
| 3932 | @@ -24,10 +24,14 @@ main { |
| 3933 | white-space: nowrap; |
| 3934 | } |
| 3935 | |
| 3936 | - section#log > section > .data-table > tbody > tr > td:first-child { |
| 3937 | + section#log>section>.data-table>tbody>tr>td:first-child { |
| 3938 | text-align: center; |
| 3939 | } |
| 3940 | |
| 3941 | + section.inner { |
| 3942 | + padding: 5px; |
| 3943 | + } |
| 3944 | + |
| 3945 | a:visited { |
| 3946 | text-decoration: none; |
| 3947 | } |
| 3948 | @@ -91,7 +95,7 @@ section.info-bar { |
| 3949 | text-decoration: underline; |
| 3950 | } |
| 3951 | |
| 3952 | - section.clone > section.title { |
| 3953 | + section.clone>section.title { |
| 3954 | padding-bottom: 10px; |
| 3955 | } |
| 3956 | |
| 3957 | @@ -99,14 +103,14 @@ section.info-bar.single { |
| 3958 | border-bottom: solid 2px; |
| 3959 | } |
| 3960 | |
| 3961 | - section.info-bar > section { |
| 3962 | + section.info-bar>section { |
| 3963 | align-content: center; |
| 3964 | justify-content: center; |
| 3965 | } |
| 3966 | |
| 3967 | - section.badge-group > section:first-child { |
| 3968 | + section.badge-group>section:first-child { |
| 3969 | margin-top: 1em; |
| 3970 | - margin-bottom: 1em; |
| 3971 | + margin-bottom: 1em; |
| 3972 | } |
| 3973 | |
| 3974 | section#code-viewer { |
| 3975 | @@ -127,7 +131,7 @@ section#commit-summary { |
| 3976 | border-radius: 5px; |
| 3977 | } |
| 3978 | |
| 3979 | - section#commit-summary > section > pre { |
| 3980 | + section#commit-summary>section>pre { |
| 3981 | border-radius: 5px; |
| 3982 | padding: 1em; |
| 3983 | } |
| 3984 | @@ -145,6 +149,14 @@ section#commit-message { |
| 3985 | margin-bottom: 0; |
| 3986 | } |
| 3987 | |
| 3988 | + /* span.workflow { */ |
| 3989 | + /* border: solid; */ |
| 3990 | + /* } */ |
| 3991 | + |
| 3992 | + span.workflow>.step::before { |
| 3993 | + content: "•" |
| 3994 | + } |
| 3995 | + |
| 3996 | span#ref-badge::before { |
| 3997 | content: "Ref:: "; |
| 3998 | } |
| 3999 | @@ -157,7 +169,7 @@ section#rss-links { |
| 4000 | display: flex; |
| 4001 | } |
| 4002 | |
| 4003 | - section#rss-links > section#rss-link-items { |
| 4004 | + section#rss-links>section#rss-link-items { |
| 4005 | display: flex; |
| 4006 | justify-content: flex-start; |
| 4007 | align-items: center; |
| 4008 | @@ -167,7 +179,7 @@ section#readme { |
| 4009 | padding: 1em; |
| 4010 | } |
| 4011 | |
| 4012 | - section#readme > header { |
| 4013 | + section#readme>header { |
| 4014 | margin: 5px; |
| 4015 | } |
| 4016 | |
| 4017 | @@ -230,11 +242,11 @@ section#repo-details-panel { |
| 4018 | padding: 1em; |
| 4019 | } |
| 4020 | |
| 4021 | - section#config-panel > section { |
| 4022 | + section#config-panel>section { |
| 4023 | padding: 1em; |
| 4024 | } |
| 4025 | |
| 4026 | - section#config-panel > section > form > button { |
| 4027 | + section#config-panel>section>form>button { |
| 4028 | margin-top: 1em; |
| 4029 | display: block; |
| 4030 | } |
| 4031 | @@ -253,7 +265,7 @@ section.selectable-text { |
| 4032 | text-decoration: none; |
| 4033 | } |
| 4034 | |
| 4035 | - section.selectable-text > span.protocol-badge { |
| 4036 | + section.selectable-text>span.protocol-badge { |
| 4037 | font-variant: all-petite-caps; |
| 4038 | border-style: solid; |
| 4039 | border-width: 3px 3px 3px 3px; |
| 4040 | @@ -261,7 +273,7 @@ section.selectable-text > span.protocol-badge { |
| 4041 | user-select: none; |
| 4042 | } |
| 4043 | |
| 4044 | - section.selectable-text > span.selectable { |
| 4045 | + section.selectable-text>span.selectable { |
| 4046 | max-width: 300px; |
| 4047 | overflow: scroll; |
| 4048 | border-style: solid; |
| 4049 | @@ -271,6 +283,10 @@ section.selectable-text > span.selectable { |
| 4050 | cursor: pointer; |
| 4051 | } |
| 4052 | |
| 4053 | + section.dag { |
| 4054 | + text-align: center; |
| 4055 | + } |
| 4056 | + |
| 4057 | footer { |
| 4058 | padding-top: 2em; |
| 4059 | text-align: center; |
| 4060 | @@ -331,7 +347,7 @@ code.highlighted { |
| 4061 | overflow: scroll; |
| 4062 | } |
| 4063 | |
| 4064 | - .code > tbody > tr > td { |
| 4065 | + .code>tbody>tr>td { |
| 4066 | text-align: revert; |
| 4067 | padding: 0 0 0 0; |
| 4068 | padding-right: 0.5em; |
| 4069 | @@ -372,8 +388,8 @@ li.active { |
| 4070 | flex-direction: column; |
| 4071 | } |
| 4072 | |
| 4073 | - section.flex-group > section { |
| 4074 | + section.flex-group>section { |
| 4075 | width: 100%; |
| 4076 | height: auto; |
| 4077 | } |
| 4078 | - } |
| 4079 | + } |
| 4080 | \ No newline at end of file |
| 4081 | diff --git a/ayllu/themes/catppuccin.css b/ayllu/themes/catppuccin.css |
| 4082 | index 3ded025..e6f3905 100644 |
| 4083 | --- a/ayllu/themes/catppuccin.css |
| 4084 | +++ b/ayllu/themes/catppuccin.css |
| 4085 | @@ -62,6 +62,14 @@ a { |
| 4086 | color: var(--ctp-latte-blue); |
| 4087 | } |
| 4088 | |
| 4089 | + .selected { |
| 4090 | + background-color: var(--ctp-latte-lavender); |
| 4091 | + } |
| 4092 | + |
| 4093 | + section.dag { |
| 4094 | + background-color: var(--ctp-latte-base); |
| 4095 | + } |
| 4096 | + |
| 4097 | body { |
| 4098 | color: var(--ctp-latte-text); |
| 4099 | background-color: var(--ctp-latte-base); |
| 4100 | @@ -73,6 +81,7 @@ nav { |
| 4101 | font-weight: bold; |
| 4102 | font-size: large; |
| 4103 | } |
| 4104 | + |
| 4105 | color: var(--ctp-latte-text); |
| 4106 | background-color: var(--ctp-latte-mantle); |
| 4107 | } |
| 4108 | @@ -94,13 +103,13 @@ table.data-table tbody tr:nth-child(even) { |
| 4109 | background-color: var(--ctp-latte-surface1); |
| 4110 | } |
| 4111 | |
| 4112 | - section.selectable-text > span.selectable { |
| 4113 | + section.selectable-text>span.selectable { |
| 4114 | color: var(--ctp-latte-text); |
| 4115 | border-color: var(--ctp-latte-lavender); |
| 4116 | background-color: var(--ctp-latte-mantle); |
| 4117 | } |
| 4118 | |
| 4119 | - section.selectable-text > span.protocol-badge { |
| 4120 | + section.selectable-text>span.protocol-badge { |
| 4121 | color: var(--ctp-latte-mantle); |
| 4122 | border-color: var(--ctp-latte-lavender); |
| 4123 | background-color: var(--ctp-latte-text); |
| 4124 | @@ -139,7 +148,7 @@ section#commit-summary { |
| 4125 | background: var(--ctp-latte-surface0); |
| 4126 | } |
| 4127 | |
| 4128 | - section#commit-summary > section > pre { |
| 4129 | + section#commit-summary>section>pre { |
| 4130 | background-color: var(--ctp-latte-mantle); |
| 4131 | } |
| 4132 | |
| 4133 | @@ -228,10 +237,17 @@ span.ts_addition { |
| 4134 | font-weight: bold; |
| 4135 | font-size: large; |
| 4136 | } |
| 4137 | + |
| 4138 | color: var(--ctp-mocha-lavender); |
| 4139 | background-color: var(--ctp-mocha-surface0); |
| 4140 | } |
| 4141 | |
| 4142 | + |
| 4143 | + |
| 4144 | + section.dag { |
| 4145 | + background-color: var(--ctp-mocha-overlay0); |
| 4146 | + } |
| 4147 | + |
| 4148 | nav .subnav { |
| 4149 | background-color: var(--ctp-mocha-surface1); |
| 4150 | } |
| 4151 | @@ -241,13 +257,14 @@ span.ts_addition { |
| 4152 | background-color: var(--ctp-mocha-base); |
| 4153 | } |
| 4154 | |
| 4155 | - section.selectable-text > .selectable { |
| 4156 | + section.selectable-text>.selectable { |
| 4157 | color: var(--ctp-mocha-base); |
| 4158 | background-color: var(--ctp-mocha-lavender); |
| 4159 | } |
| 4160 | |
| 4161 | .data-table { |
| 4162 | color: var(--ctp-mocha-text); |
| 4163 | + |
| 4164 | a { |
| 4165 | color: var(--ctp-mocha-blue); |
| 4166 | } |
| 4167 | @@ -285,7 +302,7 @@ span.ts_addition { |
| 4168 | background-color: var(--ctp-mocha-surface1); |
| 4169 | } |
| 4170 | |
| 4171 | - section#commit-summary > section > pre { |
| 4172 | + section#commit-summary>section>pre { |
| 4173 | background-color: var(--ctp-mocha-mantle); |
| 4174 | } |
| 4175 | - } |
| 4176 | + } |
| 4177 | \ No newline at end of file |
| 4178 | diff --git a/ayllu/themes/default.css b/ayllu/themes/default.css |
| 4179 | index 07d26ef..3d693fd 100644 |
| 4180 | --- a/ayllu/themes/default.css |
| 4181 | +++ b/ayllu/themes/default.css |
| 4182 | @@ -11,6 +11,11 @@ |
| 4183 | } |
| 4184 | } |
| 4185 | |
| 4186 | + .selected { |
| 4187 | + color: var(--secondary-color); |
| 4188 | + background-color: var(--primary-color); |
| 4189 | + } |
| 4190 | + |
| 4191 | body { |
| 4192 | color: var(--primary-color); |
| 4193 | background-color: var(--secondary-color); |
| 4194 | @@ -104,4 +109,4 @@ span.ts_removal { |
| 4195 | |
| 4196 | span.ts_addition { |
| 4197 | color: var(--primary-color); |
| 4198 | - } |
| 4199 | + } |
| 4200 | \ No newline at end of file |
| 4201 | diff --git a/ayllu/themes/nord.css b/ayllu/themes/nord.css |
| 4202 | index f77bf15..692dbc1 100644 |
| 4203 | --- a/ayllu/themes/nord.css |
| 4204 | +++ b/ayllu/themes/nord.css |
| 4205 | @@ -37,6 +37,7 @@ nav { |
| 4206 | font-weight: bold; |
| 4207 | font-size: large; |
| 4208 | } |
| 4209 | + |
| 4210 | color: var(--nord6); |
| 4211 | background-color: var(--nord9); |
| 4212 | } |
| 4213 | @@ -58,13 +59,13 @@ table.data-table thead { |
| 4214 | background-color: var(--nord10); |
| 4215 | } |
| 4216 | |
| 4217 | - section.selectable-text > span.text { |
| 4218 | + section.selectable-text>span.text { |
| 4219 | color: var(--nord0); |
| 4220 | border-color: var(--nord10); |
| 4221 | background-color: var(--nord5); |
| 4222 | } |
| 4223 | |
| 4224 | - section.selectable-text > span.protocol-badge { |
| 4225 | + section.selectable-text>span.protocol-badge { |
| 4226 | color: var(--nord6); |
| 4227 | border-color: var(--nord10); |
| 4228 | background-color: var(--nord0); |
| 4229 | @@ -74,7 +75,7 @@ section#readme-header { |
| 4230 | background-color: var(--nord7); |
| 4231 | } |
| 4232 | |
| 4233 | - section > a { |
| 4234 | + section>a { |
| 4235 | color: var(--nord5); |
| 4236 | } |
| 4237 | |
| 4238 | @@ -88,7 +89,7 @@ section#commit-summary { |
| 4239 | background-color: var(--nord4); |
| 4240 | } |
| 4241 | |
| 4242 | - section#commit-summary > section > pre { |
| 4243 | + section#commit-summary>section>pre { |
| 4244 | background-color: var(--nord5); |
| 4245 | } |
| 4246 | |
| 4247 | @@ -104,6 +105,14 @@ section.info-bar.single { |
| 4248 | text-shadow: 1px 1px 5px var(--nord11); |
| 4249 | } |
| 4250 | |
| 4251 | + .selected { |
| 4252 | + background-color: var(--nord7) !important; |
| 4253 | + } |
| 4254 | + |
| 4255 | + section.dag { |
| 4256 | + background-color: var(--nord4); |
| 4257 | + } |
| 4258 | + |
| 4259 | /* Syntax Highlighting */ |
| 4260 | |
| 4261 | section#code-viewer { |
| 4262 | @@ -188,10 +197,12 @@ span.ts_addition { |
| 4263 | color: var(--nord4); |
| 4264 | background-color: var(--nord0); |
| 4265 | } |
| 4266 | + |
| 4267 | nav { |
| 4268 | a { |
| 4269 | color: var(--nord6); |
| 4270 | } |
| 4271 | + |
| 4272 | color: var(--nord6); |
| 4273 | background-color: var(--nord2); |
| 4274 | } |
| 4275 | @@ -200,11 +211,16 @@ span.ts_addition { |
| 4276 | background-color: var(--nord3); |
| 4277 | } |
| 4278 | |
| 4279 | - section.selectable-text > span.text { |
| 4280 | + |
| 4281 | + section.dag { |
| 4282 | + background-color: var(--nord3); |
| 4283 | + } |
| 4284 | + |
| 4285 | + section.selectable-text>span.text { |
| 4286 | border-color: var(--nord6); |
| 4287 | } |
| 4288 | |
| 4289 | - section.selectable-text > span.protocol-badge { |
| 4290 | + section.selectable-text>span.protocol-badge { |
| 4291 | background-color: var(--nord4); |
| 4292 | color: var(--nord0); |
| 4293 | border-color: var(--nord6); |
| 4294 | @@ -214,7 +230,7 @@ span.ts_addition { |
| 4295 | background-color: var(--nord3); |
| 4296 | } |
| 4297 | |
| 4298 | - section#tree > table > thead { |
| 4299 | + section#tree>table>thead { |
| 4300 | color: var(--nord0); |
| 4301 | background-color: var(--nord4); |
| 4302 | } |
| 4303 | @@ -251,7 +267,7 @@ span.ts_addition { |
| 4304 | border-bottom-color: var(--nord5); |
| 4305 | } |
| 4306 | |
| 4307 | - section > a { |
| 4308 | + section>a { |
| 4309 | color: var(--nord5); |
| 4310 | } |
| 4311 | |
| 4312 | @@ -259,7 +275,7 @@ span.ts_addition { |
| 4313 | background-color: var(--nord2); |
| 4314 | } |
| 4315 | |
| 4316 | - section#commit-summary > section > pre { |
| 4317 | + section#commit-summary>section>pre { |
| 4318 | background-color: var(--nord3); |
| 4319 | } |
| 4320 | |
| 4321 | @@ -267,4 +283,4 @@ span.ts_addition { |
| 4322 | color: var(--nord8); |
| 4323 | } |
| 4324 | |
| 4325 | - } |
| 4326 | + } |
| 4327 | \ No newline at end of file |
| 4328 | diff --git a/config.example.toml b/config.example.toml |
| 4329 | index 1df821d..75cfa82 100644 |
| 4330 | --- a/config.example.toml |
| 4331 | +++ b/config.example.toml |
| 4332 | @@ -301,3 +301,15 @@ A Hyper Performant & Hackable Code Forge Built on Open Standards. |
| 4333 | # authorized_keys = [ |
| 4334 | # ".. your key here .." |
| 4335 | # ] |
| 4336 | + |
| 4337 | + # Global SQLite database used for all persistent storage outside of Git. |
| 4338 | + # You need to run ayllu-migrate to apply any migrations |
| 4339 | + # [database] |
| 4340 | + # Path to the SQLite database |
| 4341 | + # path = "/usr/share/ayllu/state.db" |
| 4342 | + # Directory of Migrations |
| 4343 | + # migrations = "/usr/lib/ayllu/migrations" |
| 4344 | + |
| 4345 | + # Global Builder configuration |
| 4346 | + # Used to configure the runtime properties of ayllu-build |
| 4347 | + # [builder] |
| 4348 | diff --git a/crates/api/src/build.rs b/crates/api/src/build.rs |
| 4349 | index 426f91d..de3c49c 100644 |
| 4350 | --- a/crates/api/src/build.rs |
| 4351 | +++ b/crates/api/src/build.rs |
| 4352 | @@ -1,62 +1,23 @@ |
| 4353 | - use serde::{Deserialize, Serialize}; |
| 4354 | - |
| 4355 | - #[derive(Debug, Deserialize, Serialize)] |
| 4356 | - /// Defines some kind of event that occurs within a repository |
| 4357 | - pub enum Kind { |
| 4358 | - Commit, |
| 4359 | - Tag, |
| 4360 | - } |
| 4361 | - |
| 4362 | - #[derive(Debug, Deserialize, Serialize)] |
| 4363 | - pub struct Event { |
| 4364 | - pub repository_url: String, |
| 4365 | - pub commit_hash: String, |
| 4366 | - pub kind: Kind, |
| 4367 | - } |
| 4368 | + use std::fmt::Display; |
| 4369 | |
| 4370 | - #[derive(Debug, Deserialize, Serialize)] |
| 4371 | - /// array of samples taken to construct informative charts in the UI |
| 4372 | - pub struct Samples { |
| 4373 | - load_1m: Vec<f32>, |
| 4374 | - load_5m: Vec<f32>, |
| 4375 | - load_15m: Vec<f32>, |
| 4376 | - disk_total_bytes: Vec<i64>, |
| 4377 | - disk_free_bytes: Vec<i64>, |
| 4378 | - net_sent_bytes: Vec<i64>, |
| 4379 | - net_received_bytes: Vec<i64>, |
| 4380 | - net_sent_packets: Vec<i64>, |
| 4381 | - net_received_packets: Vec<i64>, |
| 4382 | - mem_total_bytes: Vec<i64>, |
| 4383 | - mem_free_bytes: Vec<i64>, |
| 4384 | - mem_available_bytes: Vec<i64>, |
| 4385 | - } |
| 4386 | - |
| 4387 | - #[derive(Debug, Deserialize, Serialize)] |
| 4388 | - pub struct Step { |
| 4389 | - pub id: i64, |
| 4390 | - pub input: String, |
| 4391 | - pub shell: String, |
| 4392 | - } |
| 4393 | + use serde::{Deserialize, Serialize}; |
| 4394 | |
| 4395 | - #[derive(Debug, Deserialize, Serialize)] |
| 4396 | - pub struct Job { |
| 4397 | - pub id: i64, |
| 4398 | - pub name: String, |
| 4399 | - pub steps: Vec<Step>, |
| 4400 | + /// Unit of execution which is either a workflow or a step |
| 4401 | + #[derive(Serialize, Deserialize, Debug, Clone)] |
| 4402 | + pub enum Unit { |
| 4403 | + Step(i64), |
| 4404 | + Workflow(i64), |
| 4405 | } |
| 4406 | |
| 4407 | - #[derive(Debug, Deserialize, Serialize)] |
| 4408 | - pub struct Manifest { |
| 4409 | - pub id: i64, |
| 4410 | - repository_url: String, |
| 4411 | - git_hash: String, |
| 4412 | - /// DOT representation of DAG rendered via manifest |
| 4413 | - dot_chart: String, |
| 4414 | - created_at: i64, |
| 4415 | - started_at: i64, |
| 4416 | - finished_at: i64, |
| 4417 | - success: bool, |
| 4418 | - // not included on manfest list calls otherwise ordered in the way |
| 4419 | - // that they are evaluated via dependency graph |
| 4420 | - jobs: Vec<Job>, |
| 4421 | + impl Display for Unit { |
| 4422 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 4423 | + match self { |
| 4424 | + Unit::Step(id) => { |
| 4425 | + write!(f, "Step: {id}") |
| 4426 | + } |
| 4427 | + Unit::Workflow(id) => { |
| 4428 | + write!(f, "Workflow: {id}") |
| 4429 | + } |
| 4430 | + } |
| 4431 | + } |
| 4432 | } |
| 4433 | diff --git a/crates/cmd/src/lib.rs b/crates/cmd/src/lib.rs |
| 4434 | index 473f986..9ea472d 100644 |
| 4435 | --- a/crates/cmd/src/lib.rs |
| 4436 | +++ b/crates/cmd/src/lib.rs |
| 4437 | @@ -1,5 +1,6 @@ |
| 4438 | pub mod ayllu; |
| 4439 | pub mod keys; |
| 4440 | + pub mod migrate; |
| 4441 | pub mod quipu; |
| 4442 | pub mod shell; |
| 4443 | |
| 4444 | diff --git a/crates/cmd/src/migrate.rs b/crates/cmd/src/migrate.rs |
| 4445 | new file mode 100644 |
| 4446 | index 0000000..ac86806 |
| 4447 | --- /dev/null |
| 4448 | +++ b/crates/cmd/src/migrate.rs |
| 4449 | @@ -0,0 +1,23 @@ |
| 4450 | + use std::path::PathBuf; |
| 4451 | + |
| 4452 | + use clap::Parser; |
| 4453 | + |
| 4454 | + const LONG_ABOUT_DESCRIPTION: &str = r#" |
| 4455 | + |
| 4456 | + ayllu-migrate is used to manage the shared global sqlite database used across |
| 4457 | + all ayllu binaries installed on the system. Anytime a schema change is introduced |
| 4458 | + ayllu-migrate must be invoked. Typically this should only be ran by your package |
| 4459 | + management system but may also be useful as a standalone component. |
| 4460 | + "#; |
| 4461 | + |
| 4462 | + /// Manage the global Ayllu sqlite database |
| 4463 | + #[derive(Parser, Debug)] |
| 4464 | + #[clap(version, about, name = "ayllu-migrate", long_about = LONG_ABOUT_DESCRIPTION)] |
| 4465 | + pub struct Command { |
| 4466 | + /// Path to your configuration file |
| 4467 | + #[arg(short, long, value_name = "FILE")] |
| 4468 | + pub config: Option<PathBuf>, |
| 4469 | + #[arg(short, long, value_name = "FILE")] |
| 4470 | + /// Optional path to migration files |
| 4471 | + pub migrations: Option<PathBuf>, |
| 4472 | + } |
| 4473 | diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs |
| 4474 | index 2327afc..322c1a8 100644 |
| 4475 | --- a/crates/config/src/lib.rs |
| 4476 | +++ b/crates/config/src/lib.rs |
| 4477 | @@ -1,8 +1,46 @@ |
| 4478 | + use std::path::{Path, PathBuf}; |
| 4479 | + |
| 4480 | pub use error::Error; |
| 4481 | pub use flags::Command; |
| 4482 | pub use reader::{data_dir, runtime_dir, Configurable, Reader}; |
| 4483 | + use serde::{Deserialize, Serialize}; |
| 4484 | |
| 4485 | mod edit; |
| 4486 | mod error; |
| 4487 | mod flags; |
| 4488 | mod reader; |
| 4489 | + |
| 4490 | + /// Global database configuration used in all ayllu components |
| 4491 | + #[derive(Deserialize, Serialize, Clone, Debug)] |
| 4492 | + pub struct Database { |
| 4493 | + #[serde(default = "Database::path_default")] |
| 4494 | + pub path: PathBuf, |
| 4495 | + #[serde(default = "Database::migrate_default")] |
| 4496 | + pub migrate: bool, |
| 4497 | + #[serde(default = "Database::migrations_default")] |
| 4498 | + pub migrations: PathBuf, |
| 4499 | + } |
| 4500 | + |
| 4501 | + impl Database { |
| 4502 | + fn path_default() -> PathBuf { |
| 4503 | + data_dir().join("ayllu.sqlite").to_path_buf() |
| 4504 | + } |
| 4505 | + |
| 4506 | + fn migrations_default() -> PathBuf { |
| 4507 | + Path::new("/usr/lib/ayllu/migrations").to_path_buf() |
| 4508 | + } |
| 4509 | + |
| 4510 | + fn migrate_default() -> bool { |
| 4511 | + true |
| 4512 | + } |
| 4513 | + } |
| 4514 | + |
| 4515 | + impl Default for Database { |
| 4516 | + fn default() -> Self { |
| 4517 | + Self { |
| 4518 | + path: Database::path_default(), |
| 4519 | + migrate: Database::migrate_default(), |
| 4520 | + migrations: Database::migrations_default(), |
| 4521 | + } |
| 4522 | + } |
| 4523 | + } |
| 4524 | diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml |
| 4525 | index 88f48cf..d7a1022 100644 |
| 4526 | --- a/crates/database/Cargo.toml |
| 4527 | +++ b/crates/database/Cargo.toml |
| 4528 | @@ -8,7 +8,8 @@ edition = "2021" |
| 4529 | [dependencies] |
| 4530 | async-trait = { workspace = true } |
| 4531 | futures = { workspace = true } |
| 4532 | - serde = { workspace = true } |
| 4533 | + serde = { workspace = true } |
| 4534 | + serde_json = { workspace = true } |
| 4535 | sqlx = { workspace = true } |
| 4536 | - time = "0.3.41" |
| 4537 | + time = { workspace = true } |
| 4538 | tracing = { workspace = true } |
| 4539 | diff --git a/crates/database/queries/authors_list_project.sql b/crates/database/queries/authors_list_project.sql |
| 4540 | new file mode 100644 |
| 4541 | index 0000000..832e3de |
| 4542 | --- /dev/null |
| 4543 | +++ b/crates/database/queries/authors_list_project.sql |
| 4544 | @@ -0,0 +1,30 @@ |
| 4545 | + WITH RECURSIVE max_git_id AS |
| 4546 | + (SELECT contributions.id AS hash |
| 4547 | + FROM contributions |
| 4548 | + WHERE git_hash = ? |
| 4549 | + AND repo_path = ? |
| 4550 | + ORDER BY id DESC |
| 4551 | + LIMIT 1), |
| 4552 | + total_contributions AS |
| 4553 | + (SELECT COUNT(*) AS contributions |
| 4554 | + FROM contributions |
| 4555 | + WHERE repo_path = ? |
| 4556 | + AND id <= |
| 4557 | + (SELECT hash |
| 4558 | + FROM max_git_id) ) |
| 4559 | + SELECT authors.username, |
| 4560 | + authors.email, |
| 4561 | + COUNT(contributions.id) AS "count: i64", |
| 4562 | + SUM(contributions.lines_added) AS "lines_added: i64", |
| 4563 | + SUM(contributions.lines_removed) AS "lines_removed: i64", |
| 4564 | + ROUND((COUNT(contributions.id)/CAST( |
| 4565 | + (SELECT contributions |
| 4566 | + FROM total_contributions) AS REAL))*100, 2) AS "percentage: f64" |
| 4567 | + FROM contributions |
| 4568 | + LEFT JOIN authors ON (contributions.author_id = authors.id) |
| 4569 | + WHERE repo_path = ? |
| 4570 | + AND contributions.id <= |
| 4571 | + (SELECT hash |
| 4572 | + FROM max_git_id) |
| 4573 | + GROUP BY authors.email |
| 4574 | + ORDER BY "count: i64" DESC |
| 4575 | diff --git a/crates/database/queries/authors_upsert.sql b/crates/database/queries/authors_upsert.sql |
| 4576 | new file mode 100644 |
| 4577 | index 0000000..1c55636 |
| 4578 | --- /dev/null |
| 4579 | +++ b/crates/database/queries/authors_upsert.sql |
| 4580 | @@ -0,0 +1,10 @@ |
| 4581 | + INSERT INTO authors |
| 4582 | + (username, email) |
| 4583 | + VALUES |
| 4584 | + (?, ?) |
| 4585 | + ON CONFLICT |
| 4586 | + DO UPDATE |
| 4587 | + SET |
| 4588 | + username = username, |
| 4589 | + email = email |
| 4590 | + RETURNING id |
| 4591 | diff --git a/crates/database/queries/commits_count.sql b/crates/database/queries/commits_count.sql |
| 4592 | new file mode 100644 |
| 4593 | index 0000000..0088bb8 |
| 4594 | --- /dev/null |
| 4595 | +++ b/crates/database/queries/commits_count.sql |
| 4596 | @@ -0,0 +1,9 @@ |
| 4597 | + SELECT |
| 4598 | + COUNT(id) AS count |
| 4599 | + FROM contributions |
| 4600 | + WHERE |
| 4601 | + repo_path = ? AND |
| 4602 | + id <= ( |
| 4603 | + SELECT id FROM contributions |
| 4604 | + WHERE git_hash = ? AND repo_path = ? |
| 4605 | + ) |
| 4606 | diff --git a/crates/database/queries/contribution_add.sql b/crates/database/queries/contribution_add.sql |
| 4607 | new file mode 100644 |
| 4608 | index 0000000..e1085e3 |
| 4609 | --- /dev/null |
| 4610 | +++ b/crates/database/queries/contribution_add.sql |
| 4611 | @@ -0,0 +1,11 @@ |
| 4612 | + WITH previous(total) AS ( |
| 4613 | + SELECT total FROM contribution_tally |
| 4614 | + WHERE |
| 4615 | + author_id = ? AND repo_path = ? |
| 4616 | + ORDER BY id DESC |
| 4617 | + LIMIT 1 |
| 4618 | + ) |
| 4619 | + INSERT INTO contribution_tally |
| 4620 | + (git_hash, repo_path, author_id, total) |
| 4621 | + VALUES |
| 4622 | + (?, ?, ?, COALESCE((SELECT(total) FROM previous), 0)+1) |
| 4623 | diff --git a/crates/database/queries/contribution_delete.sql b/crates/database/queries/contribution_delete.sql |
| 4624 | new file mode 100644 |
| 4625 | index 0000000..6fdbe5c |
| 4626 | --- /dev/null |
| 4627 | +++ b/crates/database/queries/contribution_delete.sql |
| 4628 | @@ -0,0 +1,3 @@ |
| 4629 | + DELETE FROM contribution_tally |
| 4630 | + WHERE |
| 4631 | + repo_path = ? |
| 4632 | diff --git a/crates/database/queries/contributions_add.sql b/crates/database/queries/contributions_add.sql |
| 4633 | new file mode 100644 |
| 4634 | index 0000000..9883d94 |
| 4635 | --- /dev/null |
| 4636 | +++ b/crates/database/queries/contributions_add.sql |
| 4637 | @@ -0,0 +1,4 @@ |
| 4638 | + INSERT INTO contributions |
| 4639 | + (author_id, git_hash, repo_path, time, lines_added, lines_removed) |
| 4640 | + VALUES |
| 4641 | + (?, ?, ?, ?, ?, ?) |
| 4642 | diff --git a/crates/database/queries/contributions_bucket.sql b/crates/database/queries/contributions_bucket.sql |
| 4643 | new file mode 100644 |
| 4644 | index 0000000..c4e2e55 |
| 4645 | --- /dev/null |
| 4646 | +++ b/crates/database/queries/contributions_bucket.sql |
| 4647 | @@ -0,0 +1,10 @@ |
| 4648 | + SELECT |
| 4649 | + COUNT(id) AS "count!: i64", |
| 4650 | + time, |
| 4651 | + SUM(lines_added) AS "added!: i64", |
| 4652 | + SUM(lines_removed) AS "removed!: i64" |
| 4653 | + FROM contributions WHERE |
| 4654 | + repo_path = ? AND |
| 4655 | + id <= (SELECT id FROM contributions WHERE git_hash = ?) AND |
| 4656 | + time <= ? AND time >= ? |
| 4657 | + GROUP BY strftime(?, time) |
| 4658 | diff --git a/crates/database/queries/contributions_delete.sql b/crates/database/queries/contributions_delete.sql |
| 4659 | new file mode 100644 |
| 4660 | index 0000000..0ee5563 |
| 4661 | --- /dev/null |
| 4662 | +++ b/crates/database/queries/contributions_delete.sql |
| 4663 | @@ -0,0 +1,2 @@ |
| 4664 | + DELETE FROM contributions |
| 4665 | + WHERE repo_path = ? |
| 4666 | diff --git a/crates/database/queries/contributions_list.sql b/crates/database/queries/contributions_list.sql |
| 4667 | new file mode 100644 |
| 4668 | index 0000000..fae5633 |
| 4669 | --- /dev/null |
| 4670 | +++ b/crates/database/queries/contributions_list.sql |
| 4671 | @@ -0,0 +1,42 @@ |
| 4672 | + WITH RECURSIVE |
| 4673 | + tallys AS ( |
| 4674 | + SELECT |
| 4675 | + authors.username AS name, |
| 4676 | + authors.email AS email, |
| 4677 | + MAX(contribution_tally.total) AS total |
| 4678 | + FROM contribution_tally |
| 4679 | + LEFT JOIN authors ON |
| 4680 | + (authors.id = contribution_tally.author_id) |
| 4681 | + WHERE |
| 4682 | + contribution_tally.id < ( |
| 4683 | + SELECT id FROM contributions |
| 4684 | + WHERE |
| 4685 | + repo_path = ? AND git_hash = ? |
| 4686 | + ORDER BY id DESC |
| 4687 | + LIMIT 1 |
| 4688 | + ) AND |
| 4689 | + contribution_tally.repo_path = ? |
| 4690 | + GROUP BY authors.email |
| 4691 | + ORDER BY contribution_tally.total DESC |
| 4692 | + LIMIT 5), |
| 4693 | + raw_commits AS ( |
| 4694 | + SELECT |
| 4695 | + COUNT(*) as total |
| 4696 | + FROM contributions |
| 4697 | + WHERE |
| 4698 | + contributions.id < ( |
| 4699 | + SELECT id FROM contributions |
| 4700 | + WHERE |
| 4701 | + repo_path = ? AND git_hash = ? |
| 4702 | + ORDER BY id DESC |
| 4703 | + LIMIT 1 |
| 4704 | + ) AND |
| 4705 | + contributions.repo_path = ? |
| 4706 | + ) |
| 4707 | + SELECT |
| 4708 | + name, |
| 4709 | + email, |
| 4710 | + ( |
| 4711 | + CAST(tallys.total AS REAL)/(SELECT total FROM raw_commits) |
| 4712 | + ) * 100 AS "percentage: i64" |
| 4713 | + FROM tallys |
| 4714 | diff --git a/crates/database/queries/dags_create.sql b/crates/database/queries/dags_create.sql |
| 4715 | new file mode 100644 |
| 4716 | index 0000000..07bd1bb |
| 4717 | --- /dev/null |
| 4718 | +++ b/crates/database/queries/dags_create.sql |
| 4719 | @@ -0,0 +1,2 @@ |
| 4720 | + INSERT INTO dags (manifest_id, dag_content) |
| 4721 | + VALUES (?, ?) RETURNING id |
| 4722 | diff --git a/crates/database/queries/dags_read.sql b/crates/database/queries/dags_read.sql |
| 4723 | new file mode 100644 |
| 4724 | index 0000000..d2bb6ca |
| 4725 | --- /dev/null |
| 4726 | +++ b/crates/database/queries/dags_read.sql |
| 4727 | @@ -0,0 +1,3 @@ |
| 4728 | + SELECT |
| 4729 | + id, manifest_id, dag_content |
| 4730 | + FROM dags WHERE manifest_id = ? |
| 4731 | diff --git a/crates/database/queries/job_tracking_add.sql b/crates/database/queries/job_tracking_add.sql |
| 4732 | new file mode 100644 |
| 4733 | index 0000000..7e70756 |
| 4734 | --- /dev/null |
| 4735 | +++ b/crates/database/queries/job_tracking_add.sql |
| 4736 | @@ -0,0 +1,4 @@ |
| 4737 | + INSERT INTO job_tracking |
| 4738 | + (repo_path, git_hash, kind, job_id) |
| 4739 | + VALUES |
| 4740 | + (?, ?, ?, ?) |
| 4741 | diff --git a/crates/database/queries/job_tracking_delete.sql b/crates/database/queries/job_tracking_delete.sql |
| 4742 | new file mode 100644 |
| 4743 | index 0000000..3aef33d |
| 4744 | --- /dev/null |
| 4745 | +++ b/crates/database/queries/job_tracking_delete.sql |
| 4746 | @@ -0,0 +1,3 @@ |
| 4747 | + DELETE FROM job_tracking |
| 4748 | + WHERE |
| 4749 | + repo_path = ? |
| 4750 | diff --git a/crates/database/queries/job_tracking_delete_by_repo.sql b/crates/database/queries/job_tracking_delete_by_repo.sql |
| 4751 | new file mode 100644 |
| 4752 | index 0000000..ebd0363 |
| 4753 | --- /dev/null |
| 4754 | +++ b/crates/database/queries/job_tracking_delete_by_repo.sql |
| 4755 | @@ -0,0 +1,3 @@ |
| 4756 | + DELETE FROM jobs |
| 4757 | + WHERE |
| 4758 | + repo_path = ? |
| 4759 | diff --git a/crates/database/queries/job_tracking_read.sql b/crates/database/queries/job_tracking_read.sql |
| 4760 | new file mode 100644 |
| 4761 | index 0000000..823dfc5 |
| 4762 | --- /dev/null |
| 4763 | +++ b/crates/database/queries/job_tracking_read.sql |
| 4764 | @@ -0,0 +1,8 @@ |
| 4765 | + SELECT |
| 4766 | + git_hash AS "git_hash!" |
| 4767 | + FROM job_tracking |
| 4768 | + WHERE |
| 4769 | + repo_path = ? AND |
| 4770 | + kind = ? |
| 4771 | + ORDER BY id DESC |
| 4772 | + LIMIT 1 |
| 4773 | diff --git a/crates/database/queries/jobs_create.sql b/crates/database/queries/jobs_create.sql |
| 4774 | new file mode 100644 |
| 4775 | index 0000000..4a1bea5 |
| 4776 | --- /dev/null |
| 4777 | +++ b/crates/database/queries/jobs_create.sql |
| 4778 | @@ -0,0 +1,5 @@ |
| 4779 | + INSERT INTO jobs |
| 4780 | + (created_at, repo_path, kind) |
| 4781 | + VALUES |
| 4782 | + (?, ?, ?) |
| 4783 | + RETURNING id |
| 4784 | diff --git a/crates/database/queries/jobs_delete.sql b/crates/database/queries/jobs_delete.sql |
| 4785 | new file mode 100644 |
| 4786 | index 0000000..c70ba25 |
| 4787 | --- /dev/null |
| 4788 | +++ b/crates/database/queries/jobs_delete.sql |
| 4789 | @@ -0,0 +1,2 @@ |
| 4790 | + DELETE FROM jobs |
| 4791 | + WHERE jobs.id = ? |
| 4792 | diff --git a/crates/database/queries/jobs_list.sql b/crates/database/queries/jobs_list.sql |
| 4793 | new file mode 100644 |
| 4794 | index 0000000..b1e7f72 |
| 4795 | --- /dev/null |
| 4796 | +++ b/crates/database/queries/jobs_list.sql |
| 4797 | @@ -0,0 +1,15 @@ |
| 4798 | + SELECT |
| 4799 | + jobs.id AS "id!", |
| 4800 | + created_at AS "created_at: OffsetDateTime", |
| 4801 | + jobs.repo_path AS "repo_path!: String", |
| 4802 | + jobs.kind AS "kind!: String", |
| 4803 | + runtime AS "runtime: u32", |
| 4804 | + success AS "success: bool", |
| 4805 | + ( |
| 4806 | + SELECT COUNT(id) FROM job_tracking |
| 4807 | + WHERE job_tracking.job_id = jobs.id |
| 4808 | + ) AS "commits!: i32" |
| 4809 | + FROM jobs |
| 4810 | + WHERE |
| 4811 | + jobs.repo_path = ? OR ? IS NULL |
| 4812 | + ORDER BY DATETIME(created_at) ASC |
| 4813 | diff --git a/crates/database/queries/jobs_update.sql b/crates/database/queries/jobs_update.sql |
| 4814 | new file mode 100644 |
| 4815 | index 0000000..ea7e521 |
| 4816 | --- /dev/null |
| 4817 | +++ b/crates/database/queries/jobs_update.sql |
| 4818 | @@ -0,0 +1,6 @@ |
| 4819 | + UPDATE jobs |
| 4820 | + SET |
| 4821 | + runtime = ?, |
| 4822 | + success = ? |
| 4823 | + WHERE |
| 4824 | + jobs.id = ? |
| 4825 | diff --git a/crates/database/queries/languages_add.sql b/crates/database/queries/languages_add.sql |
| 4826 | new file mode 100644 |
| 4827 | index 0000000..54551b3 |
| 4828 | --- /dev/null |
| 4829 | +++ b/crates/database/queries/languages_add.sql |
| 4830 | @@ -0,0 +1,4 @@ |
| 4831 | + INSERT INTO languages |
| 4832 | + (git_hash, repo_path, language, loc) |
| 4833 | + VALUES |
| 4834 | + (?,?,?,?) |
| 4835 | diff --git a/crates/database/queries/languages_delete.sql b/crates/database/queries/languages_delete.sql |
| 4836 | new file mode 100644 |
| 4837 | index 0000000..06c4349 |
| 4838 | --- /dev/null |
| 4839 | +++ b/crates/database/queries/languages_delete.sql |
| 4840 | @@ -0,0 +1,3 @@ |
| 4841 | + DELETE FROM languages |
| 4842 | + WHERE |
| 4843 | + repo_path = ? |
| 4844 | diff --git a/crates/database/queries/languages_list.sql b/crates/database/queries/languages_list.sql |
| 4845 | new file mode 100644 |
| 4846 | index 0000000..608a719 |
| 4847 | --- /dev/null |
| 4848 | +++ b/crates/database/queries/languages_list.sql |
| 4849 | @@ -0,0 +1,13 @@ |
| 4850 | + SELECT |
| 4851 | + language, |
| 4852 | + loc, |
| 4853 | + ROUND( |
| 4854 | + CAST(loc AS REAL)/CAST( |
| 4855 | + (SELECT SUM(loc) FROM languages |
| 4856 | + WHERE repo_path = ? AND git_hash = ?) AS REAL)*100) |
| 4857 | + AS "percentage: f64" |
| 4858 | + FROM languages |
| 4859 | + WHERE |
| 4860 | + repo_path = ? AND git_hash = ? |
| 4861 | + ORDER BY "percentage: f64" DESC |
| 4862 | + LIMIT 5 |
| 4863 | diff --git a/crates/database/queries/latest_commit.sql b/crates/database/queries/latest_commit.sql |
| 4864 | new file mode 100644 |
| 4865 | index 0000000..bd26eac |
| 4866 | --- /dev/null |
| 4867 | +++ b/crates/database/queries/latest_commit.sql |
| 4868 | @@ -0,0 +1,7 @@ |
| 4869 | + SELECT |
| 4870 | + git_hash |
| 4871 | + FROM contributions |
| 4872 | + WHERE |
| 4873 | + repo_path = ? |
| 4874 | + ORDER BY id DESC |
| 4875 | + LIMIT 1 |
| 4876 | diff --git a/crates/database/queries/mail_deactivate_unused.sql b/crates/database/queries/mail_deactivate_unused.sql |
| 4877 | new file mode 100644 |
| 4878 | index 0000000..730dc92 |
| 4879 | --- /dev/null |
| 4880 | +++ b/crates/database/queries/mail_deactivate_unused.sql |
| 4881 | @@ -0,0 +1 @@ |
| 4882 | + UPDATE lists SET enabled = 0 WHERE address NOT IN (?) |
| 4883 | diff --git a/crates/database/queries/mail_deliver_message.sql b/crates/database/queries/mail_deliver_message.sql |
| 4884 | new file mode 100644 |
| 4885 | index 0000000..6763a82 |
| 4886 | --- /dev/null |
| 4887 | +++ b/crates/database/queries/mail_deliver_message.sql |
| 4888 | @@ -0,0 +1,10 @@ |
| 4889 | + INSERT INTO messages |
| 4890 | + (message_id, list_id, in_reply_to, subject, mail_from, content_body, raw_message) |
| 4891 | + VALUES ( |
| 4892 | + ?, |
| 4893 | + ( SELECT id FROM lists WHERE address = ? LIMIT 1 ), |
| 4894 | + ?, |
| 4895 | + ?, |
| 4896 | + ?, |
| 4897 | + ?, ? |
| 4898 | + ) RETURNING messages.id |
| 4899 | diff --git a/crates/database/queries/mail_has_message.sql b/crates/database/queries/mail_has_message.sql |
| 4900 | new file mode 100644 |
| 4901 | index 0000000..e32ce95 |
| 4902 | --- /dev/null |
| 4903 | +++ b/crates/database/queries/mail_has_message.sql |
| 4904 | @@ -0,0 +1,5 @@ |
| 4905 | + SELECT |
| 4906 | + CASE |
| 4907 | + WHEN (SELECT COUNT(*) FROM messages WHERE message_id = ?) >= 1 THEN TRUE |
| 4908 | + ELSE FALSE |
| 4909 | + END AS "has_message!: bool" |
| 4910 | diff --git a/crates/database/queries/mail_list_create.sql b/crates/database/queries/mail_list_create.sql |
| 4911 | new file mode 100644 |
| 4912 | index 0000000..770b76a |
| 4913 | --- /dev/null |
| 4914 | +++ b/crates/database/queries/mail_list_create.sql |
| 4915 | @@ -0,0 +1,9 @@ |
| 4916 | + INSERT INTO lists |
| 4917 | + (name, address, description, enabled) |
| 4918 | + VALUES |
| 4919 | + (?, ?, ?, ?) |
| 4920 | + ON CONFLICT (address) DO |
| 4921 | + UPDATE SET |
| 4922 | + name = ?, |
| 4923 | + description = ?, |
| 4924 | + enabled = ? |
| 4925 | diff --git a/crates/database/queries/mail_list_outbox.sql b/crates/database/queries/mail_list_outbox.sql |
| 4926 | new file mode 100644 |
| 4927 | index 0000000..8eaa79e |
| 4928 | --- /dev/null |
| 4929 | +++ b/crates/database/queries/mail_list_outbox.sql |
| 4930 | @@ -0,0 +1,13 @@ |
| 4931 | + SELECT |
| 4932 | + outbox.id, |
| 4933 | + messages.message_id AS "message_id!: String", |
| 4934 | + lists.name AS "list_name!: String", |
| 4935 | + participants.address AS "address!: String", |
| 4936 | + messages.raw_message AS raw_message |
| 4937 | + FROM outbox |
| 4938 | + LEFT JOIN participants ON outbox.recipient = participants.address |
| 4939 | + LEFT JOIN messages ON messages.id = outbox.message_id |
| 4940 | + LEFT JOIN lists ON messages.list_id = lists.id |
| 4941 | + WHERE |
| 4942 | + (SELECT COUNT(*) FROM delivery_failures |
| 4943 | + WHERE delivery_failures.outbox_id = outbox.id) < ? |
| 4944 | diff --git a/crates/database/queries/mail_outbox_failed.sql b/crates/database/queries/mail_outbox_failed.sql |
| 4945 | new file mode 100644 |
| 4946 | index 0000000..c7dafcb |
| 4947 | --- /dev/null |
| 4948 | +++ b/crates/database/queries/mail_outbox_failed.sql |
| 4949 | @@ -0,0 +1,3 @@ |
| 4950 | + INSERT INTO delivery_failures |
| 4951 | + (outbox_id, error_kind, message) |
| 4952 | + VALUES (?, ?, ?) |
| 4953 | diff --git a/crates/database/queries/mail_outbox_successful.sql b/crates/database/queries/mail_outbox_successful.sql |
| 4954 | new file mode 100644 |
| 4955 | index 0000000..0b0269c |
| 4956 | --- /dev/null |
| 4957 | +++ b/crates/database/queries/mail_outbox_successful.sql |
| 4958 | @@ -0,0 +1 @@ |
| 4959 | + DELETE FROM outbox WHERE id = ? |
| 4960 | diff --git a/crates/database/queries/mail_read_message.sql b/crates/database/queries/mail_read_message.sql |
| 4961 | new file mode 100644 |
| 4962 | index 0000000..1696cae |
| 4963 | --- /dev/null |
| 4964 | +++ b/crates/database/queries/mail_read_message.sql |
| 4965 | @@ -0,0 +1 @@ |
| 4966 | + SELECT * FROM messages WHERE id = ? |
| 4967 | diff --git a/crates/database/queries/mail_read_thread.sql b/crates/database/queries/mail_read_thread.sql |
| 4968 | new file mode 100644 |
| 4969 | index 0000000..09342d0 |
| 4970 | --- /dev/null |
| 4971 | +++ b/crates/database/queries/mail_read_thread.sql |
| 4972 | @@ -0,0 +1,18 @@ |
| 4973 | + WITH RECURSIVE tree AS ( |
| 4974 | + SELECT messages.*, 0 AS depth FROM messages |
| 4975 | + WHERE messages.message_id = ? |
| 4976 | + UNION ALL |
| 4977 | + SELECT other.*, depth + 1 FROM messages other |
| 4978 | + JOIN tree ON other.in_reply_to = tree.message_id |
| 4979 | + ) |
| 4980 | + SELECT |
| 4981 | + message_id, |
| 4982 | + in_reply_to, |
| 4983 | + subject, |
| 4984 | + (SELECT address FROM participants WHERE participants.id = tree.mail_from LIMIT 1) |
| 4985 | + mail_from, |
| 4986 | + raw_message, |
| 4987 | + content_body, |
| 4988 | + reply_count, |
| 4989 | + depth AS "depth!: i64" |
| 4990 | + FROM tree ORDER BY depth |
| 4991 | diff --git a/crates/database/queries/mail_read_threads.sql b/crates/database/queries/mail_read_threads.sql |
| 4992 | new file mode 100644 |
| 4993 | index 0000000..d2e3b4a |
| 4994 | --- /dev/null |
| 4995 | +++ b/crates/database/queries/mail_read_threads.sql |
| 4996 | @@ -0,0 +1,9 @@ |
| 4997 | + SELECT |
| 4998 | + messages.message_id, |
| 4999 | + messages.subject, |
| 5000 | + messages.reply_count, |
| 5001 | + participants.address AS "mail_from!: String" |
| 5002 | + FROM messages |
| 5003 | + LEFT JOIN lists ON lists.id = messages.id |
| 5004 | + LEFT JOIN participants ON participants.id = messages.mail_from |
| 5005 | + WHERE lists.name = ? AND messages.in_reply_to IS NULL |
| 5006 | diff --git a/crates/database/queries/mail_thread_count.sql b/crates/database/queries/mail_thread_count.sql |
| 5007 | new file mode 100644 |
| 5008 | index 0000000..5dc619a |
| 5009 | --- /dev/null |
| 5010 | +++ b/crates/database/queries/mail_thread_count.sql |
| 5011 | @@ -0,0 +1,4 @@ |
| 5012 | + SELECT COUNT(*) AS "count: i64" FROM messages |
| 5013 | + WHERE |
| 5014 | + list_id = (SELECT list_id FROM lists WHERE list_id = ?) AND |
| 5015 | + in_reply_to IS NULL |
| 5016 | diff --git a/crates/database/queries/mail_thread_summary.sql b/crates/database/queries/mail_thread_summary.sql |
| 5017 | new file mode 100644 |
| 5018 | index 0000000..c76aa55 |
| 5019 | --- /dev/null |
| 5020 | +++ b/crates/database/queries/mail_thread_summary.sql |
| 5021 | @@ -0,0 +1,3 @@ |
| 5022 | + SELECT messages.* FROM messages |
| 5023 | + LEFT JOIN lists ON lists.id = messages.id |
| 5024 | + WHERE lists.name = ? AND messages.reply_to IS NULL |
| 5025 | diff --git a/crates/database/queries/mail_upsert_participant.sql b/crates/database/queries/mail_upsert_participant.sql |
| 5026 | new file mode 100644 |
| 5027 | index 0000000..67b0973 |
| 5028 | --- /dev/null |
| 5029 | +++ b/crates/database/queries/mail_upsert_participant.sql |
| 5030 | @@ -0,0 +1,6 @@ |
| 5031 | + INSERT INTO participants |
| 5032 | + (address, authorized_sender) |
| 5033 | + VALUES (?, ?) |
| 5034 | + ON CONFLICT DO NOTHING; |
| 5035 | + |
| 5036 | + SELECT id FROM participants WHERE address = ? |
| 5037 | diff --git a/crates/database/queries/mail_upsert_subscription.sql b/crates/database/queries/mail_upsert_subscription.sql |
| 5038 | new file mode 100644 |
| 5039 | index 0000000..78cd886 |
| 5040 | --- /dev/null |
| 5041 | +++ b/crates/database/queries/mail_upsert_subscription.sql |
| 5042 | @@ -0,0 +1,6 @@ |
| 5043 | + INSERT INTO subscriptions |
| 5044 | + (participant_id, list_id) |
| 5045 | + VALUES ( |
| 5046 | + (SELECT id FROM participants WHERE address = ? LIMIT 1), |
| 5047 | + (SELECT id FROM lists WHERE address = ? LIMIT 1) |
| 5048 | + ) ON CONFLICT DO NOTHING; |
| 5049 | diff --git a/crates/database/queries/manifests_concise.sql b/crates/database/queries/manifests_concise.sql |
| 5050 | new file mode 100644 |
| 5051 | index 0000000..ff04dcf |
| 5052 | --- /dev/null |
| 5053 | +++ b/crates/database/queries/manifests_concise.sql |
| 5054 | @@ -0,0 +1,25 @@ |
| 5055 | + WITH params AS ( |
| 5056 | + SELECT |
| 5057 | + ? AS collection, |
| 5058 | + ? AS name, |
| 5059 | + ? AS manifest_id, |
| 5060 | + ? AS git_hash |
| 5061 | + ) |
| 5062 | + SELECT |
| 5063 | + steps.id AS step_id, |
| 5064 | + steps.name AS step_name, |
| 5065 | + workflows.id AS workflow_id, |
| 5066 | + workflows.name AS workflow_name, |
| 5067 | + manifests.id AS manifest_id, |
| 5068 | + steps.exit_code, |
| 5069 | + steps.finished_at |
| 5070 | + FROM steps |
| 5071 | + LEFT JOIN workflows ON workflows.id = steps.workflow_id |
| 5072 | + LEFT JOIN manifests ON manifests.id = workflows.manifest_id |
| 5073 | + WHERE |
| 5074 | + (manifests.collection IS (SELECT collection FROM params) OR (SELECT collection FROM params) IS NULL) |
| 5075 | + AND (manifests.name IS (SELECT name FROM params) OR (SELECT name FROM params) IS NULL) |
| 5076 | + AND (manifests.id IS (SELECT manifest_id FROM params) OR (SELECT manifest_id FROM params) IS NULL) |
| 5077 | + AND (manifests.git_hash IS (SELECT git_hash FROM params) OR (SELECT git_hash FROM params) IS NULL) |
| 5078 | + LIMIT ? |
| 5079 | + OFFSET ? |
| 5080 | diff --git a/crates/database/queries/manifests_create.sql b/crates/database/queries/manifests_create.sql |
| 5081 | new file mode 100644 |
| 5082 | index 0000000..e826336 |
| 5083 | --- /dev/null |
| 5084 | +++ b/crates/database/queries/manifests_create.sql |
| 5085 | @@ -0,0 +1,2 @@ |
| 5086 | + INSERT INTO manifests (collection, name, git_hash) |
| 5087 | + VALUES (?, ?, ?) RETURNING id |
| 5088 | diff --git a/crates/database/queries/manifests_list.sql b/crates/database/queries/manifests_list.sql |
| 5089 | new file mode 100644 |
| 5090 | index 0000000..55ea5b1 |
| 5091 | --- /dev/null |
| 5092 | +++ b/crates/database/queries/manifests_list.sql |
| 5093 | @@ -0,0 +1,14 @@ |
| 5094 | + SELECT id, |
| 5095 | + collection, |
| 5096 | + name, |
| 5097 | + git_hash, |
| 5098 | + created_at, |
| 5099 | + started_at, |
| 5100 | + duration |
| 5101 | + FROM manifests |
| 5102 | + WHERE |
| 5103 | + collection = ? OR collection IS NULL |
| 5104 | + AND name = ? OR name IS NULL |
| 5105 | + AND git_hash = ? OR git_hash IS NULL |
| 5106 | + LIMIT ? |
| 5107 | + OFFSET ? |
| 5108 | diff --git a/crates/database/queries/manifests_read.sql b/crates/database/queries/manifests_read.sql |
| 5109 | new file mode 100644 |
| 5110 | index 0000000..e74b333 |
| 5111 | --- /dev/null |
| 5112 | +++ b/crates/database/queries/manifests_read.sql |
| 5113 | @@ -0,0 +1,18 @@ |
| 5114 | + WITH params AS ( |
| 5115 | + SELECT |
| 5116 | + ? AS _manifest_id, |
| 5117 | + ? AS _collection, |
| 5118 | + ? AS _name |
| 5119 | + ) |
| 5120 | + SELECT manifests.id, |
| 5121 | + name, |
| 5122 | + collection, |
| 5123 | + git_hash, |
| 5124 | + created_at, |
| 5125 | + started_at, |
| 5126 | + finished_at |
| 5127 | + FROM manifests |
| 5128 | + WHERE |
| 5129 | + manifests.id = (SELECT _manifest_id FROM params) |
| 5130 | + AND (manifests.collection IS (SELECT _collection FROM params) OR (SELECT _collection FROM params) IS NULL) |
| 5131 | + AND (manifests.name IS (SELECT _name FROM params) OR (SELECT _name FROM params) IS NULL) |
| 5132 | diff --git a/crates/database/queries/manifests_update_finish.sql b/crates/database/queries/manifests_update_finish.sql |
| 5133 | new file mode 100644 |
| 5134 | index 0000000..d0a6513 |
| 5135 | --- /dev/null |
| 5136 | +++ b/crates/database/queries/manifests_update_finish.sql |
| 5137 | @@ -0,0 +1,4 @@ |
| 5138 | + UPDATE manifests |
| 5139 | + SET |
| 5140 | + finished_at = UNIXEPOCH() |
| 5141 | + WHERE id = ? |
| 5142 | diff --git a/crates/database/queries/manifests_update_start.sql b/crates/database/queries/manifests_update_start.sql |
| 5143 | new file mode 100644 |
| 5144 | index 0000000..fc85a4d |
| 5145 | --- /dev/null |
| 5146 | +++ b/crates/database/queries/manifests_update_start.sql |
| 5147 | @@ -0,0 +1,3 @@ |
| 5148 | + UPDATE manifests |
| 5149 | + SET started_at = UNIXEPOCH() |
| 5150 | + WHERE id = ? |
| 5151 | diff --git a/crates/database/queries/samples_create.sql b/crates/database/queries/samples_create.sql |
| 5152 | new file mode 100644 |
| 5153 | index 0000000..7fc297f |
| 5154 | --- /dev/null |
| 5155 | +++ b/crates/database/queries/samples_create.sql |
| 5156 | @@ -0,0 +1,18 @@ |
| 5157 | + INSERT INTO samples |
| 5158 | + ( |
| 5159 | + manifest_id, |
| 5160 | + load_1m, |
| 5161 | + load_5m, |
| 5162 | + load_15m, |
| 5163 | + disk_total_bytes, |
| 5164 | + disk_free_bytes, |
| 5165 | + net_sent_bytes, |
| 5166 | + net_received_bytes, |
| 5167 | + net_sent_packets, |
| 5168 | + net_received_packets, |
| 5169 | + mem_total_bytes, |
| 5170 | + mem_free_bytes, |
| 5171 | + mem_available_bytes |
| 5172 | + ) |
| 5173 | + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) |
| 5174 | + RETURNING id |
| 5175 | diff --git a/crates/database/queries/samples_read.sql b/crates/database/queries/samples_read.sql |
| 5176 | new file mode 100644 |
| 5177 | index 0000000..6842939 |
| 5178 | --- /dev/null |
| 5179 | +++ b/crates/database/queries/samples_read.sql |
| 5180 | @@ -0,0 +1,15 @@ |
| 5181 | + SELECT id, |
| 5182 | + load_1m, |
| 5183 | + load_5m, |
| 5184 | + load_15m, |
| 5185 | + disk_total_bytes, |
| 5186 | + disk_free_bytes, |
| 5187 | + net_sent_bytes, |
| 5188 | + net_received_bytes, |
| 5189 | + net_sent_packets, |
| 5190 | + net_received_packets, |
| 5191 | + mem_total_bytes, |
| 5192 | + mem_free_bytes, |
| 5193 | + mem_available_bytes |
| 5194 | + FROM samples |
| 5195 | + WHERE manifest_id = ? |
| 5196 | diff --git a/crates/database/queries/steps_create.sql b/crates/database/queries/steps_create.sql |
| 5197 | new file mode 100644 |
| 5198 | index 0000000..ababf23 |
| 5199 | --- /dev/null |
| 5200 | +++ b/crates/database/queries/steps_create.sql |
| 5201 | @@ -0,0 +1,2 @@ |
| 5202 | + INSERT INTO steps (workflow_id, name, input, shell, environment_json) |
| 5203 | + VALUES (?, ?, ?, ?, json_array(?)) RETURNING id |
| 5204 | diff --git a/crates/database/queries/steps_list.sql b/crates/database/queries/steps_list.sql |
| 5205 | new file mode 100644 |
| 5206 | index 0000000..4ab824b |
| 5207 | --- /dev/null |
| 5208 | +++ b/crates/database/queries/steps_list.sql |
| 5209 | @@ -0,0 +1,11 @@ |
| 5210 | + SELECT id, |
| 5211 | + name, |
| 5212 | + shell, |
| 5213 | + input, |
| 5214 | + stdout, |
| 5215 | + stderr, |
| 5216 | + started_at, |
| 5217 | + finished_at, |
| 5218 | + exit_code |
| 5219 | + FROM steps |
| 5220 | + WHERE workflow_id = ? |
| 5221 | diff --git a/crates/database/queries/steps_read.sql b/crates/database/queries/steps_read.sql |
| 5222 | new file mode 100644 |
| 5223 | index 0000000..2b5c4e3 |
| 5224 | --- /dev/null |
| 5225 | +++ b/crates/database/queries/steps_read.sql |
| 5226 | @@ -0,0 +1,11 @@ |
| 5227 | + SELECT |
| 5228 | + id, |
| 5229 | + name, |
| 5230 | + shell, |
| 5231 | + input, |
| 5232 | + stdout, |
| 5233 | + stderr, |
| 5234 | + started_at, |
| 5235 | + finished_at, |
| 5236 | + exit_code |
| 5237 | + FROM steps WHERE id = ? |
| 5238 | diff --git a/crates/database/queries/steps_read_env.sql b/crates/database/queries/steps_read_env.sql |
| 5239 | new file mode 100644 |
| 5240 | index 0000000..2312f2b |
| 5241 | --- /dev/null |
| 5242 | +++ b/crates/database/queries/steps_read_env.sql |
| 5243 | @@ -0,0 +1 @@ |
| 5244 | + SELECT name, value FROM steps_env_vars WHERE step_id = ? |
| 5245 | diff --git a/crates/database/queries/steps_update_finish.sql b/crates/database/queries/steps_update_finish.sql |
| 5246 | new file mode 100644 |
| 5247 | index 0000000..d80c0e3 |
| 5248 | --- /dev/null |
| 5249 | +++ b/crates/database/queries/steps_update_finish.sql |
| 5250 | @@ -0,0 +1,8 @@ |
| 5251 | + UPDATE steps |
| 5252 | + SET |
| 5253 | + finished_at = UNIXEPOCH(), |
| 5254 | + stdout = ?, |
| 5255 | + stderr = ?, |
| 5256 | + exit_code = ? |
| 5257 | + WHERE |
| 5258 | + id = ? |
| 5259 | diff --git a/crates/database/queries/steps_update_start.sql b/crates/database/queries/steps_update_start.sql |
| 5260 | new file mode 100644 |
| 5261 | index 0000000..387654b |
| 5262 | --- /dev/null |
| 5263 | +++ b/crates/database/queries/steps_update_start.sql |
| 5264 | @@ -0,0 +1,5 @@ |
| 5265 | + UPDATE steps |
| 5266 | + SET |
| 5267 | + started_at = UNIXEPOCH() |
| 5268 | + WHERE |
| 5269 | + id = ? |
| 5270 | diff --git a/crates/database/queries/workflows_create.sql b/crates/database/queries/workflows_create.sql |
| 5271 | new file mode 100644 |
| 5272 | index 0000000..0063b5f |
| 5273 | --- /dev/null |
| 5274 | +++ b/crates/database/queries/workflows_create.sql |
| 5275 | @@ -0,0 +1,2 @@ |
| 5276 | + INSERT INTO workflows (manifest_id, name) |
| 5277 | + VALUES (?, ?) RETURNING id |
| 5278 | diff --git a/crates/database/queries/workflows_list.sql b/crates/database/queries/workflows_list.sql |
| 5279 | new file mode 100644 |
| 5280 | index 0000000..7ba11c6 |
| 5281 | --- /dev/null |
| 5282 | +++ b/crates/database/queries/workflows_list.sql |
| 5283 | @@ -0,0 +1,6 @@ |
| 5284 | + SELECT id, |
| 5285 | + name, |
| 5286 | + started_at, |
| 5287 | + finished_at |
| 5288 | + FROM workflows |
| 5289 | + WHERE manifest_id = ? |
| 5290 | diff --git a/crates/database/queries/workflows_read.sql b/crates/database/queries/workflows_read.sql |
| 5291 | new file mode 100644 |
| 5292 | index 0000000..a772b4b |
| 5293 | --- /dev/null |
| 5294 | +++ b/crates/database/queries/workflows_read.sql |
| 5295 | @@ -0,0 +1 @@ |
| 5296 | + SELECT id, name, started_at, finished_at FROM workflows WHERE id = ? |
| 5297 | diff --git a/crates/database/queries/workflows_update_finish.sql b/crates/database/queries/workflows_update_finish.sql |
| 5298 | new file mode 100644 |
| 5299 | index 0000000..769a8be |
| 5300 | --- /dev/null |
| 5301 | +++ b/crates/database/queries/workflows_update_finish.sql |
| 5302 | @@ -0,0 +1,5 @@ |
| 5303 | + UPDATE workflows |
| 5304 | + SET |
| 5305 | + finished_at = UNIXEPOCH() |
| 5306 | + WHERE |
| 5307 | + id = ? |
| 5308 | diff --git a/crates/database/queries/workflows_update_start.sql b/crates/database/queries/workflows_update_start.sql |
| 5309 | new file mode 100644 |
| 5310 | index 0000000..11be057 |
| 5311 | --- /dev/null |
| 5312 | +++ b/crates/database/queries/workflows_update_start.sql |
| 5313 | @@ -0,0 +1,5 @@ |
| 5314 | + UPDATE workflows |
| 5315 | + SET |
| 5316 | + started_at = UNIXEPOCH() |
| 5317 | + WHERE |
| 5318 | + id = ? |
| 5319 | diff --git a/crates/database/src/build.rs b/crates/database/src/build.rs |
| 5320 | new file mode 100644 |
| 5321 | index 0000000..8ac8030 |
| 5322 | --- /dev/null |
| 5323 | +++ b/crates/database/src/build.rs |
| 5324 | @@ -0,0 +1,562 @@ |
| 5325 | + use std::collections::HashMap; |
| 5326 | + |
| 5327 | + use async_trait::async_trait; |
| 5328 | + use serde::{Deserialize, Serialize}; |
| 5329 | + |
| 5330 | + use crate::{Error, Tx, Wrapper as Database}; |
| 5331 | + |
| 5332 | + pub type ConciseStep = (i64, String, Option<bool>); |
| 5333 | + pub type ConciseWorkflow = (i64, String, Vec<ConciseStep>); |
| 5334 | + |
| 5335 | + /// An environment variable |
| 5336 | + pub struct Env((String, Option<String>)); |
| 5337 | + /// Environment Variables |
| 5338 | + pub struct Environment(Vec<Env>); |
| 5339 | + |
| 5340 | + impl From<Environment> for HashMap<String, Option<String>> { |
| 5341 | + fn from(val: Environment) -> Self { |
| 5342 | + let values: Vec<(String, Option<String>)> = val |
| 5343 | + .0 |
| 5344 | + .iter() |
| 5345 | + .map(|env| (env.0 .0.clone(), env.0 .1.clone())) |
| 5346 | + .collect(); |
| 5347 | + HashMap::from_iter(values) |
| 5348 | + } |
| 5349 | + } |
| 5350 | + |
| 5351 | + // Manifest item with all of it's inner state for quick display |
| 5352 | + #[derive(Clone, Serialize, Deserialize)] |
| 5353 | + pub struct ManifestItem { |
| 5354 | + pub manifest: Manifest, |
| 5355 | + // Present if the manifest job is completed, true if all items within were successful |
| 5356 | + pub success: Option<bool>, |
| 5357 | + // Concise representation of workflows and steps for display in the UI |
| 5358 | + pub workflows: Vec<ConciseWorkflow>, |
| 5359 | + } |
| 5360 | + |
| 5361 | + #[derive(Clone, Serialize, Deserialize)] |
| 5362 | + // everything needed to populate the build status page |
| 5363 | + pub struct ManifestView { |
| 5364 | + pub manifest: Manifest, |
| 5365 | + // pub samples: Vec<Sample>, |
| 5366 | + pub workflows: Vec<(Workflow, Vec<Step>)>, |
| 5367 | + pub dag: Dag, |
| 5368 | + } |
| 5369 | + |
| 5370 | + #[derive(Clone, Default, Serialize, Deserialize)] |
| 5371 | + pub struct Sample { |
| 5372 | + pub id: i64, |
| 5373 | + pub load_1m: Option<i64>, |
| 5374 | + pub load_5m: Option<i64>, |
| 5375 | + pub load_15m: Option<i64>, |
| 5376 | + pub disk_total_bytes: Option<i64>, |
| 5377 | + pub disk_free_bytes: Option<i64>, |
| 5378 | + pub net_sent_bytes: Option<i64>, |
| 5379 | + pub net_received_bytes: Option<i64>, |
| 5380 | + pub net_sent_packets: Option<i64>, |
| 5381 | + pub net_received_packets: Option<i64>, |
| 5382 | + pub mem_total_bytes: Option<i64>, |
| 5383 | + pub mem_free_bytes: Option<i64>, |
| 5384 | + pub mem_available_bytes: Option<i64>, |
| 5385 | + } |
| 5386 | + |
| 5387 | + #[derive(Clone, Serialize, Deserialize)] |
| 5388 | + pub struct Manifest { |
| 5389 | + pub id: i64, |
| 5390 | + pub collection: String, |
| 5391 | + pub name: String, |
| 5392 | + pub git_hash: String, |
| 5393 | + pub created_at: i64, |
| 5394 | + pub started_at: Option<i64>, |
| 5395 | + pub finished_at: Option<i64>, |
| 5396 | + // pub dot_content: String, |
| 5397 | + } |
| 5398 | + |
| 5399 | + // TODO |
| 5400 | + // |
| 5401 | + #[derive(Debug, Clone, Serialize, Deserialize)] |
| 5402 | + pub struct Workflow { |
| 5403 | + pub id: i64, |
| 5404 | + pub name: String, |
| 5405 | + pub started_at: Option<i64>, |
| 5406 | + pub finished_at: Option<i64>, |
| 5407 | + } |
| 5408 | + |
| 5409 | + pub struct WorkflowView { |
| 5410 | + pub workflow: Workflow, |
| 5411 | + pub steps: Vec<Step>, |
| 5412 | + } |
| 5413 | + |
| 5414 | + #[derive(Debug, Clone, Serialize, Deserialize)] |
| 5415 | + pub struct Step { |
| 5416 | + pub id: i64, |
| 5417 | + pub name: String, |
| 5418 | + pub shell: String, |
| 5419 | + pub input: String, |
| 5420 | + pub stdout: Option<String>, |
| 5421 | + pub stderr: Option<String>, |
| 5422 | + pub started_at: Option<i64>, |
| 5423 | + pub finished_at: Option<i64>, |
| 5424 | + pub exit_code: Option<i64>, |
| 5425 | + } |
| 5426 | + |
| 5427 | + #[derive(Clone, Serialize, Deserialize)] |
| 5428 | + pub struct Dag { |
| 5429 | + pub id: i64, |
| 5430 | + pub manifest_id: i64, |
| 5431 | + pub dag_content: String, |
| 5432 | + } |
| 5433 | + |
| 5434 | + /// Used to list manifests from the UI |
| 5435 | + #[derive(Clone)] |
| 5436 | + pub enum Identifier { |
| 5437 | + GitSHA(String), |
| 5438 | + Id(i64), |
| 5439 | + } |
| 5440 | + |
| 5441 | + #[async_trait] |
| 5442 | + pub trait BuildTx { |
| 5443 | + async fn create_manifest( |
| 5444 | + &mut self, |
| 5445 | + collection: &str, |
| 5446 | + name: &str, |
| 5447 | + git_hash: &str, |
| 5448 | + ) -> Result<i64, Error>; |
| 5449 | + async fn create_workflow(&mut self, manifest_id: i64, name: &str) -> Result<i64, Error>; |
| 5450 | + async fn create_step( |
| 5451 | + &mut self, |
| 5452 | + job_id: i64, |
| 5453 | + name: &str, |
| 5454 | + input: &str, |
| 5455 | + shell: &str, |
| 5456 | + environment: HashMap<String, String>, |
| 5457 | + ) -> Result<i64, Error>; |
| 5458 | + async fn create_dag(&mut self, manifest_id: i64, dag_content: &str) -> Result<i64, Error>; |
| 5459 | + } |
| 5460 | + |
| 5461 | + #[async_trait] |
| 5462 | + impl BuildTx for Tx { |
| 5463 | + // manifests |
| 5464 | + async fn create_manifest( |
| 5465 | + &mut self, |
| 5466 | + collection: &str, |
| 5467 | + name: &str, |
| 5468 | + git_hash: &str, |
| 5469 | + ) -> Result<i64, Error> { |
| 5470 | + let ret = sqlx::query_file!("queries/manifests_create.sql", collection, name, git_hash) |
| 5471 | + .fetch_one(&mut *self.inner) |
| 5472 | + .await?; |
| 5473 | + Ok(ret.id) |
| 5474 | + } |
| 5475 | + |
| 5476 | + async fn create_workflow(&mut self, manifest_id: i64, name: &str) -> Result<i64, Error> { |
| 5477 | + let ret = sqlx::query_file!("queries/workflows_create.sql", manifest_id, name) |
| 5478 | + .fetch_one(&mut *self.inner) |
| 5479 | + .await?; |
| 5480 | + Ok(ret.id) |
| 5481 | + } |
| 5482 | + |
| 5483 | + async fn create_step( |
| 5484 | + &mut self, |
| 5485 | + workflow_id: i64, |
| 5486 | + name: &str, |
| 5487 | + input: &str, |
| 5488 | + shell: &str, |
| 5489 | + environment: HashMap<String, String>, |
| 5490 | + ) -> Result<i64, Error> { |
| 5491 | + let environment_json = serde_json::ser::to_string(&environment).unwrap(); |
| 5492 | + let ret = sqlx::query_file!( |
| 5493 | + "queries/steps_create.sql", |
| 5494 | + workflow_id, |
| 5495 | + name, |
| 5496 | + input, |
| 5497 | + shell, |
| 5498 | + environment_json |
| 5499 | + ) |
| 5500 | + .fetch_one(&mut *self.inner) |
| 5501 | + .await?; |
| 5502 | + Ok(ret.id) |
| 5503 | + } |
| 5504 | + |
| 5505 | + async fn create_dag(&mut self, manifest_id: i64, dag_content: &str) -> Result<i64, Error> { |
| 5506 | + let ret = sqlx::query_file!("queries/dags_create.sql", manifest_id, dag_content) |
| 5507 | + .fetch_one(&mut *self.inner) |
| 5508 | + .await?; |
| 5509 | + Ok(ret.id) |
| 5510 | + } |
| 5511 | + } |
| 5512 | + |
| 5513 | + #[async_trait] |
| 5514 | + pub trait BuildExt { |
| 5515 | + // manifests |
| 5516 | + async fn create_manifest( |
| 5517 | + &self, |
| 5518 | + collection: &str, |
| 5519 | + name: &str, |
| 5520 | + git_hash: &str, |
| 5521 | + ) -> Result<i64, Error>; |
| 5522 | + async fn update_manifest_start(&self, manifest_id: i64) -> Result<(), Error>; |
| 5523 | + async fn update_manifest_finish(&self, manifest_id: i64) -> Result<(), Error>; |
| 5524 | + async fn list_manifest( |
| 5525 | + &self, |
| 5526 | + collection: Option<&str>, |
| 5527 | + name: Option<&str>, |
| 5528 | + filter: Option<&Identifier>, |
| 5529 | + limit: i64, |
| 5530 | + offset: i64, |
| 5531 | + ) -> Result<Vec<ManifestItem>, Error>; |
| 5532 | + async fn read_manifest( |
| 5533 | + &self, |
| 5534 | + collection: &str, |
| 5535 | + name: &str, |
| 5536 | + manifest_id: i64, |
| 5537 | + ) -> Result<ManifestView, Error>; |
| 5538 | + |
| 5539 | + // workflows |
| 5540 | + async fn create_workflow(&self, manifest_id: i64, name: &str) -> Result<i64, Error>; |
| 5541 | + async fn update_workflow_start(&self, workflow_id: i64) -> Result<(), Error>; |
| 5542 | + async fn update_workflow_finish(&self, workflow_id: i64) -> Result<(), Error>; |
| 5543 | + async fn read_workflow(&self, workflow_id: i64) -> Result<Workflow, Error>; |
| 5544 | + async fn read_workflow_view(&self, workflow_id: i64) -> Result<WorkflowView, Error>; |
| 5545 | + // steps |
| 5546 | + async fn create_step( |
| 5547 | + &self, |
| 5548 | + job_id: i64, |
| 5549 | + name: &str, |
| 5550 | + input: &str, |
| 5551 | + shell: &str, |
| 5552 | + environment: HashMap<String, String>, |
| 5553 | + ) -> Result<i64, Error>; |
| 5554 | + async fn read_step(&self, step_id: i64) -> Result<Step, Error>; |
| 5555 | + async fn read_step_env(&self, step_id: i64) -> Result<Environment, Error>; |
| 5556 | + async fn update_step_start(&self, step_id: i64) -> Result<(), Error>; |
| 5557 | + async fn update_step_finish( |
| 5558 | + &self, |
| 5559 | + step_id: i64, |
| 5560 | + stdout: &str, |
| 5561 | + stderr: &str, |
| 5562 | + exit_code: i8, |
| 5563 | + ) -> Result<(), Error>; |
| 5564 | + |
| 5565 | + // misc |
| 5566 | + async fn create_sample(&self, manifest_id: i64, sample: Sample) -> Result<i64, Error>; |
| 5567 | + |
| 5568 | + async fn read_dag(&self, manifest_id: i64) -> Result<Dag, Error>; |
| 5569 | + } |
| 5570 | + |
| 5571 | + #[async_trait] |
| 5572 | + impl BuildExt for Database { |
| 5573 | + // manifests |
| 5574 | + async fn create_manifest( |
| 5575 | + &self, |
| 5576 | + collection: &str, |
| 5577 | + name: &str, |
| 5578 | + git_hash: &str, |
| 5579 | + ) -> Result<i64, Error> { |
| 5580 | + let ret = sqlx::query_file!("queries/manifests_create.sql", collection, name, git_hash) |
| 5581 | + .fetch_one(&self.pool) |
| 5582 | + .await?; |
| 5583 | + Ok(ret.id) |
| 5584 | + } |
| 5585 | + |
| 5586 | + async fn update_manifest_start(&self, manifest_id: i64) -> Result<(), Error> { |
| 5587 | + sqlx::query_file!("queries/manifests_update_start.sql", manifest_id,) |
| 5588 | + .execute(&self.pool) |
| 5589 | + .await?; |
| 5590 | + Ok(()) |
| 5591 | + } |
| 5592 | + |
| 5593 | + async fn update_manifest_finish(&self, manifest_id: i64) -> Result<(), Error> { |
| 5594 | + sqlx::query_file!("queries/manifests_update_finish.sql", manifest_id) |
| 5595 | + .execute(&self.pool) |
| 5596 | + .await?; |
| 5597 | + Ok(()) |
| 5598 | + } |
| 5599 | + |
| 5600 | + async fn list_manifest( |
| 5601 | + &self, |
| 5602 | + collection: Option<&str>, |
| 5603 | + name: Option<&str>, |
| 5604 | + filter: Option<&Identifier>, |
| 5605 | + limit: i64, |
| 5606 | + offset: i64, |
| 5607 | + ) -> Result<Vec<ManifestItem>, Error> { |
| 5608 | + let (manifest_id, git_hash) = match filter { |
| 5609 | + Some(Identifier::GitSHA(gitsha)) => (None, Some(gitsha.clone())), |
| 5610 | + Some(Identifier::Id(manifest_id)) => (Some(manifest_id.to_string()), None), |
| 5611 | + None => (None, None), |
| 5612 | + }; |
| 5613 | + let records = sqlx::query_file!( |
| 5614 | + "queries/manifests_concise.sql", |
| 5615 | + collection, |
| 5616 | + name, |
| 5617 | + manifest_id, |
| 5618 | + git_hash, |
| 5619 | + limit, |
| 5620 | + offset |
| 5621 | + ) |
| 5622 | + .fetch_all(&self.pool) |
| 5623 | + .await?; |
| 5624 | + let invocations: HashMap<i64, HashMap<i64, (String, Vec<ConciseStep>)>> = |
| 5625 | + records.iter().fold(HashMap::new(), |mut mapped, record| { |
| 5626 | + match mapped.get_mut(&record.manifest_id) { |
| 5627 | + Some(workflow) => match workflow.get_mut(&record.workflow_id) { |
| 5628 | + Some(steps) => steps.1.push(( |
| 5629 | + record.step_id, |
| 5630 | + record.step_name.clone(), |
| 5631 | + record.exit_code.map(|code| code == 0), |
| 5632 | + )), |
| 5633 | + None => { |
| 5634 | + workflow.insert( |
| 5635 | + record.workflow_id, |
| 5636 | + ( |
| 5637 | + record.workflow_name.clone().unwrap_or_default(), |
| 5638 | + vec![( |
| 5639 | + record.step_id, |
| 5640 | + record.step_name.clone(), |
| 5641 | + record.exit_code.map(|code| code == 0), |
| 5642 | + )], |
| 5643 | + ), |
| 5644 | + ); |
| 5645 | + } |
| 5646 | + }, |
| 5647 | + None => { |
| 5648 | + let workflow: HashMap<i64, (String, Vec<ConciseStep>)> = HashMap::from([( |
| 5649 | + record.workflow_id, |
| 5650 | + ( |
| 5651 | + record.workflow_name.clone().unwrap_or_default(), |
| 5652 | + vec![( |
| 5653 | + record.step_id, |
| 5654 | + record.step_name.clone(), |
| 5655 | + record.exit_code.map(|code| code == 0), |
| 5656 | + )], |
| 5657 | + ), |
| 5658 | + )]); |
| 5659 | + mapped.insert(record.manifest_id, workflow); |
| 5660 | + } |
| 5661 | + }; |
| 5662 | + mapped |
| 5663 | + }); |
| 5664 | + |
| 5665 | + let mut as_ordered_vec: Vec<(i64, Vec<ConciseWorkflow>)> = |
| 5666 | + invocations |
| 5667 | + .iter() |
| 5668 | + .fold(Vec::new(), |mut accm, (manifest_id, workflows)| { |
| 5669 | + let mut workflows: Vec<ConciseWorkflow> = workflows.iter().fold( |
| 5670 | + Vec::new(), |
| 5671 | + |mut wf_accm, (workflow_id, (workflow_name, steps))| { |
| 5672 | + wf_accm.push((*workflow_id, workflow_name.clone(), steps.clone())); |
| 5673 | + wf_accm |
| 5674 | + }, |
| 5675 | + ); |
| 5676 | + workflows.sort_by(|first, second| first.0.cmp(&second.0)); |
| 5677 | + accm.push((*manifest_id, workflows)); |
| 5678 | + accm |
| 5679 | + }); |
| 5680 | + |
| 5681 | + as_ordered_vec.sort_by(|first, second| first.0.cmp(&second.0)); |
| 5682 | + |
| 5683 | + let mut items: Vec<ManifestItem> = Vec::new(); |
| 5684 | + for (manifest_id, workflows) in as_ordered_vec { |
| 5685 | + let manifest = sqlx::query_file_as!( |
| 5686 | + Manifest, |
| 5687 | + "queries/manifests_read.sql", |
| 5688 | + manifest_id, |
| 5689 | + None::<String>, |
| 5690 | + None::<String> |
| 5691 | + ) |
| 5692 | + .fetch_one(&self.pool) |
| 5693 | + .await?; |
| 5694 | + let success = workflows |
| 5695 | + .iter() |
| 5696 | + .all(|(_, _, steps)| steps.iter().all(|(_, _, success)| success.is_some())) |
| 5697 | + .then(|| { |
| 5698 | + workflows.iter().all(|(_, _, steps)| { |
| 5699 | + steps |
| 5700 | + .iter() |
| 5701 | + .all(|(_, _, success)| success.is_some_and(|success| success)) |
| 5702 | + }) |
| 5703 | + }); |
| 5704 | + |
| 5705 | + items.push(ManifestItem { |
| 5706 | + manifest, |
| 5707 | + success, |
| 5708 | + workflows, |
| 5709 | + }); |
| 5710 | + } |
| 5711 | + items.sort_by(|first, second| second.manifest.id.cmp(&first.manifest.id)); |
| 5712 | + Ok(items) |
| 5713 | + } |
| 5714 | + |
| 5715 | + async fn read_manifest( |
| 5716 | + &self, |
| 5717 | + collection: &str, |
| 5718 | + name: &str, |
| 5719 | + manifest_id: i64, |
| 5720 | + ) -> Result<ManifestView, Error> { |
| 5721 | + let manifest = sqlx::query_file_as!( |
| 5722 | + Manifest, |
| 5723 | + "queries/manifests_read.sql", |
| 5724 | + manifest_id, |
| 5725 | + collection, |
| 5726 | + name |
| 5727 | + ) |
| 5728 | + .fetch_one(&self.pool) |
| 5729 | + .await?; |
| 5730 | + let dag = sqlx::query_file_as!(Dag, "queries/dags_read.sql", manifest_id) |
| 5731 | + .fetch_one(&self.pool) |
| 5732 | + .await?; |
| 5733 | + let mut normalized = ManifestView { |
| 5734 | + manifest, |
| 5735 | + workflows: Vec::default(), |
| 5736 | + dag, |
| 5737 | + }; |
| 5738 | + let workflows = sqlx::query_file_as!(Workflow, "queries/workflows_list.sql", manifest_id) |
| 5739 | + .fetch_all(&self.pool) |
| 5740 | + .await?; |
| 5741 | + for workflow in workflows { |
| 5742 | + let steps = sqlx::query_file_as!(Step, "queries/steps_list.sql", workflow.id) |
| 5743 | + .fetch_all(&self.pool) |
| 5744 | + .await?; |
| 5745 | + normalized.workflows.push((workflow, steps)); |
| 5746 | + } |
| 5747 | + Ok(normalized) |
| 5748 | + } |
| 5749 | + |
| 5750 | + // workflows |
| 5751 | + |
| 5752 | + async fn read_workflow(&self, workflow_id: i64) -> Result<Workflow, Error> { |
| 5753 | + let workflow = sqlx::query_file_as!(Workflow, "queries/workflows_read.sql", workflow_id) |
| 5754 | + .fetch_one(&self.pool) |
| 5755 | + .await?; |
| 5756 | + Ok(workflow) |
| 5757 | + } |
| 5758 | + |
| 5759 | + async fn read_workflow_view(&self, workflow_id: i64) -> Result<WorkflowView, Error> { |
| 5760 | + let workflow = sqlx::query_file_as!(Workflow, "queries/workflows_read.sql", workflow_id) |
| 5761 | + .fetch_one(&self.pool) |
| 5762 | + .await?; |
| 5763 | + let steps = sqlx::query_file_as!(Step, "queries/steps_list.sql", workflow_id) |
| 5764 | + .fetch_all(&self.pool) |
| 5765 | + .await?; |
| 5766 | + Ok(WorkflowView { workflow, steps }) |
| 5767 | + } |
| 5768 | + |
| 5769 | + async fn create_workflow(&self, manifest_id: i64, name: &str) -> Result<i64, Error> { |
| 5770 | + let ret = sqlx::query_file!("queries/workflows_create.sql", manifest_id, name) |
| 5771 | + .fetch_one(&self.pool) |
| 5772 | + .await?; |
| 5773 | + Ok(ret.id) |
| 5774 | + } |
| 5775 | + |
| 5776 | + async fn update_workflow_start(&self, workflow_id: i64) -> Result<(), Error> { |
| 5777 | + sqlx::query_file!("queries/workflows_update_start.sql", workflow_id,) |
| 5778 | + .execute(&self.pool) |
| 5779 | + .await?; |
| 5780 | + Ok(()) |
| 5781 | + } |
| 5782 | + |
| 5783 | + async fn update_workflow_finish(&self, workflow_id: i64) -> Result<(), Error> { |
| 5784 | + sqlx::query_file!("queries/workflows_update_finish.sql", workflow_id) |
| 5785 | + .execute(&self.pool) |
| 5786 | + .await?; |
| 5787 | + Ok(()) |
| 5788 | + } |
| 5789 | + |
| 5790 | + // steps |
| 5791 | + |
| 5792 | + async fn create_step( |
| 5793 | + &self, |
| 5794 | + workflow_id: i64, |
| 5795 | + name: &str, |
| 5796 | + input: &str, |
| 5797 | + shell: &str, |
| 5798 | + environment: HashMap<String, String>, |
| 5799 | + ) -> Result<i64, Error> { |
| 5800 | + let environment_json = serde_json::ser::to_string(&environment).unwrap(); |
| 5801 | + let ret = sqlx::query_file!( |
| 5802 | + "queries/steps_create.sql", |
| 5803 | + workflow_id, |
| 5804 | + name, |
| 5805 | + input, |
| 5806 | + shell, |
| 5807 | + environment_json |
| 5808 | + ) |
| 5809 | + .fetch_one(&self.pool) |
| 5810 | + .await?; |
| 5811 | + Ok(ret.id) |
| 5812 | + } |
| 5813 | + |
| 5814 | + async fn read_step(&self, step_id: i64) -> Result<Step, Error> { |
| 5815 | + sqlx::query_file_as!(Step, "queries/steps_read.sql", step_id) |
| 5816 | + .fetch_one(&self.pool) |
| 5817 | + .await |
| 5818 | + } |
| 5819 | + |
| 5820 | + async fn read_step_env(&self, step_id: i64) -> Result<Environment, Error> { |
| 5821 | + let rows = sqlx::query_file!("queries/steps_read_env.sql", step_id) |
| 5822 | + .fetch_all(&self.pool) |
| 5823 | + .await?; |
| 5824 | + |
| 5825 | + let envs: Vec<Env> = rows |
| 5826 | + .iter() |
| 5827 | + .map(|record| Env((record.name.clone(), record.value.clone()))) |
| 5828 | + .collect(); |
| 5829 | + |
| 5830 | + Ok(Environment(envs)) |
| 5831 | + } |
| 5832 | + |
| 5833 | + async fn update_step_start(&self, step_id: i64) -> Result<(), Error> { |
| 5834 | + sqlx::query_file!("queries/steps_update_start.sql", step_id) |
| 5835 | + .execute(&self.pool) |
| 5836 | + .await?; |
| 5837 | + Ok(()) |
| 5838 | + } |
| 5839 | + |
| 5840 | + async fn update_step_finish( |
| 5841 | + &self, |
| 5842 | + step_id: i64, |
| 5843 | + stdout: &str, |
| 5844 | + stderr: &str, |
| 5845 | + exit_code: i8, |
| 5846 | + ) -> Result<(), Error> { |
| 5847 | + sqlx::query_file!( |
| 5848 | + "queries/steps_update_finish.sql", |
| 5849 | + stdout, |
| 5850 | + stderr, |
| 5851 | + exit_code, |
| 5852 | + step_id, |
| 5853 | + ) |
| 5854 | + .execute(&self.pool) |
| 5855 | + .await?; |
| 5856 | + Ok(()) |
| 5857 | + } |
| 5858 | + |
| 5859 | + async fn create_sample(&self, manifest_id: i64, sample: Sample) -> Result<i64, Error> { |
| 5860 | + let ret = sqlx::query_file!( |
| 5861 | + "queries/samples_create.sql", |
| 5862 | + manifest_id, |
| 5863 | + sample.load_1m, |
| 5864 | + sample.load_5m, |
| 5865 | + sample.load_15m, |
| 5866 | + sample.disk_total_bytes, |
| 5867 | + sample.disk_free_bytes, |
| 5868 | + sample.net_sent_bytes, |
| 5869 | + sample.net_received_bytes, |
| 5870 | + sample.net_sent_packets, |
| 5871 | + sample.net_received_packets, |
| 5872 | + sample.mem_total_bytes, |
| 5873 | + sample.mem_free_bytes, |
| 5874 | + sample.mem_available_bytes, |
| 5875 | + ) |
| 5876 | + .fetch_one(&self.pool) |
| 5877 | + .await?; |
| 5878 | + Ok(ret.id) |
| 5879 | + } |
| 5880 | + |
| 5881 | + async fn read_dag(&self, manifest_id: i64) -> Result<Dag, Error> { |
| 5882 | + sqlx::query_file_as!(Dag, "queries/dags_read.sql", manifest_id) |
| 5883 | + .fetch_one(&self.pool) |
| 5884 | + .await |
| 5885 | + } |
| 5886 | + } |
| 5887 | diff --git a/crates/database/src/lib.rs b/crates/database/src/lib.rs |
| 5888 | index 0ceda9f..cee98bc 100644 |
| 5889 | --- a/crates/database/src/lib.rs |
| 5890 | +++ b/crates/database/src/lib.rs |
| 5891 | @@ -1,17 +1,19 @@ |
| 5892 | use std::fs::create_dir_all; |
| 5893 | - use std::path::Path; |
| 5894 | + use std::path::{Path, PathBuf}; |
| 5895 | |
| 5896 | use sqlx::migrate::Migrator; |
| 5897 | use sqlx::sqlite::{SqliteConnectOptions, SqliteLockingMode, SqlitePool, SqlitePoolOptions}; |
| 5898 | use sqlx::ConnectOptions; |
| 5899 | - use sqlx::Error as SqlxError; |
| 5900 | + use sqlx::{Error as SqlxError, Sqlite, Transaction}; |
| 5901 | use tracing::log; |
| 5902 | |
| 5903 | - pub mod contributors; |
| 5904 | - pub mod jobs; |
| 5905 | - pub mod languages; |
| 5906 | - pub mod mail; |
| 5907 | - pub mod stats; |
| 5908 | + // pub mod contributors; |
| 5909 | + // pub mod jobs; |
| 5910 | + // pub mod languages; |
| 5911 | + // pub mod mail; |
| 5912 | + // pub mod stats; |
| 5913 | + |
| 5914 | + pub mod build; |
| 5915 | |
| 5916 | pub type Error = SqlxError; |
| 5917 | |
| 5918 | @@ -36,12 +38,12 @@ pub struct Builder { |
| 5919 | pub url: Option<String>, |
| 5920 | pub read_only: bool, |
| 5921 | pub log_queries: bool, |
| 5922 | - pub migrations: Option<String>, |
| 5923 | + pub migrations: Option<PathBuf>, |
| 5924 | } |
| 5925 | |
| 5926 | impl Builder { |
| 5927 | - pub fn url(mut self, url: &str) -> Self { |
| 5928 | - self.url = Some(url.to_string()); |
| 5929 | + pub fn path(mut self, path: &Path) -> Self { |
| 5930 | + self.url = Some(path.to_str().unwrap().to_string()); |
| 5931 | self |
| 5932 | } |
| 5933 | |
| 5934 | @@ -55,8 +57,8 @@ impl Builder { |
| 5935 | self |
| 5936 | } |
| 5937 | |
| 5938 | - pub fn migrations(mut self, path: &str) -> Self { |
| 5939 | - self.migrations = Some(path.to_string()); |
| 5940 | + pub fn migrations(mut self, path: &Path) -> Self { |
| 5941 | + self.migrations = Some(path.to_path_buf()); |
| 5942 | self |
| 5943 | } |
| 5944 | |
| 5945 | @@ -109,12 +111,31 @@ impl Builder { |
| 5946 | } |
| 5947 | } |
| 5948 | |
| 5949 | + pub struct Tx { |
| 5950 | + inner: Transaction<'static, Sqlite>, |
| 5951 | + } |
| 5952 | + |
| 5953 | + impl Tx { |
| 5954 | + pub async fn commit(self) -> Result<(), Error> { |
| 5955 | + self.inner.commit().await |
| 5956 | + } |
| 5957 | + |
| 5958 | + pub async fn rollback(self) -> Result<(), Error> { |
| 5959 | + self.inner.rollback().await |
| 5960 | + } |
| 5961 | + } |
| 5962 | + |
| 5963 | #[derive(Clone, Debug)] |
| 5964 | pub struct Wrapper { |
| 5965 | pub pool: SqlitePool, |
| 5966 | } |
| 5967 | |
| 5968 | impl Wrapper { |
| 5969 | + pub async fn begin(&self) -> Result<Tx, Error> { |
| 5970 | + let inner = self.pool.begin().await?; |
| 5971 | + Ok(Tx { inner }) |
| 5972 | + } |
| 5973 | + |
| 5974 | pub async fn close(&self) -> Result<(), Error> { |
| 5975 | self.pool.close().await; |
| 5976 | Ok(()) |
| 5977 | diff --git a/migrations/20231204194038_init.sql b/migrations/20231204194038_init.sql |
| 5978 | new file mode 100644 |
| 5979 | index 0000000..2882f7e |
| 5980 | --- /dev/null |
| 5981 | +++ b/migrations/20231204194038_init.sql |
| 5982 | @@ -0,0 +1,62 @@ |
| 5983 | + CREATE TABLE manifests ( |
| 5984 | + id INTEGER PRIMARY KEY NOT NULL, |
| 5985 | + collection TEXT NOT NULL, |
| 5986 | + name TEXT NOT NULL, |
| 5987 | + git_hash TEXT NOT NULL, |
| 5988 | + created_at INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 5989 | + started_at INTEGER CHECK (started_at > 0), |
| 5990 | + finished_at INTEGER CHECK (finished_at > 0) |
| 5991 | + ) STRICT ; |
| 5992 | + |
| 5993 | + CREATE TABLE workflows ( |
| 5994 | + id INTEGER PRIMARY KEY NOT NULL, |
| 5995 | + manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 5996 | + name TEXT NOT NULL, |
| 5997 | + started_at INTEGER CHECK (started_at > 0), |
| 5998 | + finished_at INTEGER CHECK (finished_at > 0) |
| 5999 | + ) STRICT ; |
| 6000 | + |
| 6001 | + CREATE TABLE steps ( |
| 6002 | + id INTEGER PRIMARY KEY NOT NULL, |
| 6003 | + name TEXT NOT NULL, |
| 6004 | + workflow_id INTEGER REFERENCES workflows(id) ON DELETE CASCADE NOT NULL, |
| 6005 | + shell TEXT NOT NULL DEFAULT "/bin/sh", |
| 6006 | + environment_json TEXT, |
| 6007 | + input TEXT NOT NULL, |
| 6008 | + started_at INTEGER CHECK (started_at > 0), |
| 6009 | + finished_at INTEGER CHECK (finished_at > 0), |
| 6010 | + stdout TEXT, |
| 6011 | + stderr TEXT, |
| 6012 | + exit_code INTEGER CHECK (exit_code <= 255) |
| 6013 | + ) STRICT ; |
| 6014 | + |
| 6015 | + CREATE TABLE steps_env_vars ( |
| 6016 | + id INTEGER PRIMARY KEY NOT NULL, |
| 6017 | + step_id INTEGER REFERENCES steps(id) ON DELETE CASCADE NOT NULL, |
| 6018 | + name TEXT NOT NULL, |
| 6019 | + value TEXT |
| 6020 | + ) STRICT ; |
| 6021 | + |
| 6022 | + CREATE TABLE dags ( |
| 6023 | + id INTEGER PRIMARY KEY NOT NULL, |
| 6024 | + manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 6025 | + dag_content TEXT NOT NULL |
| 6026 | + ) STRICT ; |
| 6027 | + |
| 6028 | + CREATE TABLE samples ( |
| 6029 | + id INTEGER PRIMARY KEY NOT NULL, |
| 6030 | + manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 6031 | + timestamp INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 6032 | + load_1m INTEGER, |
| 6033 | + load_5m INTEGER, |
| 6034 | + load_15m INTEGER, |
| 6035 | + disk_total_bytes INTEGER, |
| 6036 | + disk_free_bytes INTEGER, |
| 6037 | + net_sent_bytes INTEGER, |
| 6038 | + net_received_bytes INTEGER, |
| 6039 | + net_sent_packets INTEGER, |
| 6040 | + net_received_packets INTEGER, |
| 6041 | + mem_total_bytes INTEGER, |
| 6042 | + mem_free_bytes INTEGER, |
| 6043 | + mem_available_bytes INTEGER |
| 6044 | + ) STRICT ; |
| 6045 | diff --git a/packaging/archlinux/ayllu-git/PKGBUILD b/packaging/archlinux/ayllu-git/PKGBUILD |
| 6046 | index f2756ea..6e1751f 100644 |
| 6047 | --- a/packaging/archlinux/ayllu-git/PKGBUILD |
| 6048 | +++ b/packaging/archlinux/ayllu-git/PKGBUILD |
| 6049 | @@ -20,7 +20,7 @@ makedepends=( |
| 6050 | provides=("ayllu-git") |
| 6051 | optdepends=() |
| 6052 | source=( |
| 6053 | - "$_pkgname::git+https://ayllu-forge.org/ayllu/ayllu#branch=main" |
| 6054 | + "$_pkgname::git+https://ayllu-forge.org/ayllu/ayllu#branch=ayllu-build-round-2" |
| 6055 | ) |
| 6056 | # See: https://gitlab.archlinux.org/archlinux/packaging/packages/pacman/-/issues/20 |
| 6057 | options=(!lto) |
| 6058 | @@ -40,6 +40,9 @@ build() { |
| 6059 | } |
| 6060 | |
| 6061 | package() { |
| 6062 | + mkdir -p "${pkgdir}/usr/lib/ayllu/migrations" |
| 6063 | + find "${srcdir}/ayllu/migrations" -name "*.sql" \ |
| 6064 | + | xargs install -Dm644 -t "${pkgdir}/usr/lib/ayllu/migrations" |
| 6065 | install -Dm755 \ |
| 6066 | "${srcdir}/target/release/ayllu" "${pkgdir}/usr/bin/ayllu" |
| 6067 | install -Dm755 \ |
| 6068 | @@ -48,6 +51,10 @@ package() { |
| 6069 | "${srcdir}/target/release/ayllu-shell" "${pkgdir}/usr/bin/ayllu-shell" |
| 6070 | install -Dm755 \ |
| 6071 | "${srcdir}/target/release/ayllu-keys" "${pkgdir}/usr/bin/ayllu-keys" |
| 6072 | + install -Dm755 \ |
| 6073 | + "${srcdir}/target/release/ayllu-migrate" "${pkgdir}/usr/bin/ayllu-migrate" |
| 6074 | + install -Dm755 \ |
| 6075 | + "${srcdir}/target/release/ayllu-build" "${pkgdir}/usr/bin/ayllu-build" |
| 6076 | install -Dm644 \ |
| 6077 | "${srcdir}/ayllu/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}" |
| 6078 | install -Dm644 \ |
| 6079 | diff --git a/packaging/debian/postinst b/packaging/debian/postinst |
| 6080 | index 7a769f3..6a48aa1 100755 |
| 6081 | --- a/packaging/debian/postinst |
| 6082 | +++ b/packaging/debian/postinst |
| 6083 | @@ -3,6 +3,7 @@ |
| 6084 | AYLLU_SHELL_PATH="/usr/bin/ayllu-shell" |
| 6085 | AYLLU_HOME_PATH="/var/lib/ayllu" |
| 6086 | AYLLU_SHARE_PATH="/usr/share/ayllu" |
| 6087 | + AYLLU_LIB_PATH="/usr/lib/ayllu" |
| 6088 | |
| 6089 | if [ ! "$(id ayllu)" ] ; then |
| 6090 | adduser --system --group --shell="$AYLLU_SHELL_PATH" --home="$AYLLU_HOME_PATH" ayllu |
| 6091 | @@ -12,3 +13,7 @@ if [ -d "$AYLLU_SHARE_PATH" ] ; then |
| 6092 | mkdir -p "$AYLLU_SHARE_PATH" |
| 6093 | chown ayllu:ayllu "$AYLLU_SHARE_PATH" |
| 6094 | fi |
| 6095 | + |
| 6096 | + if [ -d "$ALLYU_LIB_PATH" ] ; then |
| 6097 | + mkdir -p "$AYLLU_LIB_PATH" |
| 6098 | + fi |
| 6099 | diff --git a/queries/authors_list_project.sql b/queries/authors_list_project.sql |
| 6100 | deleted file mode 100644 |
| 6101 | index 832e3de..0000000 |
| 6102 | --- a/queries/authors_list_project.sql |
| 6103 | +++ /dev/null |
| 6104 | @@ -1,30 +0,0 @@ |
| 6105 | - WITH RECURSIVE max_git_id AS |
| 6106 | - (SELECT contributions.id AS hash |
| 6107 | - FROM contributions |
| 6108 | - WHERE git_hash = ? |
| 6109 | - AND repo_path = ? |
| 6110 | - ORDER BY id DESC |
| 6111 | - LIMIT 1), |
| 6112 | - total_contributions AS |
| 6113 | - (SELECT COUNT(*) AS contributions |
| 6114 | - FROM contributions |
| 6115 | - WHERE repo_path = ? |
| 6116 | - AND id <= |
| 6117 | - (SELECT hash |
| 6118 | - FROM max_git_id) ) |
| 6119 | - SELECT authors.username, |
| 6120 | - authors.email, |
| 6121 | - COUNT(contributions.id) AS "count: i64", |
| 6122 | - SUM(contributions.lines_added) AS "lines_added: i64", |
| 6123 | - SUM(contributions.lines_removed) AS "lines_removed: i64", |
| 6124 | - ROUND((COUNT(contributions.id)/CAST( |
| 6125 | - (SELECT contributions |
| 6126 | - FROM total_contributions) AS REAL))*100, 2) AS "percentage: f64" |
| 6127 | - FROM contributions |
| 6128 | - LEFT JOIN authors ON (contributions.author_id = authors.id) |
| 6129 | - WHERE repo_path = ? |
| 6130 | - AND contributions.id <= |
| 6131 | - (SELECT hash |
| 6132 | - FROM max_git_id) |
| 6133 | - GROUP BY authors.email |
| 6134 | - ORDER BY "count: i64" DESC |
| 6135 | diff --git a/queries/authors_upsert.sql b/queries/authors_upsert.sql |
| 6136 | deleted file mode 100644 |
| 6137 | index 1c55636..0000000 |
| 6138 | --- a/queries/authors_upsert.sql |
| 6139 | +++ /dev/null |
| 6140 | @@ -1,10 +0,0 @@ |
| 6141 | - INSERT INTO authors |
| 6142 | - (username, email) |
| 6143 | - VALUES |
| 6144 | - (?, ?) |
| 6145 | - ON CONFLICT |
| 6146 | - DO UPDATE |
| 6147 | - SET |
| 6148 | - username = username, |
| 6149 | - email = email |
| 6150 | - RETURNING id |
| 6151 | diff --git a/queries/commits_count.sql b/queries/commits_count.sql |
| 6152 | deleted file mode 100644 |
| 6153 | index 0088bb8..0000000 |
| 6154 | --- a/queries/commits_count.sql |
| 6155 | +++ /dev/null |
| 6156 | @@ -1,9 +0,0 @@ |
| 6157 | - SELECT |
| 6158 | - COUNT(id) AS count |
| 6159 | - FROM contributions |
| 6160 | - WHERE |
| 6161 | - repo_path = ? AND |
| 6162 | - id <= ( |
| 6163 | - SELECT id FROM contributions |
| 6164 | - WHERE git_hash = ? AND repo_path = ? |
| 6165 | - ) |
| 6166 | diff --git a/queries/contribution_add.sql b/queries/contribution_add.sql |
| 6167 | deleted file mode 100644 |
| 6168 | index e1085e3..0000000 |
| 6169 | --- a/queries/contribution_add.sql |
| 6170 | +++ /dev/null |
| 6171 | @@ -1,11 +0,0 @@ |
| 6172 | - WITH previous(total) AS ( |
| 6173 | - SELECT total FROM contribution_tally |
| 6174 | - WHERE |
| 6175 | - author_id = ? AND repo_path = ? |
| 6176 | - ORDER BY id DESC |
| 6177 | - LIMIT 1 |
| 6178 | - ) |
| 6179 | - INSERT INTO contribution_tally |
| 6180 | - (git_hash, repo_path, author_id, total) |
| 6181 | - VALUES |
| 6182 | - (?, ?, ?, COALESCE((SELECT(total) FROM previous), 0)+1) |
| 6183 | diff --git a/queries/contribution_delete.sql b/queries/contribution_delete.sql |
| 6184 | deleted file mode 100644 |
| 6185 | index 6fdbe5c..0000000 |
| 6186 | --- a/queries/contribution_delete.sql |
| 6187 | +++ /dev/null |
| 6188 | @@ -1,3 +0,0 @@ |
| 6189 | - DELETE FROM contribution_tally |
| 6190 | - WHERE |
| 6191 | - repo_path = ? |
| 6192 | diff --git a/queries/contributions_add.sql b/queries/contributions_add.sql |
| 6193 | deleted file mode 100644 |
| 6194 | index 9883d94..0000000 |
| 6195 | --- a/queries/contributions_add.sql |
| 6196 | +++ /dev/null |
| 6197 | @@ -1,4 +0,0 @@ |
| 6198 | - INSERT INTO contributions |
| 6199 | - (author_id, git_hash, repo_path, time, lines_added, lines_removed) |
| 6200 | - VALUES |
| 6201 | - (?, ?, ?, ?, ?, ?) |
| 6202 | diff --git a/queries/contributions_bucket.sql b/queries/contributions_bucket.sql |
| 6203 | deleted file mode 100644 |
| 6204 | index c4e2e55..0000000 |
| 6205 | --- a/queries/contributions_bucket.sql |
| 6206 | +++ /dev/null |
| 6207 | @@ -1,10 +0,0 @@ |
| 6208 | - SELECT |
| 6209 | - COUNT(id) AS "count!: i64", |
| 6210 | - time, |
| 6211 | - SUM(lines_added) AS "added!: i64", |
| 6212 | - SUM(lines_removed) AS "removed!: i64" |
| 6213 | - FROM contributions WHERE |
| 6214 | - repo_path = ? AND |
| 6215 | - id <= (SELECT id FROM contributions WHERE git_hash = ?) AND |
| 6216 | - time <= ? AND time >= ? |
| 6217 | - GROUP BY strftime(?, time) |
| 6218 | diff --git a/queries/contributions_delete.sql b/queries/contributions_delete.sql |
| 6219 | deleted file mode 100644 |
| 6220 | index 0ee5563..0000000 |
| 6221 | --- a/queries/contributions_delete.sql |
| 6222 | +++ /dev/null |
| 6223 | @@ -1,2 +0,0 @@ |
| 6224 | - DELETE FROM contributions |
| 6225 | - WHERE repo_path = ? |
| 6226 | diff --git a/queries/contributions_list.sql b/queries/contributions_list.sql |
| 6227 | deleted file mode 100644 |
| 6228 | index fae5633..0000000 |
| 6229 | --- a/queries/contributions_list.sql |
| 6230 | +++ /dev/null |
| 6231 | @@ -1,42 +0,0 @@ |
| 6232 | - WITH RECURSIVE |
| 6233 | - tallys AS ( |
| 6234 | - SELECT |
| 6235 | - authors.username AS name, |
| 6236 | - authors.email AS email, |
| 6237 | - MAX(contribution_tally.total) AS total |
| 6238 | - FROM contribution_tally |
| 6239 | - LEFT JOIN authors ON |
| 6240 | - (authors.id = contribution_tally.author_id) |
| 6241 | - WHERE |
| 6242 | - contribution_tally.id < ( |
| 6243 | - SELECT id FROM contributions |
| 6244 | - WHERE |
| 6245 | - repo_path = ? AND git_hash = ? |
| 6246 | - ORDER BY id DESC |
| 6247 | - LIMIT 1 |
| 6248 | - ) AND |
| 6249 | - contribution_tally.repo_path = ? |
| 6250 | - GROUP BY authors.email |
| 6251 | - ORDER BY contribution_tally.total DESC |
| 6252 | - LIMIT 5), |
| 6253 | - raw_commits AS ( |
| 6254 | - SELECT |
| 6255 | - COUNT(*) as total |
| 6256 | - FROM contributions |
| 6257 | - WHERE |
| 6258 | - contributions.id < ( |
| 6259 | - SELECT id FROM contributions |
| 6260 | - WHERE |
| 6261 | - repo_path = ? AND git_hash = ? |
| 6262 | - ORDER BY id DESC |
| 6263 | - LIMIT 1 |
| 6264 | - ) AND |
| 6265 | - contributions.repo_path = ? |
| 6266 | - ) |
| 6267 | - SELECT |
| 6268 | - name, |
| 6269 | - email, |
| 6270 | - ( |
| 6271 | - CAST(tallys.total AS REAL)/(SELECT total FROM raw_commits) |
| 6272 | - ) * 100 AS "percentage: i64" |
| 6273 | - FROM tallys |
| 6274 | diff --git a/queries/job_tracking_add.sql b/queries/job_tracking_add.sql |
| 6275 | deleted file mode 100644 |
| 6276 | index 7e70756..0000000 |
| 6277 | --- a/queries/job_tracking_add.sql |
| 6278 | +++ /dev/null |
| 6279 | @@ -1,4 +0,0 @@ |
| 6280 | - INSERT INTO job_tracking |
| 6281 | - (repo_path, git_hash, kind, job_id) |
| 6282 | - VALUES |
| 6283 | - (?, ?, ?, ?) |
| 6284 | diff --git a/queries/job_tracking_delete.sql b/queries/job_tracking_delete.sql |
| 6285 | deleted file mode 100644 |
| 6286 | index 3aef33d..0000000 |
| 6287 | --- a/queries/job_tracking_delete.sql |
| 6288 | +++ /dev/null |
| 6289 | @@ -1,3 +0,0 @@ |
| 6290 | - DELETE FROM job_tracking |
| 6291 | - WHERE |
| 6292 | - repo_path = ? |
| 6293 | diff --git a/queries/job_tracking_delete_by_repo.sql b/queries/job_tracking_delete_by_repo.sql |
| 6294 | deleted file mode 100644 |
| 6295 | index ebd0363..0000000 |
| 6296 | --- a/queries/job_tracking_delete_by_repo.sql |
| 6297 | +++ /dev/null |
| 6298 | @@ -1,3 +0,0 @@ |
| 6299 | - DELETE FROM jobs |
| 6300 | - WHERE |
| 6301 | - repo_path = ? |
| 6302 | diff --git a/queries/job_tracking_read.sql b/queries/job_tracking_read.sql |
| 6303 | deleted file mode 100644 |
| 6304 | index 823dfc5..0000000 |
| 6305 | --- a/queries/job_tracking_read.sql |
| 6306 | +++ /dev/null |
| 6307 | @@ -1,8 +0,0 @@ |
| 6308 | - SELECT |
| 6309 | - git_hash AS "git_hash!" |
| 6310 | - FROM job_tracking |
| 6311 | - WHERE |
| 6312 | - repo_path = ? AND |
| 6313 | - kind = ? |
| 6314 | - ORDER BY id DESC |
| 6315 | - LIMIT 1 |
| 6316 | diff --git a/queries/jobs_create.sql b/queries/jobs_create.sql |
| 6317 | deleted file mode 100644 |
| 6318 | index 4a1bea5..0000000 |
| 6319 | --- a/queries/jobs_create.sql |
| 6320 | +++ /dev/null |
| 6321 | @@ -1,5 +0,0 @@ |
| 6322 | - INSERT INTO jobs |
| 6323 | - (created_at, repo_path, kind) |
| 6324 | - VALUES |
| 6325 | - (?, ?, ?) |
| 6326 | - RETURNING id |
| 6327 | diff --git a/queries/jobs_delete.sql b/queries/jobs_delete.sql |
| 6328 | deleted file mode 100644 |
| 6329 | index c70ba25..0000000 |
| 6330 | --- a/queries/jobs_delete.sql |
| 6331 | +++ /dev/null |
| 6332 | @@ -1,2 +0,0 @@ |
| 6333 | - DELETE FROM jobs |
| 6334 | - WHERE jobs.id = ? |
| 6335 | diff --git a/queries/jobs_list.sql b/queries/jobs_list.sql |
| 6336 | deleted file mode 100644 |
| 6337 | index b1e7f72..0000000 |
| 6338 | --- a/queries/jobs_list.sql |
| 6339 | +++ /dev/null |
| 6340 | @@ -1,15 +0,0 @@ |
| 6341 | - SELECT |
| 6342 | - jobs.id AS "id!", |
| 6343 | - created_at AS "created_at: OffsetDateTime", |
| 6344 | - jobs.repo_path AS "repo_path!: String", |
| 6345 | - jobs.kind AS "kind!: String", |
| 6346 | - runtime AS "runtime: u32", |
| 6347 | - success AS "success: bool", |
| 6348 | - ( |
| 6349 | - SELECT COUNT(id) FROM job_tracking |
| 6350 | - WHERE job_tracking.job_id = jobs.id |
| 6351 | - ) AS "commits!: i32" |
| 6352 | - FROM jobs |
| 6353 | - WHERE |
| 6354 | - jobs.repo_path = ? OR ? IS NULL |
| 6355 | - ORDER BY DATETIME(created_at) ASC |
| 6356 | diff --git a/queries/jobs_update.sql b/queries/jobs_update.sql |
| 6357 | deleted file mode 100644 |
| 6358 | index ea7e521..0000000 |
| 6359 | --- a/queries/jobs_update.sql |
| 6360 | +++ /dev/null |
| 6361 | @@ -1,6 +0,0 @@ |
| 6362 | - UPDATE jobs |
| 6363 | - SET |
| 6364 | - runtime = ?, |
| 6365 | - success = ? |
| 6366 | - WHERE |
| 6367 | - jobs.id = ? |
| 6368 | diff --git a/queries/languages_add.sql b/queries/languages_add.sql |
| 6369 | deleted file mode 100644 |
| 6370 | index 54551b3..0000000 |
| 6371 | --- a/queries/languages_add.sql |
| 6372 | +++ /dev/null |
| 6373 | @@ -1,4 +0,0 @@ |
| 6374 | - INSERT INTO languages |
| 6375 | - (git_hash, repo_path, language, loc) |
| 6376 | - VALUES |
| 6377 | - (?,?,?,?) |
| 6378 | diff --git a/queries/languages_delete.sql b/queries/languages_delete.sql |
| 6379 | deleted file mode 100644 |
| 6380 | index 06c4349..0000000 |
| 6381 | --- a/queries/languages_delete.sql |
| 6382 | +++ /dev/null |
| 6383 | @@ -1,3 +0,0 @@ |
| 6384 | - DELETE FROM languages |
| 6385 | - WHERE |
| 6386 | - repo_path = ? |
| 6387 | diff --git a/queries/languages_list.sql b/queries/languages_list.sql |
| 6388 | deleted file mode 100644 |
| 6389 | index 608a719..0000000 |
| 6390 | --- a/queries/languages_list.sql |
| 6391 | +++ /dev/null |
| 6392 | @@ -1,13 +0,0 @@ |
| 6393 | - SELECT |
| 6394 | - language, |
| 6395 | - loc, |
| 6396 | - ROUND( |
| 6397 | - CAST(loc AS REAL)/CAST( |
| 6398 | - (SELECT SUM(loc) FROM languages |
| 6399 | - WHERE repo_path = ? AND git_hash = ?) AS REAL)*100) |
| 6400 | - AS "percentage: f64" |
| 6401 | - FROM languages |
| 6402 | - WHERE |
| 6403 | - repo_path = ? AND git_hash = ? |
| 6404 | - ORDER BY "percentage: f64" DESC |
| 6405 | - LIMIT 5 |
| 6406 | diff --git a/queries/latest_commit.sql b/queries/latest_commit.sql |
| 6407 | deleted file mode 100644 |
| 6408 | index bd26eac..0000000 |
| 6409 | --- a/queries/latest_commit.sql |
| 6410 | +++ /dev/null |
| 6411 | @@ -1,7 +0,0 @@ |
| 6412 | - SELECT |
| 6413 | - git_hash |
| 6414 | - FROM contributions |
| 6415 | - WHERE |
| 6416 | - repo_path = ? |
| 6417 | - ORDER BY id DESC |
| 6418 | - LIMIT 1 |
| 6419 | diff --git a/queries/mail_deactivate_unused.sql b/queries/mail_deactivate_unused.sql |
| 6420 | deleted file mode 100644 |
| 6421 | index 730dc92..0000000 |
| 6422 | --- a/queries/mail_deactivate_unused.sql |
| 6423 | +++ /dev/null |
| 6424 | @@ -1 +0,0 @@ |
| 6425 | - UPDATE lists SET enabled = 0 WHERE address NOT IN (?) |
| 6426 | diff --git a/queries/mail_deliver_message.sql b/queries/mail_deliver_message.sql |
| 6427 | deleted file mode 100644 |
| 6428 | index 6763a82..0000000 |
| 6429 | --- a/queries/mail_deliver_message.sql |
| 6430 | +++ /dev/null |
| 6431 | @@ -1,10 +0,0 @@ |
| 6432 | - INSERT INTO messages |
| 6433 | - (message_id, list_id, in_reply_to, subject, mail_from, content_body, raw_message) |
| 6434 | - VALUES ( |
| 6435 | - ?, |
| 6436 | - ( SELECT id FROM lists WHERE address = ? LIMIT 1 ), |
| 6437 | - ?, |
| 6438 | - ?, |
| 6439 | - ?, |
| 6440 | - ?, ? |
| 6441 | - ) RETURNING messages.id |
| 6442 | diff --git a/queries/mail_has_message.sql b/queries/mail_has_message.sql |
| 6443 | deleted file mode 100644 |
| 6444 | index e32ce95..0000000 |
| 6445 | --- a/queries/mail_has_message.sql |
| 6446 | +++ /dev/null |
| 6447 | @@ -1,5 +0,0 @@ |
| 6448 | - SELECT |
| 6449 | - CASE |
| 6450 | - WHEN (SELECT COUNT(*) FROM messages WHERE message_id = ?) >= 1 THEN TRUE |
| 6451 | - ELSE FALSE |
| 6452 | - END AS "has_message!: bool" |
| 6453 | diff --git a/queries/mail_list_create.sql b/queries/mail_list_create.sql |
| 6454 | deleted file mode 100644 |
| 6455 | index 770b76a..0000000 |
| 6456 | --- a/queries/mail_list_create.sql |
| 6457 | +++ /dev/null |
| 6458 | @@ -1,9 +0,0 @@ |
| 6459 | - INSERT INTO lists |
| 6460 | - (name, address, description, enabled) |
| 6461 | - VALUES |
| 6462 | - (?, ?, ?, ?) |
| 6463 | - ON CONFLICT (address) DO |
| 6464 | - UPDATE SET |
| 6465 | - name = ?, |
| 6466 | - description = ?, |
| 6467 | - enabled = ? |
| 6468 | diff --git a/queries/mail_list_outbox.sql b/queries/mail_list_outbox.sql |
| 6469 | deleted file mode 100644 |
| 6470 | index 8eaa79e..0000000 |
| 6471 | --- a/queries/mail_list_outbox.sql |
| 6472 | +++ /dev/null |
| 6473 | @@ -1,13 +0,0 @@ |
| 6474 | - SELECT |
| 6475 | - outbox.id, |
| 6476 | - messages.message_id AS "message_id!: String", |
| 6477 | - lists.name AS "list_name!: String", |
| 6478 | - participants.address AS "address!: String", |
| 6479 | - messages.raw_message AS raw_message |
| 6480 | - FROM outbox |
| 6481 | - LEFT JOIN participants ON outbox.recipient = participants.address |
| 6482 | - LEFT JOIN messages ON messages.id = outbox.message_id |
| 6483 | - LEFT JOIN lists ON messages.list_id = lists.id |
| 6484 | - WHERE |
| 6485 | - (SELECT COUNT(*) FROM delivery_failures |
| 6486 | - WHERE delivery_failures.outbox_id = outbox.id) < ? |
| 6487 | diff --git a/queries/mail_outbox_failed.sql b/queries/mail_outbox_failed.sql |
| 6488 | deleted file mode 100644 |
| 6489 | index c7dafcb..0000000 |
| 6490 | --- a/queries/mail_outbox_failed.sql |
| 6491 | +++ /dev/null |
| 6492 | @@ -1,3 +0,0 @@ |
| 6493 | - INSERT INTO delivery_failures |
| 6494 | - (outbox_id, error_kind, message) |
| 6495 | - VALUES (?, ?, ?) |
| 6496 | diff --git a/queries/mail_outbox_successful.sql b/queries/mail_outbox_successful.sql |
| 6497 | deleted file mode 100644 |
| 6498 | index 0b0269c..0000000 |
| 6499 | --- a/queries/mail_outbox_successful.sql |
| 6500 | +++ /dev/null |
| 6501 | @@ -1 +0,0 @@ |
| 6502 | - DELETE FROM outbox WHERE id = ? |
| 6503 | diff --git a/queries/mail_read_message.sql b/queries/mail_read_message.sql |
| 6504 | deleted file mode 100644 |
| 6505 | index 1696cae..0000000 |
| 6506 | --- a/queries/mail_read_message.sql |
| 6507 | +++ /dev/null |
| 6508 | @@ -1 +0,0 @@ |
| 6509 | - SELECT * FROM messages WHERE id = ? |
| 6510 | diff --git a/queries/mail_read_thread.sql b/queries/mail_read_thread.sql |
| 6511 | deleted file mode 100644 |
| 6512 | index 09342d0..0000000 |
| 6513 | --- a/queries/mail_read_thread.sql |
| 6514 | +++ /dev/null |
| 6515 | @@ -1,18 +0,0 @@ |
| 6516 | - WITH RECURSIVE tree AS ( |
| 6517 | - SELECT messages.*, 0 AS depth FROM messages |
| 6518 | - WHERE messages.message_id = ? |
| 6519 | - UNION ALL |
| 6520 | - SELECT other.*, depth + 1 FROM messages other |
| 6521 | - JOIN tree ON other.in_reply_to = tree.message_id |
| 6522 | - ) |
| 6523 | - SELECT |
| 6524 | - message_id, |
| 6525 | - in_reply_to, |
| 6526 | - subject, |
| 6527 | - (SELECT address FROM participants WHERE participants.id = tree.mail_from LIMIT 1) |
| 6528 | - mail_from, |
| 6529 | - raw_message, |
| 6530 | - content_body, |
| 6531 | - reply_count, |
| 6532 | - depth AS "depth!: i64" |
| 6533 | - FROM tree ORDER BY depth |
| 6534 | diff --git a/queries/mail_read_threads.sql b/queries/mail_read_threads.sql |
| 6535 | deleted file mode 100644 |
| 6536 | index d2e3b4a..0000000 |
| 6537 | --- a/queries/mail_read_threads.sql |
| 6538 | +++ /dev/null |
| 6539 | @@ -1,9 +0,0 @@ |
| 6540 | - SELECT |
| 6541 | - messages.message_id, |
| 6542 | - messages.subject, |
| 6543 | - messages.reply_count, |
| 6544 | - participants.address AS "mail_from!: String" |
| 6545 | - FROM messages |
| 6546 | - LEFT JOIN lists ON lists.id = messages.id |
| 6547 | - LEFT JOIN participants ON participants.id = messages.mail_from |
| 6548 | - WHERE lists.name = ? AND messages.in_reply_to IS NULL |
| 6549 | diff --git a/queries/mail_thread_count.sql b/queries/mail_thread_count.sql |
| 6550 | deleted file mode 100644 |
| 6551 | index 5dc619a..0000000 |
| 6552 | --- a/queries/mail_thread_count.sql |
| 6553 | +++ /dev/null |
| 6554 | @@ -1,4 +0,0 @@ |
| 6555 | - SELECT COUNT(*) AS "count: i64" FROM messages |
| 6556 | - WHERE |
| 6557 | - list_id = (SELECT list_id FROM lists WHERE list_id = ?) AND |
| 6558 | - in_reply_to IS NULL |
| 6559 | diff --git a/queries/mail_thread_summary.sql b/queries/mail_thread_summary.sql |
| 6560 | deleted file mode 100644 |
| 6561 | index c76aa55..0000000 |
| 6562 | --- a/queries/mail_thread_summary.sql |
| 6563 | +++ /dev/null |
| 6564 | @@ -1,3 +0,0 @@ |
| 6565 | - SELECT messages.* FROM messages |
| 6566 | - LEFT JOIN lists ON lists.id = messages.id |
| 6567 | - WHERE lists.name = ? AND messages.reply_to IS NULL |
| 6568 | diff --git a/queries/mail_upsert_participant.sql b/queries/mail_upsert_participant.sql |
| 6569 | deleted file mode 100644 |
| 6570 | index 67b0973..0000000 |
| 6571 | --- a/queries/mail_upsert_participant.sql |
| 6572 | +++ /dev/null |
| 6573 | @@ -1,6 +0,0 @@ |
| 6574 | - INSERT INTO participants |
| 6575 | - (address, authorized_sender) |
| 6576 | - VALUES (?, ?) |
| 6577 | - ON CONFLICT DO NOTHING; |
| 6578 | - |
| 6579 | - SELECT id FROM participants WHERE address = ? |
| 6580 | diff --git a/queries/mail_upsert_subscription.sql b/queries/mail_upsert_subscription.sql |
| 6581 | deleted file mode 100644 |
| 6582 | index 78cd886..0000000 |
| 6583 | --- a/queries/mail_upsert_subscription.sql |
| 6584 | +++ /dev/null |
| 6585 | @@ -1,6 +0,0 @@ |
| 6586 | - INSERT INTO subscriptions |
| 6587 | - (participant_id, list_id) |
| 6588 | - VALUES ( |
| 6589 | - (SELECT id FROM participants WHERE address = ? LIMIT 1), |
| 6590 | - (SELECT id FROM lists WHERE address = ? LIMIT 1) |
| 6591 | - ) ON CONFLICT DO NOTHING; |
| 6592 | diff --git a/scripts/build_deb.sh b/scripts/build_deb.sh |
| 6593 | index 26709db..8ecdf77 100755 |
| 6594 | --- a/scripts/build_deb.sh |
| 6595 | +++ b/scripts/build_deb.sh |
| 6596 | @@ -12,10 +12,13 @@ cp -rvp packaging/debian/ "${BUILD_DIR}/DEBIAN/" |
| 6597 | |
| 6598 | sed -i "s/Version: X.X.X/Version: ${AYLLU_VERSION}/g" "${BUILD_DIR}/DEBIAN/control" |
| 6599 | |
| 6600 | + find migrations -name "*.sql" | xargs install -Dm644 -t "${BUILD_DIR}/usr/lib/ayllu/migrations" |
| 6601 | install -Dm755 "target/release/ayllu" "${BUILD_DIR}/usr/bin/ayllu" |
| 6602 | install -Dm755 "target/release/quipu" "${BUILD_DIR}/usr/bin/quipu" |
| 6603 | install -Dm755 "target/release/ayllu-shell" "${BUILD_DIR}/usr/bin/ayllu-shell" |
| 6604 | install -Dm755 "target/release/ayllu-keys" "${BUILD_DIR}/usr/bin/ayllu-keys" |
| 6605 | + install -Dm755 "target/release/ayllu-migrate" "${BUILD_DIR}/usr/bin/ayllu-migrate" |
| 6606 | + install -Dm755 "target/release/ayllu-build" "${BUILD_DIR}/usr/bin/ayllu-build" |
| 6607 | install -Dm644 "LICENSE" "${BUILD_DIR}/usr/share/licenses/ayllu" |
| 6608 | install -Dm644 "config.example.toml" "${BUILD_DIR}/etc/ayllu/config.example.toml" |
| 6609 | install -Dm644 \ |
| 6610 | diff --git a/scripts/ensure_database.sh b/scripts/ensure_database.sh |
| 6611 | index f954193..722ad25 100755 |
| 6612 | --- a/scripts/ensure_database.sh |
| 6613 | +++ b/scripts/ensure_database.sh |
| 6614 | @@ -2,12 +2,11 @@ |
| 6615 | set -ex |
| 6616 | # initialize a local database for builds and testing assuming the package |
| 6617 | # has database support. |
| 6618 | - |
| 6619 | + |
| 6620 | DB_PATH="db/ayllu.db" |
| 6621 | DB_URL="sqlite://${DB_PATH}" |
| 6622 | |
| 6623 | mkdir -p "$(dirname "${DB_PATH}")" |
| 6624 | - |
| 6625 | echo "$DB_PATH" |
| 6626 | |
| 6627 | if [ ! -e "${DB_PATH}" ]; then |