diff options
Diffstat (limited to 'gnu/tests/forgejo.scm')
| -rw-r--r-- | gnu/tests/forgejo.scm | 416 |
1 files changed, 0 insertions, 416 deletions
diff --git a/gnu/tests/forgejo.scm b/gnu/tests/forgejo.scm deleted file mode 100644 index d13114228f7..00000000000 --- a/gnu/tests/forgejo.scm +++ /dev/null | |||
| @@ -1,416 +0,0 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2026 Maxim Cournoyer <maxim@guixotic.coop> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (gnu tests forgejo) | ||
| 20 | #:use-module (gnu packages databases) | ||
| 21 | #:use-module (gnu packages guile) | ||
| 22 | #:use-module (gnu packages linux) | ||
| 23 | #:use-module (gnu packages sqlite) | ||
| 24 | #:use-module (gnu packages version-control) | ||
| 25 | #:use-module (gnu tests) | ||
| 26 | #:use-module (gnu system) | ||
| 27 | #:use-module (gnu system vm) | ||
| 28 | #:use-module (gnu services) | ||
| 29 | #:use-module (gnu services base) | ||
| 30 | #:use-module (gnu services databases) | ||
| 31 | #:use-module (gnu services forgejo) | ||
| 32 | #:use-module (gnu services networking) | ||
| 33 | #:use-module (gnu services ssh) | ||
| 34 | #:use-module (guix gexp) | ||
| 35 | #:use-module (ice-9 match) | ||
| 36 | #:use-module (srfi srfi-1) | ||
| 37 | #:export (%test-forgejo | ||
| 38 | %test-forgejo-mysql | ||
| 39 | %test-forgejo-postgres)) | ||
| 40 | |||
| 41 | ;;; Sample SSH key generated with 'ssh-keygen -t ed25519'. | ||
| 42 | (define dummy-ssh-private-key "\ | ||
| 43 | -----BEGIN OPENSSH PRIVATE KEY----- | ||
| 44 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW | ||
| 45 | QyNTUxOQAAACAsDitIHHy6wlmXz7cJO0UQQbrszdpLvBSiTZk1l08z0AAAAJBl4y2eZeMt | ||
| 46 | ngAAAAtzc2gtZWQyNTUxOQAAACAsDitIHHy6wlmXz7cJO0UQQbrszdpLvBSiTZk1l08z0A | ||
| 47 | AAAEDxsrZIsEgI6cehDgFNsP/FQ3aefvb7fUtp/RF6sZf3GiwOK0gcfLrCWZfPtwk7RRBB | ||
| 48 | uuzN2ku8FKJNmTWXTzPQAAAAC21heGltQHRlcnJhAQI= | ||
| 49 | -----END OPENSSH PRIVATE KEY----- | ||
| 50 | ") | ||
| 51 | |||
| 52 | (define dummy-ssh-public-key "\ | ||
| 53 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICwOK0gcfLrCWZfPtwk7RRBBuuzN2ku8FK\ | ||
| 54 | JNmTWXTzPQ dummy") | ||
| 55 | |||
| 56 | ;;; For a manual test/inspection: | ||
| 57 | #;( | ||
| 58 | |||
| 59 | $(./pre-inst-env guix system vm \ | ||
| 60 | -e '(@@ (gnu tests forgejo) %forgejo-os)' --no-graphic) \ | ||
| 61 | -nic user,model=virtio-net-pci,hostfwd=tcp::3000-:3000 -m 1024 | ||
| 62 | |||
| 63 | ) | ||
| 64 | |||
| 65 | (define %forgejo-os | ||
| 66 | (let ((base %simple-os)) | ||
| 67 | (operating-system | ||
| 68 | (inherit %simple-os) | ||
| 69 | (packages (cons* git-minimal git-lfs | ||
| 70 | ;;sqlite strace ;for debug | ||
| 71 | %base-packages)) | ||
| 72 | (services | ||
| 73 | (cons* (service dhcpcd-service-type) | ||
| 74 | (service openssh-service-type) | ||
| 75 | (service forgejo-service-type | ||
| 76 | (forgejo-configuration | ||
| 77 | (application-slogan "In Code We Trust") | ||
| 78 | (run-mode "dev") | ||
| 79 | (log-level "debug") | ||
| 80 | (user-push-to-create? #t) | ||
| 81 | (default-push-to-create-private? #f) | ||
| 82 | (mailer? #t) | ||
| 83 | (mail-from "Forgejo Test <test@example.com>") | ||
| 84 | (mail-protocol "dummy") | ||
| 85 | (mail-notification? #t) | ||
| 86 | (mail-notification-on-new-user-signin? #t))) | ||
| 87 | %base-services))))) | ||
| 88 | |||
| 89 | (define %forgejo-os/postgres | ||
| 90 | (operating-system | ||
| 91 | (inherit %forgejo-os) | ||
| 92 | (services | ||
| 93 | (cons* | ||
| 94 | (service postgresql-service-type | ||
| 95 | (postgresql-configuration | ||
| 96 | (postgresql postgresql))) | ||
| 97 | (service postgresql-role-service-type | ||
| 98 | (postgresql-role-configuration | ||
| 99 | (roles (list (postgresql-role | ||
| 100 | (name "forgejo") | ||
| 101 | (create-database? #t)))))) | ||
| 102 | (modify-services (operating-system-user-services %forgejo-os) | ||
| 103 | (forgejo-service-type | ||
| 104 | config => | ||
| 105 | (forgejo-configuration | ||
| 106 | (inherit config) | ||
| 107 | (database-type "postgres")))))))) | ||
| 108 | |||
| 109 | (define %forgejo-os/mysql | ||
| 110 | (operating-system | ||
| 111 | (inherit %forgejo-os) | ||
| 112 | (services | ||
| 113 | (cons | ||
| 114 | (service mysql-service-type) | ||
| 115 | (modify-services (operating-system-user-services %forgejo-os) | ||
| 116 | (forgejo-service-type | ||
| 117 | config => | ||
| 118 | (forgejo-configuration | ||
| 119 | (inherit config) | ||
| 120 | (database-type "mysql") | ||
| 121 | (database-host "/run/mysqld/mysqld.sock")))))))) | ||
| 122 | |||
| 123 | (define (os->forgejo-configuration os) | ||
| 124 | (let ((forgejo-service | ||
| 125 | (find (lambda (x) | ||
| 126 | (eq? forgejo-service-type (service-kind x))) | ||
| 127 | (operating-system-user-services os)))) | ||
| 128 | (service-value forgejo-service))) | ||
| 129 | |||
| 130 | (define* (make-forgejo-test name #:key (os %forgejo-os)) | ||
| 131 | "Return a test of an OS running the Forgejo service." | ||
| 132 | |||
| 133 | (define forgejo-config | ||
| 134 | (os->forgejo-configuration os)) | ||
| 135 | |||
| 136 | (define database-type | ||
| 137 | (forgejo-configuration-database-type forgejo-config)) | ||
| 138 | |||
| 139 | (define database-name | ||
| 140 | (forgejo-configuration-database-name forgejo-config)) | ||
| 141 | |||
| 142 | (define database-user | ||
| 143 | (forgejo-configuration-database-user forgejo-config)) | ||
| 144 | |||
| 145 | (define vm | ||
| 146 | (virtual-machine | ||
| 147 | (operating-system (marionette-operating-system | ||
| 148 | os | ||
| 149 | #:imported-modules '((gnu services herd)) | ||
| 150 | #:requirements (match database-type | ||
| 151 | ("mysql" '(mysql)) | ||
| 152 | ("postgres" '(postgres)) | ||
| 153 | ("sqlite3" '())))) | ||
| 154 | (memory-size 1024) | ||
| 155 | (port-forwardings '((3333 . 3000))))) ;3333 on host | ||
| 156 | |||
| 157 | (define test | ||
| 158 | (with-extensions (list guile-json-4) | ||
| 159 | (with-imported-modules '((gnu build dbus-service) | ||
| 160 | (gnu build marionette) | ||
| 161 | (guix base64)) | ||
| 162 | #~(begin | ||
| 163 | (use-modules (gnu build dbus-service) | ||
| 164 | (gnu build marionette) | ||
| 165 | (guix base64) | ||
| 166 | (json) | ||
| 167 | (rnrs base) | ||
| 168 | (rnrs bytevectors) | ||
| 169 | (srfi srfi-64) | ||
| 170 | (srfi srfi-71) | ||
| 171 | (web client) | ||
| 172 | (web response) | ||
| 173 | (web uri)) | ||
| 174 | |||
| 175 | (define marionette | ||
| 176 | (make-marionette (list #$vm))) | ||
| 177 | |||
| 178 | (test-runner-current (system-test-runner #$output)) | ||
| 179 | (test-begin "forgejo") | ||
| 180 | |||
| 181 | (unless (string=? "mysql" #$database-type) | ||
| 182 | (test-skip 2)) | ||
| 183 | (test-assert "wait for mysql socket" | ||
| 184 | ;; This can be removed after Shepherd gains systemd notify | ||
| 185 | ;; support (mysql uses it to notify when it's ready). | ||
| 186 | (wait-for-unix-socket | ||
| 187 | #$(forgejo-configuration-database-host forgejo-config) | ||
| 188 | marionette)) | ||
| 189 | (test-assert "mysql setup" | ||
| 190 | (marionette-eval | ||
| 191 | '(begin | ||
| 192 | (use-modules (guix build utils)) | ||
| 193 | (invoke "mysql" "-e" (string-append "\ | ||
| 194 | CREATE USER '" #$database-user "'@'localhost'; | ||
| 195 | CREATE DATABASE " #$database-name "; | ||
| 196 | GRANT ALL PRIVILEGES ON " #$database-name ".*" | ||
| 197 | "TO '" #$database-user "'@'localhost'; | ||
| 198 | FLUSH PRIVILEGES;"))) | ||
| 199 | marionette)) | ||
| 200 | |||
| 201 | (test-assert "forgejo can be restarted" | ||
| 202 | (marionette-eval | ||
| 203 | '(begin | ||
| 204 | (use-modules (gnu services herd)) | ||
| 205 | (restart-service 'forgejo)) | ||
| 206 | marionette)) | ||
| 207 | |||
| 208 | (test-assert "forgejo runs" | ||
| 209 | (marionette-eval | ||
| 210 | '(begin | ||
| 211 | (use-modules (gnu services herd)) | ||
| 212 | (start-service 'forgejo)) | ||
| 213 | marionette)) | ||
| 214 | |||
| 215 | (test-assert "shepherd listens on tcp port 3000" | ||
| 216 | (wait-for-tcp-port 3000 marionette)) | ||
| 217 | |||
| 218 | (test-assert "slogan can be retrieved from main page" | ||
| 219 | ;; This socket-activates Forgejo, so we must wait a bit while it | ||
| 220 | ;; becomes ready. | ||
| 221 | (with-retries 20 1 | ||
| 222 | (let (((values response body) | ||
| 223 | (http-get "http://localhost:3333"))) | ||
| 224 | (assert (= 200 (response-code response))) | ||
| 225 | (string-contains body "In Code We Trust")))) | ||
| 226 | |||
| 227 | (test-assert "create test forgejo user" | ||
| 228 | (marionette-eval | ||
| 229 | '(begin | ||
| 230 | (use-modules (guix build utils)) | ||
| 231 | (invoke "su" "-l" "forgejo" "-c" | ||
| 232 | "FORGEJO_WORK_DIR=/var/lib/forgejo forgejo \ | ||
| 233 | admin user create --username dummy --password dummy \ | ||
| 234 | --email dummy@localhost --must-change-password=false")) | ||
| 235 | marionette)) | ||
| 236 | |||
| 237 | (test-assert "upload ssh key for dummy forgejo user" | ||
| 238 | ;; We use the Forgejo API to get a token, then use it to set the | ||
| 239 | ;; SSH public key of the user, which is needed for | ||
| 240 | ;; non-interactively pushing to a repository. | ||
| 241 | (let (((values response body) | ||
| 242 | (http-post "http://localhost:3333/api/v1/user/keys" | ||
| 243 | #:headers | ||
| 244 | `((Accept . "application/json") | ||
| 245 | (Authorization | ||
| 246 | . ,(string-append | ||
| 247 | "Basic " (base64-encode | ||
| 248 | (string->utf8 "dummy:dummy")))) | ||
| 249 | (Content-Type . "application/json")) | ||
| 250 | #:body (string->utf8 | ||
| 251 | (scm->json-string | ||
| 252 | '(("key" . #$dummy-ssh-public-key) | ||
| 253 | ("read_only" . #t) | ||
| 254 | ("title" . "Dummy's SSH key"))))))) | ||
| 255 | (= 201 (response-code response)))) | ||
| 256 | |||
| 257 | (test-assert "configure git client for dummy user" | ||
| 258 | (marionette-eval | ||
| 259 | '(begin | ||
| 260 | (setenv "HOME" "/root") | ||
| 261 | (chdir "/root") | ||
| 262 | |||
| 263 | ;; Populate private SSH key. | ||
| 264 | (mkdir ".ssh") | ||
| 265 | (call-with-output-file ".ssh/id_ed25519" | ||
| 266 | (lambda (port) | ||
| 267 | (display #$dummy-ssh-private-key port))) | ||
| 268 | (chmod ".ssh/id_ed25519" #o700) | ||
| 269 | |||
| 270 | ;; To avoid interactive prompts. | ||
| 271 | (call-with-output-file ".ssh/config" | ||
| 272 | (lambda (port) | ||
| 273 | (display "StrictHostKeyChecking no\n" port))) | ||
| 274 | |||
| 275 | ;; Init git. | ||
| 276 | (invoke "git" "config" "--global" "user.name" "dummy") | ||
| 277 | (invoke "git" "config" "--global" "user.email" | ||
| 278 | "dummy@localhost")) | ||
| 279 | marionette)) | ||
| 280 | |||
| 281 | (test-assert "git create dummy local repo" | ||
| 282 | (marionette-eval | ||
| 283 | '(begin | ||
| 284 | (mkdir "dummy-repo") | ||
| 285 | (chdir "dummy-repo") | ||
| 286 | (invoke "git" "init") | ||
| 287 | (invoke "git" "remote" "add" "origin" | ||
| 288 | "forgejo@localhost:dummy/hello") ;SSH remote | ||
| 289 | (call-with-output-file "hello.txt" | ||
| 290 | (lambda (port) | ||
| 291 | (display "is anybody here?\n" port))) | ||
| 292 | (invoke "git" "add" "hello.txt") | ||
| 293 | (invoke "git" "commit" "-m" "init repo")) | ||
| 294 | marionette)) | ||
| 295 | |||
| 296 | (test-assert "git push repo to forgejo via ssh" | ||
| 297 | (marionette-eval | ||
| 298 | '(begin | ||
| 299 | (invoke "git" "push" "origin" "master")) | ||
| 300 | marionette)) | ||
| 301 | |||
| 302 | (test-assert "git clone repo from forgejo via http" | ||
| 303 | (marionette-eval | ||
| 304 | '(begin | ||
| 305 | (use-modules (ice-9 textual-ports)) | ||
| 306 | ;; FIXME: Switch back 127.0.0.1 to localhost after | ||
| 307 | ;; <https://codeberg.org/shepherd/shepherd/issues/122> is | ||
| 308 | ;; resolved. | ||
| 309 | (invoke "git" "clone" "http://127.0.0.1:3000/dummy/hello" | ||
| 310 | "/tmp/hello-copy") | ||
| 311 | (call-with-input-file "/tmp/hello-copy/hello.txt" | ||
| 312 | (lambda (port) | ||
| 313 | (string-contains (get-string-all port) | ||
| 314 | "is anybody here?")))) | ||
| 315 | marionette)) | ||
| 316 | |||
| 317 | (test-assert "setup git lfs" | ||
| 318 | (marionette-eval | ||
| 319 | '(begin | ||
| 320 | (invoke "git" "lfs" "install") | ||
| 321 | (invoke "git" "lfs" "track" "*.blob") | ||
| 322 | (invoke "git" "add" ".gitattributes")) | ||
| 323 | marionette)) | ||
| 324 | |||
| 325 | (test-assert "commit blob file with git lfs" | ||
| 326 | (marionette-eval | ||
| 327 | '(begin | ||
| 328 | (use-modules (ice-9 binary-ports) | ||
| 329 | (rnrs base) | ||
| 330 | ((scheme base) #:select (read-bytevector | ||
| 331 | write-bytevector))) | ||
| 332 | |||
| 333 | (call-with-output-file "one-mebibyte.blob" | ||
| 334 | (lambda (out) | ||
| 335 | (write-bytevector | ||
| 336 | (call-with-input-file "/dev/random" | ||
| 337 | (lambda (in) | ||
| 338 | (read-bytevector (expt 2 20) in)) | ||
| 339 | #:binary #t) | ||
| 340 | out)) | ||
| 341 | #:binary #t) | ||
| 342 | |||
| 343 | (invoke "git" "add" "one-mebibyte.blob") | ||
| 344 | (invoke "git" "commit" "-m" "add binary blob") | ||
| 345 | (zero? | ||
| 346 | (system "git lfs ls-files|grep -Fq one-mebibyte.blob"))) | ||
| 347 | marionette)) | ||
| 348 | |||
| 349 | (test-assert "push lfs tracked files to forgejo" | ||
| 350 | (marionette-eval | ||
| 351 | '(begin | ||
| 352 | (invoke "git" "push" "origin" "master")) | ||
| 353 | marionette)) | ||
| 354 | |||
| 355 | (test-assert "cloned repo contains lfs tracked files" | ||
| 356 | (marionette-eval | ||
| 357 | '(begin | ||
| 358 | ;; FIXME: Switch back 127.0.0.1 to localhost after | ||
| 359 | ;; <https://codeberg.org/shepherd/shepherd/issues/122> is | ||
| 360 | ;; resolved. | ||
| 361 | (invoke "git" "clone" "http://127.0.0.1:3000/dummy/hello" | ||
| 362 | "/tmp/hello-with-blob") | ||
| 363 | (= (expt 2 20) | ||
| 364 | (stat:size | ||
| 365 | (stat "/tmp/hello-with-blob/one-mebibyte.blob")))) | ||
| 366 | marionette)) | ||
| 367 | |||
| 368 | (test-assert "email notification works" | ||
| 369 | (begin | ||
| 370 | (let (((values response body) | ||
| 371 | (http-post | ||
| 372 | "http://localhost:3333/user/forgot_password" | ||
| 373 | #:headers `((Content-Type | ||
| 374 | . "application/x-www-form-urlencoded")) | ||
| 375 | #:body (string->utf8 | ||
| 376 | (string-append | ||
| 377 | "email=" (uri-encode "dummy@localhost")))))) | ||
| 378 | (assert (= 200 (response-code response)))) | ||
| 379 | |||
| 380 | (with-retries 10 1 | ||
| 381 | (marionette-eval | ||
| 382 | '(begin | ||
| 383 | (use-modules (ice-9 textual-ports)) | ||
| 384 | (string-contains (call-with-input-file | ||
| 385 | "/var/log/forgejo.log" | ||
| 386 | get-string-all) | ||
| 387 | "Subject: Recover your account")) | ||
| 388 | marionette)))) | ||
| 389 | |||
| 390 | (test-end))))) | ||
| 391 | |||
| 392 | (gexp->derivation (string-append "forgejo-test-" name) test)) | ||
| 393 | |||
| 394 | (define %test-forgejo | ||
| 395 | (system-test | ||
| 396 | (name "forgejo") | ||
| 397 | (description "Basic tests for the Forgejo service.") | ||
| 398 | (value (make-forgejo-test "sqlite")))) | ||
| 399 | |||
| 400 | (define %test-forgejo-mysql | ||
| 401 | (system-test | ||
| 402 | (name "forgejo-mysql") | ||
| 403 | (description "Basic tests for the Forgejo service, using a MySQL | ||
| 404 | database.") | ||
| 405 | (value (make-forgejo-test "mysql" #:os %forgejo-os/mysql)))) | ||
| 406 | |||
| 407 | (define %test-forgejo-postgres | ||
| 408 | (system-test | ||
| 409 | (name "forgejo-postgres") | ||
| 410 | (description "Basic tests for the Forgejo service, using a PostgreSQL | ||
| 411 | database.") | ||
| 412 | (value (make-forgejo-test "postgres" #:os %forgejo-os/postgres)))) | ||
| 413 | |||
| 414 | ;; Local Variables: | ||
| 415 | ;; eval: (put 'with-retries 'scheme-indent-function 2) | ||
| 416 | ;; End: | ||
