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