19644bd6b90acc1fc3f688ee3f120e381f1a1a99
[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 (* Local repository that contains build dependencies. *)
20 let yum_repo = "koji-rawhide"
21
22 let blocked = [
23   "ocaml-lwt"; "ocaml-react"; (* loganjerry is handling *)
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 --disablerepo=\\* --enablerepo=%s %s
143     fedpkg local
144   " (fedora_repo pkg branch)
145     (quote yum_repo)
146     (fedora_specfile pkg branch);
147
148   memory_set key "1"
149
150 and specfile_updated pkg =
151   let repodir = fedora_repo pkg branch in
152   let specfile = fedora_specfile pkg branch in
153
154   sh "
155     cd %s
156     rm -rf x86_64 noarch *.src.rpm .build* clog
157     git fetch
158   " repodir;
159
160   if not (git_has_local_changes repodir) then
161     sh "
162       cd %s
163       git pull --rebase
164     " repodir;
165
166   sh "sudo yum-builddep -y --disablerepo=\\* --enablerepo=%s %s"
167     (quote yum_repo) specfile;
168
169   (* For rationale behind always bumping the spec file, see comment
170    * in 'fedora.ml'.
171    *)
172   let title =
173     if not (file_contains_string specfile rebuild_name) then
174       rebuild_name ^ " rebuild."
175     else
176       "Bump release and rebuild." in
177   sh "rpmdev-bumpspec -c %s %s" (quote title) specfile;
178
179   (* XXX Automate common specfile fixes. *)
180
181   sh "
182     cd %s
183     echo 'Please make further changes as required to the spec file %s.spec'
184     echo '(Press return key)'
185     read
186     emacs -nw %s
187     echo 'OK to commit this change? (press ^C if not)'
188     read
189     fedpkg commit -c
190     echo 'OK to push this change? (press ^C if not)'
191     read
192     fedpkg push
193   " repodir
194     pkg
195     specfile