Fedora OCaml: Improve parallelism by not waiting for rebuilds unless they are require...
[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 Fedora
9
10 let branch = "master"
11 let koji_target = "rawhide"
12
13 (* The name of the rebuild, and also the magic substring that must
14  * appear in the %changelog when the package has been rebuilt.
15  *)
16 let rebuild_name = "OCaml 4.01.0"
17
18 (* Packages that have problems or we just don't want to build. *)
19 let blocked = [
20   "ocaml-libvirt"; (* RHBZ#1009701 *)
21   "ocaml-lwt"; "ocaml-react"; (* loganjerry is handling *)
22 ]
23
24 (* List of OCaml-related source package names. *)
25 let source_packages =
26   let dirs = shlines "cd %s && ls -1d ocaml*" fedora_dir in
27   dirs @ [ "alt-ergo"; "apron"; "brltty"; "coccinelle"; "coq";
28            "cduce"; "frama-c"; "gappalib-coq"; "graphviz"; "hivex";
29            "js-of-ocaml"; "llvm"; "plplot"; "whenjobs"; "why3"; "xen" ]
30
31 let source_packages =
32   List.filter (fun pkg -> not (List.mem pkg blocked)) source_packages
33
34 (* Dependencies of each package.  (pkg, [deps ...]) *)
35 let pkg_deps = dependencies branch source_packages
36
37 (* Goal: rebuild all packages. *)
38 let rec goal all () =
39   List.iter (fun pkg -> require (rebuild_started pkg)) source_packages
40
41 (* Goal: That 'package' has been rebuilt and exists in Koji. *)
42 and rebuilt pkg =
43   let specfile = fedora_specfile pkg branch in
44
45   (* Note: verrel may change as we go along, so don't assign it to
46    * variable.
47    *)
48
49   (* Note the target must be both of these because the old verrel
50    * could exist as a koji build without it having been part of the
51    * rebuild.
52    *)
53   target (file_contains_string specfile rebuild_name &&
54           koji_build_state (fedora_verrel pkg branch) == `Complete);
55
56   (* Start the rebuild. *)
57   require (rebuild_started pkg);
58
59   (* Wait for the build state to reach a conclusion. *)
60   let rec loop () =
61     match koji_build_state (fedora_verrel pkg branch) with
62     | `Building ->
63       sleep 30;
64       loop ()
65     | `Complete ->
66       ()
67     | `Deleted ->
68       failwith (sprintf "rebuild of package %s: deleted" pkg)
69     | `Failed ->
70       failwith (sprintf "rebuild of package %s: failed" pkg)
71     | `Canceled ->
72       failwith (sprintf "rebuild of package %s: canceled" pkg)
73   in
74   loop ();
75
76   (* Wait for the build to appear in Koji repo. *)
77   koji_wait_repo koji_target (fedora_verrel pkg branch)
78
79 (* Goal: The rebuild of the package has started, but we haven't waited
80  * for it to finish.
81  *)
82 and rebuild_started pkg =
83   let deps = List.assoc pkg pkg_deps in
84   let specfile = fedora_specfile pkg branch in
85
86   (* Note the target must be both of these because the old verrel
87    * could exist as a koji build without it having been part of the
88    * rebuild.
89    *)
90   target (file_contains_string specfile rebuild_name &&
91             (match koji_build_state (fedora_verrel pkg branch) with
92             | `Building | `Complete -> true
93             | `Deleted | `Failed | `Canceled -> false));
94
95   (* All dependent packages must have been fully rebuilt and in the
96    * repo first.
97    *)
98   List.iter (fun dep -> require (rebuilt dep)) deps;
99
100   (* A local test build must succeed. *)
101   require (local_build_succeeded pkg);
102
103   (* Rebuild the package in Koji, but don't wait. *)
104   koji_build ~wait:false pkg branch
105
106 and local_build_succeeded pkg =
107   (* The specfile must have been updated. *)
108   require (specfile_updated pkg);
109
110   let key =
111     sprintf "fedora_ocaml_local_build_%s_%s" pkg (fedora_verrel pkg branch) in
112
113   target (memory_exists key);
114
115   (* Do a local test build to ensure the Koji build will work. *)
116   sh "
117     cd %s
118     sudo yum-builddep %s
119     fedpkg local
120   " (fedora_repo pkg branch)
121     (fedora_specfile pkg branch);
122
123   memory_set key "1"
124
125 and specfile_updated pkg =
126   let repodir = fedora_repo pkg branch in
127   let specfile = fedora_specfile pkg branch in
128
129   (* XXX Automate common changes. *)
130   let title = rebuild_name ^ " rebuild." in
131   sh "
132     cd %s
133     git pull --rebase
134     rm -rf x86_64 noarch *.src.rpm
135     rpmdev-bumpspec -c %s %s
136     echo 'Please make further changes as required to the spec file %s.spec'
137     echo '(Press return key)'
138     read
139     emacs -nw %s
140     echo 'OK to commit this change? (press ^C if not)'
141     read
142     fedpkg commit -c
143     echo 'OK to push this change? (press ^C if not)'
144     read
145     fedpkg push
146   " repodir
147     (quote title) specfile
148     pkg
149     specfile