libguestfs: Enable debugging.
[goaljobs-goals.git] / libguestfs_upstream.ml
1 (* This goal script is responsible for:
2  *  - testing each new commit to the libguestfs source repo
3  *  - checking for new upstream releases of libguestfs
4  *  - testing new upstream releases
5  *  - packaging them as a source tarball
6  *  - testing the source tarball on a variety of systems
7  *  - if all the above works, uploading the external website
8  * Note this doesn't build the Fedora releases.  See 'libguestfs_fedora.ml'.
9  *)
10
11 open Goaljobs
12 open Printf
13 open Config
14
15 (* Enable debugging. *)
16 let () =
17   Unix.putenv "LIBGUESTFS_DEBUG" "1";
18   Unix.putenv "LIBGUESTFS_TRACE" "1"
19
20 let package = "libguestfs"
21
22 (* Helper object which stores everything about a version. *)
23 type info = {
24   version : string;              (* The version as a normal string. *)
25   major : int;                   (* Broken-out version fields. *)
26   minor : int;
27   release: int;
28   is_stable : bool;              (* is a stable version of libguestfs? *)
29   branch : string;               (* 'master' or 'stable-1.xx' *)
30   package_version : string;      (* package-version *)
31   tarball : string;              (* package-version.tar.gz *)
32   urlpath : string;              (* download/1.X-(stable|development)/tarball *)
33   url : string;                  (* full download URL of tarball *)
34 }
35
36 (* Helper: Fetch latest gnulib into $buildtmp/repos/gnulib
37  * XXX Move to Gnulib module.
38  *)
39 let get_gnulib () =
40   sh "
41     cd %s/repos
42     if [ ! -d gnulib ]; then git clone git://git.sv.gnu.org/gnulib.git; fi
43     cd gnulib
44     git checkout --force master
45     git pull
46   " buildtmp
47
48 (* Goal: the website has been updated to 'version'. *)
49 let rec goal website_updated version =
50   target (url_exists version.url);
51
52   require (tarball_created version);
53   require (tarball_tested version);
54
55   (* We only update the website for the development releases. *)
56   if not version.is_stable then
57     require (website_built version);
58
59   require (website_cvs_checked_in version);
60   require (website_rsync_done version)
61
62 (* Goal: website has been rsync'd. *)
63 and website_rsync_done version =
64   let key = sprintf "libguestfs_website_rsync_done_%s" version.version in
65   target (memory_exists key);
66
67   sh "
68     cd %s
69     echo NOT RUNNING: . .rsync
70   " libguestfs_website_cvs;
71   memory_set key "1"
72
73 (* Goal: Tarball added to CVS and CVS checked in. *)
74 and website_cvs_checked_in version =
75   let key = sprintf "libguestfs_website_cvs_checked_in_%s" version.version in
76   target (memory_exists key);
77
78   require (tarball_created version);
79   require (tarball_tested version);
80
81   sh "
82     cd %s
83     cp %s/tarballs/%s %s
84     echo NOT RUNNING: cvs add -kb %s
85     echo NOT RUNNING: cvs ci -m \"Version %s\"
86   " libguestfs_website_cvs
87     buildtmp version.tarball version.urlpath
88     version.urlpath
89     version.version
90
91 (* Goal: website (local copy) has been built. *)
92 and website_built version =
93   let index_file = sprintf "%s/index.html" libguestfs_website_cvs in
94   target (file_contains_string index_file version.version);
95
96   require (tarball_created version);
97   require (tarball_tested version);
98
99   (* We should only update the website on development releases. *)
100   assert (not version.is_stable);
101
102   sh "
103     tar zxf %s/tarballs/%s
104     cd %s
105     echo %s > localconfigure
106     chmod +x localconfigure
107     echo %s > localenv .
108     ./localconfigure
109     make
110     make website
111   " buildtmp version.tarball
112     version.package_version
113     (quote (libguestfs_localconfigure `Tarball))
114     (quote libguestfs_localenv)
115
116 (* Goal: the tarball has passed the required set of tests before
117  * a release is allowed.
118  *)
119 and tarball_tested version =
120   let key = sprintf "libguestfs_tarball_tested_%s" version.version in
121   target (memory_exists key);
122
123   require (tarball_created version);
124
125   sh "
126     tar zxf %s/tarballs/%s
127     cd %s
128     echo %s > localconfigure
129     chmod +x localconfigure
130     echo %s > localenv .
131     ./localconfigure
132     make
133     make check-release
134   " buildtmp version.tarball
135     version.package_version
136     (quote (libguestfs_localconfigure `Tarball))
137     (quote libguestfs_localenv)
138
139 (* Goal: the tarball has been created from git. *)
140 and tarball_created version =
141   let filename = sprintf "%s/tarballs/%s" buildtmp version.tarball in
142   target (file_exists filename);
143
144   let repodir = sprintf "%s/repos/%s-%s" buildtmp package version.branch in
145   require (directory_exists repodir);
146
147   sh "
148     cp -a %s libguestfs
149     cd libguestfs
150     git reset --hard %s
151
152     echo %s > localconfigure
153     chmod +x localconfigure
154     echo %s > localenv .
155
156     ./localconfigure
157     make
158     make dist
159     mv %s %s/tarballs/%s
160   " repodir
161     version.version
162     (quote (libguestfs_localconfigure `Git))
163     (quote libguestfs_localenv)
164     version.tarball buildtmp version.tarball
165
166 (* Goal: test a commit. *)
167 and commit_tested branch commit =
168   let key = sprintf "libguestfs_commit_tested_%s" commit in
169   target (memory_exists key);
170
171   let repodir = sprintf "%s/repos/%s-%s" buildtmp package branch in
172   require (directory_exists repodir);
173
174   sh "
175     cp -a %s libguestfs
176     cd libguestfs
177     git reset --hard %s
178
179     echo %s > localconfigure
180     chmod +x localconfigure
181     echo %s > localenv
182
183     ./localconfigure
184     make
185     make check-release
186   " repodir
187     commit
188     (quote (libguestfs_localconfigure `Git))
189     (quote libguestfs_localenv);
190
191   memory_set key "1"
192
193 (* Helper function to make a full 'info' object from a version
194  * number.
195  *)
196 let vernames version =
197   Scanf.sscanf version "%d.%d.%d" (
198     fun major minor release ->
199       let is_stable = minor mod 2 = 0 in
200       let branch =
201         if is_stable then
202           sprintf "stable-%d.%d" major minor
203         else
204           sprintf "master" in
205       let package_version = sprintf "%s-%d.%d.%d" package major minor release in
206       let tarball = sprintf "%s.tar.gz" package_version in
207       let urlpath =
208         if is_stable then
209           sprintf "download/%d.%d-stable/%s" major minor tarball
210         else
211           sprintf "download/%d.%d-development/%s" major minor tarball in
212       let url = "http://libguestfs.org/" ^ urlpath in
213       { version = version;
214         major = major; minor = minor; release = release;
215         is_stable = is_stable;
216         branch = branch;
217         package_version = package_version;
218         tarball = tarball;
219         urlpath = urlpath;
220         url = url }
221   )
222
223 (* Helper function to read the latest version in a repo and return
224  * the version.
225  *)
226 let git_latest_version branch =
227   let v = shout "
228     cd %s/repos/%s-%s
229     git describe --tags --abbrev=0
230   " buildtmp package (quote branch) in
231   vernames v
232
233 (* Get the latest commit. *)
234 let git_latest_commit branch =
235   shout "
236     cd %s/repos/%s-%s
237     git rev-parse HEAD
238   " buildtmp package (quote branch)
239
240 (* Clone or update a repo to the latest version on a branch, by force.
241  * It is cached in name = $buildtmp/repos/<package>-<branch>
242  *)
243 let git_force url branch =
244   sh "
245     cd %s/repos
246     if [ ! -d %s-%s ]; then git clone %s %s-%s; fi
247     cd %s-%s
248     git checkout --force %s
249     git pull
250     # Copy or update gnulib
251     git submodule init
252     git submodule update
253   " buildtmp
254     package (quote branch) (quote url) package (quote branch)
255     package (quote branch)
256     (quote branch)
257
258 let () =
259   (* Add a periodic job to check for new git commits and test them. *)
260   every libguestfs_query_mins minutes ~name:"new libguestfs commit" (
261     fun () ->
262       git_force "https://github.com/libguestfs/libguestfs.git" "master";
263
264       let commit = git_latest_commit "master" in
265       require (commit_tested "master" commit);
266   );
267
268   (* Periodic job to build new tarballs. *)
269   every libguestfs_query_mins minutes ~name:"new libguestfs version" (
270     fun () ->
271       git_force "https://github.com/libguestfs/libguestfs.git" "master";
272
273       let version = git_latest_version "master" in
274       require (website_updated version)
275   )