+(* 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
+
+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 =
+ 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/<package>-<branch>
+ *)
+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 5 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 5 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)
+ )