Further updates to OCaml rebuild.
[goaljobs-goals.git] / fedora_ocaml_rebuild.ml
1 (* Perform a complete Fedora OCaml rebuild, in build order. *)
2
3 open Unix
4 open Printf
5
6 open Goaljobs
7 open Config
8 open Git
9 open Fedora
10
11 let branch = "master"
12 let koji_target = "rawhide"
13
14 (* The name of the rebuild, and also the magic substring that must
15  * appear in the %changelog when the package has been rebuilt.
16  *)
17 let rebuild_name = "OCaml 4.01.0"
18
19 (* Packages that have problems or we just don't want to build. *)
20 let blocked = [
21   "ocaml-libvirt"; (* RHBZ#1009701 *)
22   "ocaml-lwt"; "ocaml-react"; (* loganjerry is handling *)
23   "ocaml-xmlrpc-light"; (* temporary, can remove after 2013-09-19 *)
24 ]
25
26 (* List of OCaml-related source package names. *)
27 let source_packages =
28   let dirs = shlines "cd %s && ls -1d ocaml*" fedora_dir in
29   dirs @ [ "alt-ergo"; "apron"; "brltty"; "coccinelle"; "coq";
30            "cduce"; "frama-c"; "gappalib-coq"; "graphviz"; "hivex";
31            "js-of-ocaml"; "llvm"; "plplot"; "whenjobs"; "why3"; "xen" ]
32
33 let source_packages =
34   List.filter (fun pkg -> not (List.mem pkg blocked)) source_packages
35
36 (* Dependencies of each package.  (pkg, [deps ...]) *)
37 let pkg_deps = dependencies branch source_packages
38
39 (* Goal: rebuild all packages. *)
40 let rec goal all () =
41   List.iter (fun pkg -> require (rebuild_started pkg)) source_packages
42
43 (* Goal: That 'package' has been rebuilt and exists in Koji. *)
44 and rebuilt pkg =
45   let specfile = fedora_specfile pkg branch in
46
47   (* Note: verrel may change as we go along, so don't assign it to
48    * variable.
49    *)
50
51   (* Note the target must be both of these because the old verrel
52    * could exist as a koji build without it having been part of the
53    * rebuild.
54    *)
55   target (file_contains_string specfile rebuild_name &&
56           koji_build_state (fedora_verrel pkg branch) == `Complete);
57
58   (* Start the rebuild. *)
59   require (rebuild_started pkg);
60
61   (* Wait for the build state to reach a conclusion. *)
62   let rec loop () =
63     match koji_build_state (fedora_verrel pkg branch) with
64     | `No_such_build ->
65       failwith (sprintf "rebuild of package %s: no build found" pkg)
66     | `Building ->
67       sleep 60;
68       loop ()
69     | `Complete ->
70       ()
71     | `Deleted ->
72       failwith (sprintf "rebuild of package %s: deleted" pkg)
73     | `Failed ->
74       failwith (sprintf "rebuild of package %s: failed" pkg)
75     | `Canceled ->
76       failwith (sprintf "rebuild of package %s: canceled" pkg)
77   in
78   loop ();
79
80   (* Wait for the build to appear in Koji repo. *)
81   koji_wait_repo koji_target (fedora_verrel pkg branch)
82
83 (* Goal: The rebuild of the package has started, but we haven't waited
84  * for it to finish.
85  *)
86 and rebuild_started pkg =
87   let deps = List.assoc pkg pkg_deps in
88   let specfile = fedora_specfile pkg branch in
89
90   (* Note the target must be both of these because the old verrel
91    * could exist as a koji build without it having been part of the
92    * rebuild.
93    *)
94   target (file_contains_string specfile rebuild_name &&
95             (match koji_build_state (fedora_verrel pkg branch) with
96             | `Building | `Complete -> true
97             | `Deleted | `Failed | `Canceled | `No_such_build -> false));
98
99   (* All dependent packages must have been fully rebuilt and in the
100    * repo first.
101    *)
102   List.iter (fun dep -> require (rebuilt dep)) deps;
103
104   (* A local test build must succeed. *)
105   require (local_build_succeeded pkg);
106
107   (* Rebuild the package in Koji.  Don't wait ... *)
108   koji_build ~wait:false pkg branch;
109
110   (* ... but the build doesn't appear in Koji (eg. in 'koji
111    * buildinfo') until the SRPM has been built.  This can take quite
112    * some time.  Loop here until the build appears.
113    *)
114   let rec loop () =
115     match koji_build_state (fedora_verrel pkg branch) with
116     | `No_such_build ->
117       sleep 60;
118       loop ();
119     | `Building | `Complete ->
120       ()
121     | `Deleted ->
122       failwith (sprintf "rebuild of package %s: deleted" pkg)
123     | `Failed ->
124       failwith (sprintf "rebuild of package %s: failed" pkg)
125     | `Canceled ->
126       failwith (sprintf "rebuild of package %s: canceled" pkg)
127   in
128   loop ()
129
130 and local_build_succeeded pkg =
131   (* The specfile must have been updated. *)
132   require (specfile_updated pkg);
133
134   let key =
135     sprintf "fedora_ocaml_local_build_%s_%s" pkg (fedora_verrel pkg branch) in
136
137   target (memory_exists key);
138
139   (* Do a local test build to ensure the Koji build will work. *)
140   sh "
141     cd %s
142     sudo yum-builddep -y %s
143     fedpkg local
144   " (fedora_repo pkg branch)
145     (fedora_specfile pkg branch);
146
147   memory_set key "1"
148
149 and specfile_updated pkg =
150   let repodir = fedora_repo pkg branch in
151   let specfile = fedora_specfile pkg branch in
152
153   sh "
154     cd %s
155     rm -rf x86_64 noarch *.src.rpm .build* clog
156     git fetch
157   " repodir;
158
159   if not (git_has_local_changes repodir) then
160     sh "
161       cd %s
162       git pull --rebase
163     " repodir;
164
165   sh "sudo yum-builddep -y %s" specfile;
166
167   (* For rationale behind always bumping the spec file, see comment
168    * in 'fedora.ml'.
169    *)
170   (* XXX Automate common specfile fixes. *)
171   let title = rebuild_name ^ " rebuild." in
172   sh "rpmdev-bumpspec -c %s %s" (quote title) specfile;
173
174   sh "
175     cd %s
176     echo 'Please make further changes as required to the spec file %s.spec'
177     echo '(Press return key)'
178     read
179     emacs -nw %s
180     echo 'OK to commit this change? (press ^C if not)'
181     read
182     fedpkg commit -c
183     echo 'OK to push this change? (press ^C if not)'
184     read
185     fedpkg push
186   " repodir
187     pkg
188     specfile