This hasn't been used in a long time (Guix uses its own CI system), and it probably doesn't work anymore.
(cherry picked from commit 23c9ca3e94669087d463642baea0cf35a0b8d72f)
QGLBQ5IOVSMBQRXXHO4LOJG4A7V3HSUZESCP2N235A7L4VVOBKCQC SVDJSA6U3T3WMJHXZ24IB7HJYDN2XG35DWGDS2FV6CR2Y3YKRFEAC UL6TSQEAQ36LH5U4FTXROJYVPG3BFZZ2H6XUZRK2HJRZA545A5YAC 3K3GDTUQ3MGTU6F5MTT5YVTDMNTSJIU5K2T344DMR4Y53PJQC6FQC YHDX3LB65VVAVCLK7BKQCSWRT54Q3RWTPFMFHTUSCQD7D7VCJ2KQC 3HVZCXJR6DHPOGJ4YCGHQUNHTPPC6D2QEFRLKRJIISAYATKJMRIQC UXRNODRJJU7A33F4PG24WOHKTJFI3XQMZGT2MUOBRAH2MPQ7NZ2AC ICYJNJWHY6KBNLM2EMSW7VJ35OIOHN26JO3FG32VYTKNLFNZAREQC STZE4KKRL2AGCPP2FOMBNZHJTRTKJQZSEKALWEV6FK5BII6H7EDAC HP5WJLQUNP7PXGVBYOMWRCZ4QKDECULS2EAFX2FPHRUXV2CMMYCAC GBCPEGYCLFC5FUNAK2BV47G3EGQ26TPXSFCKVCY23QYET7A5A5YAC Y6H7Y3OTXVLF6PJ5BR6WXS7KVS4VMTUKRYVM6FALKMY3DCBYEJSQC KNLKTCDMQNYJ2Y4B7PDQ4WLZUSYKU4VV74YDCDJH5OBCYGP7W4VQC 2KJFOYGSVN3TYHG7YCXJLNYMHCVY7E6LYV4QPRTUSJLJCRGKF7HAC FV2M6MOTAP4BJMEKU5XUDVEACWEJGEIRCCE2MRY3F6SF2SFOE3MQC M3A5PZIHA3LDVTBTKGTLCYGJSMNJOFXNO5GBPAUDHO5XGHLKYYPQC QMW24O5S43MYF5ZTBULUEZNDW2FKJ3QP2GL46P6B2SVGSQLVEACAC FAIJDQKZH6SUUNCKW5RIOZ37YRAO5ACS6FX76MHRNN53LDBWO6ZQC NNQ7IQJXKU6EBW45T3EHYDLC7GY5CYSZJKC3IGOWNUW22MYD5ORQC T4LLYESZ2HUXSLKZ6GNBLVWUVG7R5IDFHYHYO773QIZ6QTOOXR2AC ODNCGFQ5FPKFI624BVMLW7PJ2EFJOR3TY66OCZM42UNNTWBCF2TQC 3HZY24CX4U2TO74HOY4YX3LBJIYF4DLXHCIY7J2RASAC4COMSMZAC LZVO64YG43JD7YMZSCTZNOBS5ROZA4FMPKJW2YOMHX2V5PTGBVWQC CQTN62OHT4DY35E2MJEG7GFTVNEE5KRDMV6ASBQLBHN7BUDK7WHAC D5QIOJGPKQJIYBUCSC3MFJ3TXLPNZ2XMI37GXMFRVRFWWR2VMTFAC VML3XVFYL57QICENFGVPB4SMHUQX2IOJVDZIDRK5KGS657SKQVWAC W2VB36NMID2UYEJB5THOAYYNJEQ42WIF2K7IRXEUYMNTI2AHFYTAC HXS5NUHWFIQSEX6HEKVOBX62IZV5OV4HFTVDRMMQBNM4GXMF4WKQC IS7GUIWYGOHEOYMOULIRE45MG7FFSBDN2MYDPKLGZ6PIQ5X4F5XQC DBPIYHMAHIV2ENFEWE474K5LV27WAHMR3ZZ5HF6FM7YVDM3MK4HQC VU2OLHD246DFWL2WPFSKWPLXTN3WRL25TSRU4PJMJBNWDF35OFRAC N22GPKYTOLZLBGTGDATQDVZ4R5APZEAOIA7L32X4UXBH4XNI7MWAC FDE3BJAPDEP3BYT5A5GEGLNXPPZLA2KTGXB4ZNYRP4LJ7IFRKYXAC 5SHCWE7XPQORSOLY7HGAIK2ODKBFPY4KVXRL2W7X6D4WALU544HQC MPFSVI5XLGXVPJP5OJXMT7CF2SFFFFT6R36O74MJB5TF6474E54AC IMQRX4MPANNOXDP6THT2FA4576CDFY44LGNCS74BHV6DWLOCXQOQC NS7SND6RF6X3CVSVP7MLAQQZFA64E63YKFFABPEAGEPHX6PNWBOQC RFE6T5LGBFFNEPHZOPF4UNMFC2L4CGD5TPAMOXDLRPH3TZJ43UBAC # When the expression is in a .scm file, assume it's a Guile + Guix# build expression.my $exprType =$c->stash->{params}->{"nixexprpath"} =~ /.scm$/ ? "guile" : "nix";
#!/bin/sh# Aside from this initial boilerplate, this is actually -*- scheme -*- code.main="(module-ref (resolve-interface '(hydra-eval-guile-jobs)) 'eval-guile-jobs)"# Keep the host's GUILE_LOAD_PATH unchanged to allow the installed Guix to# be used. This moves Guix modules possibly out of control, but solves# bootstrapping issues.## Use `--fresh-auto-compile' to ignore any available .go, and force# recompilation. This is because checkouts in the store has mtime set to# the epoch, and thus .go files look newer, even though they may not# correspond.exec ${GUILE:-@GUILE@} --no-auto-compile --fresh-auto-compile \-l "$0" -c "(apply $main (cdr (command-line)))" "$@"!#;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>;;;;;; This file is part of Hydra.;;;;;; Hydra 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.;;;;;; Hydra 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 Hydra. If not, see <http://www.gnu.org/licenses/>.(define-module (hydra-eval-guile-jobs)#:use-module (sxml simple)#:use-module (ice-9 match)#:use-module (ice-9 regex)#:use-module (srfi srfi-1)#:use-module (srfi srfi-11)#:export (job-evaluations->xmleval-guile-jobs))(define (guix-variable module name)"Dynamically link variable NAME under Guix module MODULE and return it.Note: this is used instead of `@', because when using `@' in an uncompiledfile, Guile tries to load the module directly as it reads the source, whichfails in our case, leading to the creation of empty (guix ...) modules.";; TODO: fail with an XML error description(let ((m (resolve-interface `(guix ,module))))(module-ref m name)))(define (%derivation-system drv);; XXX: Awful hack to workaround the fact that `derivation-system', which;; is a macro, cannot be referred to dynamically.(struct-ref drv 3))(define strip-store-path(let* ((store (or (getenv "NIX_STORE_DIR") "/nix/store"))(store-path-rx(make-regexp (string-append "^.*" (regexp-quote store)"/[^-]+-(.+)$"))))(lambda (path)(or (and=> (regexp-exec store-path-rx path)(lambda (match)(let ((path (match:substring match 1)))path)))path))))(define (derivation-path->name drv)"Return the base name of DRV, sans hash and `.drv' extension."(let ((d (strip-store-path drv)))(if (string-suffix? ".drv" d)(string-drop-right d 4)d)))(define (register-gc-root drv roots-dir)"Register a permanent garbage collector root under ROOTS-DIR for DRV."(let ((root (string-append roots-dir "/" (basename drv))))(unless (file-exists? root)(symlink drv root))))(define* (job-evaluations->sxml jobs#:key gc-roots-dir)"Return the hydra-eval-jobs SXML form for the result of JOBS, a list ofsymbol/thunk pairs."`(*TOP*(*PI* xml "version='1.0' encoding='utf-8'")"\n"(jobs "\n",@(map (match-lambda(((? symbol? name) . (? thunk? thunk))(let* ((result (save-module-excursion(lambda ()(set-current-module %user-module)(with-output-to-port (%make-void-port "w")thunk))))(drv (assoc-ref result 'derivation)))(define (opt-attr xml-name name)(match (assoc name result)((_ . value)`((,xml-name ,value)))(_'())));; XXX: Add <arg ...> tags?`(job (@ (jobName ,name)(drvPath ,drv),@(opt-attr 'homepage 'home-page)(license,(let loop ((license (assoc-ref result 'license)))(match license((? struct?)(struct-ref license 0))((l ...)(string-join (map loop l)))(_ "")))),@(opt-attr 'description 'description)(maintainers,(string-join (or (assoc-ref result 'maintainers)'())", "))(maxSilent,(number->string (or (assoc-ref result'max-silent-time)3600)))(timeout,(number->string (or (assoc-ref result 'timeout)72000)))(nixName ,(derivation-path->name drv))(schedulingPriority,(number->string (or (assoc-ref result'scheduling-priority)10)))(system,(call-with-input-file drv(compose %derivation-system(guix-variable 'derivations'read-derivation)))))"\n"))))jobs))))(define* (job-evaluations->xml jobs port#:key gc-roots-dir)(set-port-encoding! port "UTF-8")(sxml->xml (job-evaluations->sxml jobs #:gc-roots-dir gc-roots-dir)port));;;;;; Command-line entry point.;;;(define (parse-arguments args)"Traverse ARGS, a list of command-line arguments compatible with`hydra-eval-jobs', and return the name of the file that defines the jobs, anexpression that returns the entry point in that file (a unary procedure), thelist of name/value pairs passed to that entry point, as well as a GC rootdirectory or #f."(define (module-directory dir)(let ((d (string-append dir "/share/guile/site/2.0")))(if (file-exists? d)ddir)))(let loop ((args args)(result '())(file #f)(entry 'hydra-jobs)(roots-dir #f))(match args(()(if (not file)(error "hydra-eval-guile-jobs: no expression file given")(values file entry (reverse result) roots-dir)))(("-I" name=dir rest ...)(let* ((dir (match (string-tokenize name=dir(char-set-complement (char-set#\=)))((_ dir) dir)((dir) dir)))(dir* (module-directory dir)))(format (current-error-port) "adding `~a' to the load path~%" dir*)(set! %load-path (cons dir* %load-path))(set! %load-compiled-path (cons dir* %load-compiled-path)))(loop rest result file entry roots-dir))(("--argstr" name value rest ...)(loop rest (alist-cons (string->symbol name) value result)file entry roots-dir))(("--arg" name expr rest ...)(let ((value (eval (call-with-input-string expr read)(current-module))))(loop rest (alist-cons (string->symbol name) value result)file entry roots-dir)))(("--gc-roots-dir" dir rest ...)(loop rest result file entry dir))(("-j" _ rest ...) ; XXX: what's this?(loop rest result file entry roots-dir))(("--entry" expr rest ...) ; entry point, like `guile -e'(let ((expr (call-with-input-string expr read)))(loop rest result file expr roots-dir)))((file rest ...) ; source file that defines the jobs(loop rest result file entry roots-dir))(_(error "hydra-eval-guile-jobs: invalid arguments" args)))))(define %user-module;; Hydra user module.;; TODO: Make it a sandbox.(let ((m (make-module)))(beautify-user-module! m)m))(define (eval-guile-jobs . args)(setlocale LC_ALL "")(let-values (((file entry args gc-roots-dir)(parse-arguments args)))(save-module-excursion(lambda ()(set-current-module %user-module);; The standard output must contain only XML.(with-output-to-port (%make-void-port "w")(lambda ()(primitive-load file)))))(let* ((entry (eval entry %user-module))(store ((guix-variable 'store 'open-connection)))(jobs (entry store args)))(unless (string? gc-roots-dir)(format (current-error-port)"warning: --gc-roots-dir not specified~%"))(job-evaluations->xml jobs (current-output-port)#:gc-roots-dir gc-roots-dir))));; Resolve Guix modules lazily.,(map (match-lambda((name . path)`(output (@ (name ,name) (path ,path)))))((guix-variable 'derivations'derivation-path->output-paths)drv))(when gc-roots-dir;; Register DRV as a GC root so that it's not collected by;; the time 'hydra-queue-runner' attempts to build it.(register-gc-root drv gc-roots-dir))
my ($exprType, $input) = @_;my $result;if ($exprType eq "guile") {$result = "'((file-name . \"" . ${input}->{storePath} . "\")" .(defined $input->{revision} ? "(revision . \"" . $input->{revision} . "\")" : "") .(defined $input->{revCount} ? "(revision-count . " . $input->{revCount} . ")" : "") .(defined $input->{gitTag} ? "(git-tag . \"" . $input->{gitTag} . "\")" : "") .(defined $input->{shortRev} ? "(short-revision . \"" . $input->{shortRev} . "\")" : "") .(defined $input->{version} ? "(version . \"" . $input->{version} . "\")" : "") .")";} else {$result = "{ outPath = builtins.storePath " . $input->{storePath} . "" ."; inputType = \"" . $input->{type} . "\"" .(defined $input->{uri} ? "; uri = \"" . $input->{uri} . "\"" : "") .(defined $input->{revNumber} ? "; rev = " . $input->{revNumber} . "" : "") .(defined $input->{revision} ? "; rev = \"" . $input->{revision} . "\"" : "") .(defined $input->{revCount} ? "; revCount = " . $input->{revCount} . "" : "") .(defined $input->{gitTag} ? "; gitTag = \"" . $input->{gitTag} . "\"" : "") .(defined $input->{shortRev} ? "; shortRev = \"" . $input->{shortRev} . "\"" : "") .(defined $input->{version} ? "; version = \"" . $input->{version} . "\"" : "") .(defined $input->{outputName} ? "; outputName = \"" . $input->{outputName} . "\"" : "") .(defined $input->{drvPath} ? "; drvPath = builtins.storePath " . $input->{drvPath} . "" : "") .";}";}return $result;
my ($input) = @_;return"{ outPath = builtins.storePath " . $input->{storePath} . "" ."; inputType = \"" . $input->{type} . "\"" .(defined $input->{uri} ? "; uri = \"" . $input->{uri} . "\"" : "") .(defined $input->{revNumber} ? "; rev = " . $input->{revNumber} . "" : "") .(defined $input->{revision} ? "; rev = \"" . $input->{revision} . "\"" : "") .(defined $input->{revCount} ? "; revCount = " . $input->{revCount} . "" : "") .(defined $input->{gitTag} ? "; gitTag = \"" . $input->{gitTag} . "\"" : "") .(defined $input->{shortRev} ? "; shortRev = \"" . $input->{shortRev} . "\"" : "") .(defined $input->{version} ? "; version = \"" . $input->{version} . "\"" : "") .(defined $input->{outputName} ? "; outputName = \"" . $input->{outputName} . "\"" : "") .(defined $input->{drvPath} ? "; drvPath = builtins.storePath " . $input->{drvPath} . "" : "") .";}";
my ($jobs, $nixExprInput) = evalJobs($inputInfo, $exprType, $jobset->nixexprinput, $jobset->nixexprpath);
my ($jobs, $nixExprInput) = evalJobs($inputInfo, $jobset->nixexprinput, $jobset->nixexprpath);