Fedora OCaml rebuild for OCaml 4.02.0 beta in Rawhide.
[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.02.0 beta"
18
19 (* Packages that have problems or we just don't want to build. *)
20 let blocked = [
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     | `No_such_build ->
63       failwith (sprintf "rebuild of package %s: no build found" pkg)
64     | `Building ->
65       sleep 60;
66       loop ()
67     | `Complete ->
68       ()
69     | `Deleted ->
70       failwith (sprintf "rebuild of package %s: deleted" pkg)
71     | `Failed ->
72       failwith (sprintf "rebuild of package %s: failed" pkg)
73     | `Canceled ->
74       failwith (sprintf "rebuild of package %s: canceled" pkg)
75   in
76   loop ();
77
78   (* Wait for the build to appear in Koji repo. *)
79   koji_wait_repo koji_target (fedora_verrel pkg branch)
80
81 (* Goal: The rebuild of the package has started, but we haven't waited
82  * for it to finish.
83  *)
84 and rebuild_started pkg =
85   let deps = List.assoc pkg pkg_deps in
86   let specfile = fedora_specfile pkg branch in
87
88   (* Note the target must be both of these because the old verrel
89    * could exist as a koji build without it having been part of the
90    * rebuild.
91    *)
92   target (file_contains_string specfile rebuild_name &&
93             (match koji_build_state (fedora_verrel pkg branch) with
94             | `Building | `Complete -> true
95             | `Deleted | `Failed | `Canceled | `No_such_build -> false));
96
97   (* All dependent packages must have been fully rebuilt and in the
98    * repo first.
99    *)
100   List.iter (fun dep -> require (rebuilt dep)) deps;
101
102   (* A local test build must succeed. *)
103   require (local_build_succeeded pkg);
104
105   (* Rebuild the package in Koji.  Don't wait ... *)
106   koji_build ~wait:false pkg branch;
107
108   (* ... but the build doesn't appear in Koji (eg. in 'koji
109    * buildinfo') until the SRPM has been built.  This can take quite
110    * some time.  Loop here until the build appears.
111    *)
112   let rec loop () =
113     match koji_build_state (fedora_verrel pkg branch) with
114     | `No_such_build ->
115       sleep 60;
116       loop ();
117     | `Building | `Complete ->
118       ()
119     | `Deleted ->
120       failwith (sprintf "rebuild of package %s: deleted" pkg)
121     | `Failed ->
122       failwith (sprintf "rebuild of package %s: failed" pkg)
123     | `Canceled ->
124       failwith (sprintf "rebuild of package %s: canceled" pkg)
125   in
126   loop ()
127
128 and local_build_succeeded pkg =
129   (* The specfile must have been updated. *)
130   require (specfile_updated pkg);
131
132   let key =
133     sprintf "fedora_ocaml_local_build_%s_%s" pkg (fedora_verrel pkg branch) in
134
135   target (memory_exists key);
136
137   (* Do a local test build to ensure the Koji build will work. *)
138   sh "
139     cd %s
140     sudo yum-builddep -y %s
141     fedpkg local
142   " (fedora_repo pkg branch)
143     (fedora_specfile pkg branch);
144
145   memory_set key "1"
146
147 and specfile_updated pkg =
148   let repodir = fedora_repo pkg branch in
149   let specfile = fedora_specfile pkg branch in
150
151   sh "
152     cd %s
153     rm -rf x86_64 noarch *.src.rpm .build* clog
154     git fetch
155   " repodir;
156
157   if not (git_has_local_changes repodir) then
158     sh "
159       cd %s
160       git pull --rebase
161     " repodir;
162
163   sh "sudo yum-builddep -y %s" specfile;
164
165   (* For rationale behind always bumping the spec file, see comment
166    * in 'fedora.ml'.
167    *)
168   let title =
169     if not (file_contains_string specfile rebuild_name) then
170       rebuild_name ^ " rebuild."
171     else
172       "Bump release and rebuild." in
173   sh "rpmdev-bumpspec -c %s %s" (quote title) specfile;
174
175   (* XXX Automate common specfile fixes. *)
176
177   sh "
178     cd %s
179     echo 'Please make further changes as required to the spec file %s.spec'
180     echo '(Press return key)'
181     read
182     emacs -nw %s
183     echo 'OK to commit this change? (press ^C if not)'
184     read
185     fedpkg commit -c
186     echo 'OK to push this change? (press ^C if not)'
187     read
188     fedpkg push
189   " repodir
190     pkg
191     specfile