(* This goal script is responsible for: * - testing each new commit to the libguestfs source repo * - checking for new upstream releases of libguestfs * - testing new upstream releases * - packaging them as a source tarball * - testing the source tarball on a variety of systems * - if all the above works, uploading the external website * Note this doesn't build the Fedora releases. See 'libguestfs_fedora.ml'. *) open Goaljobs open Printf open Config (* Enable debugging. *) let () = Unix.putenv "LIBGUESTFS_DEBUG" "1"; Unix.putenv "LIBGUESTFS_TRACE" "1" (* Log program output. *) let from = "rjones@redhat.com" let to_ = "rjones@redhat.com" let logfile = log_program_output () let () = eprintf "logging to %s\n%!" logfile let package = "libguestfs" (* Helper object which stores everything about a version. *) type info = { version : string; (* The version as a normal string. *) major : int; (* Broken-out version fields. *) minor : int; release: int; is_stable : bool; (* is a stable version of libguestfs? *) branch : string; (* 'master' or 'stable-1.xx' *) package_version : string; (* package-version *) tarball : string; (* package-version.tar.gz *) urlpath : string; (* download/1.X-(stable|development)/tarball *) url : string; (* full download URL of tarball *) } (* Helper: Fetch latest gnulib into $buildtmp/repos/gnulib * XXX Move to Gnulib module. *) let get_gnulib () = sh " cd %s/repos if [ ! -d gnulib ]; then git clone git://git.sv.gnu.org/gnulib.git; fi cd gnulib git checkout --force master git pull " buildtmp (* Goal: the website has been updated to 'version'. *) let rec goal website_updated version = target (url_exists version.url); require (tarball_created version); require (tarball_tested version); (* We only update the website for the development releases. *) if not version.is_stable then require (website_built version); require (website_cvs_checked_in version); require (website_rsync_done version) (* Goal: website has been rsync'd. *) and website_rsync_done version = let key = sprintf "libguestfs_website_rsync_done_%s" version.version in target (memory_exists key); sh " cd %s echo NOT RUNNING: . .rsync " libguestfs_website_cvs; memory_set key "1" (* Goal: Tarball added to CVS and CVS checked in. *) and website_cvs_checked_in version = let key = sprintf "libguestfs_website_cvs_checked_in_%s" version.version in target (memory_exists key); require (tarball_created version); require (tarball_tested version); sh " cd %s cp %s/tarballs/%s %s echo NOT RUNNING: cvs add -kb %s echo NOT RUNNING: cvs ci -m \"Version %s\" " libguestfs_website_cvs buildtmp version.tarball version.urlpath version.urlpath version.version (* Goal: website (local copy) has been built. *) and website_built version = let index_file = sprintf "%s/index.html" libguestfs_website_cvs in target (file_contains_string index_file version.version); require (tarball_created version); require (tarball_tested version); (* We should only update the website on development releases. *) assert (not version.is_stable); sh " tar zxf %s/tarballs/%s cd %s echo %s > localconfigure chmod +x localconfigure echo %s > localenv ./localconfigure make make website " buildtmp version.tarball version.package_version (quote (libguestfs_localconfigure `Tarball)) (quote libguestfs_localenv) (* Goal: the tarball has passed the required set of tests before * a release is allowed. *) and tarball_tested version = let key = sprintf "libguestfs_tarball_tested_%s" version.version in target (memory_exists key); require (tarball_created version); sh " tar zxf %s/tarballs/%s cd %s echo %s > localconfigure chmod +x localconfigure echo %s > localenv ./localconfigure make make check-release " buildtmp version.tarball version.package_version (quote (libguestfs_localconfigure `Tarball)) (quote libguestfs_localenv) (* Goal: the tarball has been created from git. *) and tarball_created version = let filename = sprintf "%s/tarballs/%s" buildtmp version.tarball in target (file_exists filename); let repodir = sprintf "%s/repos/%s-%s" buildtmp package version.branch in require (directory_exists repodir); sh " cp -a %s libguestfs cd libguestfs git reset --hard %s echo %s > localconfigure chmod +x localconfigure echo %s > localenv ./localconfigure make make dist mv %s %s/tarballs/%s " repodir version.version (quote (libguestfs_localconfigure `Git)) (quote libguestfs_localenv) version.tarball buildtmp version.tarball (* Goal: test a commit. *) and commit_tested branch commit = onfail ( fun _ -> let subject = sprintf "goal: %s: FAILED" goalname in mailto ~from ~subject ~attach:[logfile] to_ ); let key = sprintf "libguestfs_commit_tested_%s" commit in target (memory_exists key); let repodir = sprintf "%s/repos/%s-%s" buildtmp package branch in require (directory_exists repodir); sh " cp -a %s libguestfs cd libguestfs git reset --hard %s echo %s > localconfigure chmod +x localconfigure echo %s > localenv ./localconfigure make make check-release " repodir commit (quote (libguestfs_localconfigure `Git)) (quote libguestfs_localenv); memory_set key "1" (* Helper function to make a full 'info' object from a version * number. *) let vernames version = Scanf.sscanf version "%d.%d.%d" ( fun major minor release -> let is_stable = minor mod 2 = 0 in let branch = if is_stable then sprintf "stable-%d.%d" major minor else sprintf "master" in let package_version = sprintf "%s-%d.%d.%d" package major minor release in let tarball = sprintf "%s.tar.gz" package_version in let urlpath = if is_stable then sprintf "download/%d.%d-stable/%s" major minor tarball else sprintf "download/%d.%d-development/%s" major minor tarball in let url = "http://libguestfs.org/" ^ urlpath in { version = version; major = major; minor = minor; release = release; is_stable = is_stable; branch = branch; package_version = package_version; tarball = tarball; urlpath = urlpath; url = url } ) (* Helper function to read the latest version in a repo and return * the version. *) let git_latest_version branch = let v = shout " cd %s/repos/%s-%s git describe --tags --abbrev=0 " buildtmp package (quote branch) in vernames v (* Get the latest commit. *) let git_latest_commit branch = shout " cd %s/repos/%s-%s git rev-parse HEAD " buildtmp package (quote branch) (* Clone or update a repo to the latest version on a branch, by force. * It is cached in name = $buildtmp/repos/- *) let git_force url branch = sh " cd %s/repos if [ ! -d %s-%s ]; then git clone %s %s-%s; fi cd %s-%s git checkout --force %s git pull # Copy or update gnulib git submodule init git submodule update " buildtmp package (quote branch) (quote url) package (quote branch) package (quote branch) (quote branch) let () = (* Add a periodic job to check for new git commits and test them. *) every libguestfs_query_mins minutes ~name:"new libguestfs commit" ( fun () -> git_force "https://github.com/libguestfs/libguestfs.git" "master"; let commit = git_latest_commit "master" in require (commit_tested "master" commit); ); (* Periodic job to build new tarballs. *) every libguestfs_query_mins minutes ~name:"new libguestfs version" ( fun () -> git_force "https://github.com/libguestfs/libguestfs.git" "master"; let version = git_latest_version "master" in require (website_updated version) )