#!/bin/sh # -*- scheme -*- # @configure_input@ #GUILE_LOAD_PATH="@PACKAGE_LOAD_PATH@${GUILE_LOAD_PATH:+:}$GUILE_LOAD_PATH" #GUILE_LOAD_COMPILED_PATH="@PACKAGE_LOAD_COMPILED_PATH@${GUILE_LOAD_COMPILED_PATH:+:}$GUILE_LOAD_COMPILED_PATH" exec ${GUILE:-@GUILE@} --no-auto-compile -e main -s "$0" "$@" !# ;;;; cuirass -- continuous integration tool ;;; Copyright © 2016 Mathieu Lirzin ;;; Copyright © 2017 Mathieu Othacehe ;;; ;;; This file is part of Cuirass. ;;; ;;; Cuirass is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation, either version 3 of the License, or ;;; (at your option) any later version. ;;; ;;; Cuirass is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with Cuirass. If not, see . (use-modules (cuirass) (cuirass ui) (cuirass logging) (guix ui) (fibers) (fibers channels) (ice-9 getopt-long)) (define (show-help) (format #t "Usage: ~a [OPTIONS]~%" (%program-name)) (display "Run build jobs from internal database. --one-shot Evaluate and build jobs only once --cache-directory=DIR Use DIR for storing repository data --fallback Fall back to building when the substituter fails. -L --load-path=DIR Prepend DIR to Guix package module search path. -S --specifications=SPECFILE Add specifications from SPECFILE to database. -D --database=DB Use DB to store build results. -p --port=NUM Port of the HTTP server. --listen=HOST Listen on the network interface for HOST -I, --interval=N Wait N seconds between each poll --use-substitutes Allow usage of pre-built substitutes -V, --version Display version -h, --help Display this help message") (newline) (show-package-information)) (define %options '((one-shot (value #f)) (cache-directory (value #t)) (load-path (single-char #\L) (value #t)) (specifications (single-char #\S) (value #t)) (database (single-char #\D) (value #t)) (port (single-char #\p) (value #t)) (listen (value #t)) (interval (single-char #\I) (value #t)) (use-substitutes (value #f)) (fallback (value #f)) (version (single-char #\V) (value #f)) (help (single-char #\h) (value #f)))) ;;; ;;; Entry point. ;;; (define* (main #:optional (args (command-line))) (let ((opts (getopt-long args %options))) (parameterize ((%program-name (car args)) (%package-database (option-ref opts 'database (%package-database))) (%package-cachedir (option-ref opts 'cache-directory (%package-cachedir))) (%guix-package-path (option-ref opts 'load-path (%guix-package-path))) (%use-substitutes? (option-ref opts 'use-substitutes #f)) (%fallback? (option-ref opts 'fallback #f))) (cond ((option-ref opts 'help #f) (show-help) (exit 0)) ((option-ref opts 'version #f) (show-version) (exit 0)) (else (let ((one-shot? (option-ref opts 'one-shot #f)) (port (string->number (option-ref opts 'port "8080"))) (host (option-ref opts 'listen "localhost")) (interval (string->number (option-ref opts 'interval "300"))) (specfile (option-ref opts 'specifications #f))) (prepare-git) (run-fibers (lambda () (with-database db (and specfile (let ((new-specs (save-module-excursion (lambda () (set-current-module (make-user-module '())) (primitive-load specfile))))) (for-each (lambda (spec) (db-add-specification db spec)) new-specs))) (if one-shot? (process-specs db (db-get-specifications db)) (let ((exit-channel (make-channel)) (pending (begin (log-message "retrieving list of pending builds...") (db-get-builds db '((status pending)))))) ;; First off, restart builds that had not completed or ;; were not even started on a previous run. (spawn-fiber (lambda () (with-database db (restart-builds db pending)))) (spawn-fiber (lambda () (catch #t (lambda () (with-database db (while #t (process-specs db (db-get-specifications db)) (log-message "sleeping for ~a seconds" interval) (sleep interval)))) (lambda (key . args) ;; If something goes wrong in this fiber, we have ;; a problem, so stop everything. (log-message "uncaught exception in main fiber!") (false-if-exception (let ((stack (make-stack #t))) (display-backtrace stack (current-error-port)) (print-exception (current-error-port) (stack-ref stack 0) key args))) (put-message exit-channel 1))))) (spawn-fiber (lambda () (with-database db (run-cuirass-server db #:host host #:port port)))) (primitive-exit (get-message exit-channel)))))) ;; Most of our code is I/O so preemption doesn't matter much (it ;; could help while we're doing SQL requests, for instance, but it ;; doesn't actually help since these are non-resumable ;; continuations.) Thus, reduce the tick rate. #:hz 10 #:drain? #t)))))))