Views: Removed global open of Tyxml.Html and switched to prefix -

.. there are too many common names in this modules scope, and code gets easier to understand
 .. also I don't think global open is a good idea in general for this kind of module, so better
    to fix this style now than be sorry later
This commit is contained in:
rand00 2022-02-03 12:54:02 +01:00
parent ae5c5cb67d
commit f8b17e6b17

View file

@ -1,26 +1,26 @@
open Tyxml.Html module H = Tyxml.Html
let pp_ptime ppf ptime = let pp_ptime ppf ptime =
let (y, m, d), ((hh, mm, ss), _) = Ptime.to_date_time ptime in let (y, m, d), ((hh, mm, ss), _) = Ptime.to_date_time ptime in
Fmt.pf ppf "%04d-%02d-%02d %02d:%02d:%02dZ" y m d hh mm ss Fmt.pf ppf "%04d-%02d-%02d %02d:%02d:%02dZ" y m d hh mm ss
let txtf fmt = Fmt.kstr txt fmt let txtf fmt = Fmt.kstr H.txt fmt
let a_titlef fmt = Fmt.kstr a_title fmt let a_titlef fmt = Fmt.kstr H.a_title fmt
let check_icon result = let check_icon result =
match result with match result with
| Builder.Exited 0 -> | Builder.Exited 0 ->
span ~a:[ H.span ~a:H.[
a_style "color: green; cursor: pointer;"; a_style "color: green; cursor: pointer;";
a_titlef "%a" Builder.pp_execution_result result; a_titlef "%a" Builder.pp_execution_result result;
] ]
[txt ""] [H.txt ""]
| _ -> | _ ->
span ~a:[ H.span ~a:H.[
a_style "color: red; cursor: pointer;"; a_style "color: red; cursor: pointer;";
a_titlef "%a" Builder.pp_execution_result result; a_titlef "%a" Builder.pp_execution_result result;
] ]
[txt ""] [H.txt ""]
type nav = [ type nav = [
| `Default | `Default
@ -80,19 +80,22 @@ h1,h2,h3{line-height:1.2}
} }
|} |}
let layout ?include_static_css ?nav:(nav_=`Default) ~title:title_ body_ = let layout ?include_static_css ?(nav=`Default) ~title body =
let breadcrumb = let breadcrumb =
let to_nav kvs = let to_nav kvs =
nav [ ul (List.map (fun (desc, href) -> H.nav [
li [a ~a:[a_href href] [desc]]) H.ul (
kvs) ] List.map (fun (desc, href) ->
H.li [H.a ~a:H.[a_href href] [desc]]
) kvs
)]
in in
match nav_ with match nav with
| `Default -> | `Default ->
to_nav [txt "Home", "/"] to_nav [H.txt "Home", "/"]
| `Job (job_name, platform) -> | `Job (job_name, platform) ->
to_nav [ to_nav [
txt "Home", "/"; H.txt "Home", "/";
txtf "Job %s" job_name, Fmt.str "/job/%s/" job_name ; txtf "Job %s" job_name, Fmt.str "/job/%s/" job_name ;
( (
txtf "%a" pp_platform platform, txtf "%a" pp_platform platform,
@ -101,7 +104,7 @@ let layout ?include_static_css ?nav:(nav_=`Default) ~title:title_ body_ =
] ]
| `Build (job_name, build) -> | `Build (job_name, build) ->
to_nav [ to_nav [
txt "Home", "/"; H.txt "Home", "/";
txtf "Job %s" job_name, Fmt.str "/job/%s/" job_name; txtf "Job %s" job_name, Fmt.str "/job/%s/" job_name;
( (
txtf "%a" pp_platform (Some build.Builder_db.Build.platform), txtf "%a" pp_platform (Some build.Builder_db.Build.platform),
@ -116,7 +119,7 @@ let layout ?include_static_css ?nav:(nav_=`Default) ~title:title_ body_ =
] ]
| `Comparison ((job_left, build_left), (job_right, build_right)) -> | `Comparison ((job_left, build_left), (job_right, build_right)) ->
to_nav [ to_nav [
txt "Home", "/"; H.txt "Home", "/";
txtf "Comparison between %s@%a and %s@%a" txtf "Comparison between %s@%a and %s@%a"
job_left pp_ptime build_left.Builder_db.Build.start job_left pp_ptime build_left.Builder_db.Build.start
job_right pp_ptime build_right.Builder_db.Build.start, job_right pp_ptime build_right.Builder_db.Build.start,
@ -128,32 +131,32 @@ let layout ?include_static_css ?nav:(nav_=`Default) ~title:title_ body_ =
(*> Note: Last declared CSS wins - so one can override here*) (*> Note: Last declared CSS wins - so one can override here*)
let static_css = static_css :: Option.to_list include_static_css let static_css = static_css :: Option.to_list include_static_css
in in
html H.html
(head (title (txt title_)) (H.head (H.title (H.txt title))
[style ~a:[a_mime_type "text/css"] static_css]) [H.style ~a:H.[a_mime_type "text/css"] static_css])
(body [ (H.body [
breadcrumb; breadcrumb;
main body_ H.main body
]) ])
let toggleable ?(hidden=true) id description content = let toggleable ?(hidden=true) id description content =
let checked = if hidden then [] else [a_checked ()] in let checked = if hidden then [] else H.[a_checked ()] in
div [ H.div [
label H.label
~a:[ ~a:H.[
a_label_for id; a_label_for id;
a_class ["toggleable-descr"]; a_class ["toggleable-descr"];
] ]
[txt description]; [H.txt description];
input H.input
~a:(checked @ [ ~a:(checked @ H.[
a_input_type `Checkbox; a_input_type `Checkbox;
a_id id; a_id id;
a_style "display: none;"; a_style "display: none;";
]) (); ]) ();
div H.div
~a:[ ~a:H.[
a_class ["toggleable"] a_class ["toggleable"]
] ]
content; content;
@ -172,13 +175,13 @@ let artifact
Fpath.pp filepath Fpath.pp filepath
in in
[ [
a ~a:[a_href artifact_link] H.a ~a:H.[a_href artifact_link]
[ [
if basename then txt (Fpath.basename filepath) if basename then H.txt (Fpath.basename filepath)
else txtf "%a" Fpath.pp filepath else txtf "%a" Fpath.pp filepath
]; ];
txt " "; H.txt " ";
code [txtf "SHA256:%a" Hex.pp (Hex.of_cstruct sha256)]; H.code [txtf "SHA256:%a" Hex.pp (Hex.of_cstruct sha256)];
txtf " (%a)" Fmt.byte_size size; txtf " (%a)" Fmt.byte_size size;
] ]
@ -187,34 +190,37 @@ module Builds = struct
let make section_job_map = let make section_job_map =
layout ~title:"Reproducible OPAM builds" layout ~title:"Reproducible OPAM builds"
([ ([
h1 [txt "Reproducible OPAM builds"]; H.h1 [ H.txt "Reproducible OPAM builds" ];
p [ txt "This website offers binary MirageOS unikernels and \ H.p [ H.txt "This website offers binary MirageOS unikernels and \
supplementary OS packages." ]; supplementary OS packages." ];
p [ txt "Following is a list of jobs that are built daily. A \ H.p [
H.txt "Following is a list of jobs that are built daily. A \
persistent link to the latest successful build is available \ persistent link to the latest successful build is available \
as /job/*jobname*/build/latest/. All builds can be \ as /job/*jobname*/build/latest/. All builds can be \
reproduced with "; reproduced with ";
a ~a:[a_href "https://github.com/roburio/orb/"] [txt "orb"]; H.a ~a:H.[a_href "https://github.com/roburio/orb/"]
txt ". The builds are scheduled and executed by "; [H.txt "orb"];
a ~a:[a_href "https://github.com/roburio/builder/"] [txt "builder"]; H.txt ". The builds are scheduled and executed by ";
txt ". The web interface is "; H.a ~a:H.[a_href "https://github.com/roburio/builder/"]
a ~a:[a_href "https://git.robur.io/robur/builder-web/"] [H.txt "builder"];
[txt "builder-web"]; H.txt ". The web interface is ";
txt ". Contact team@robur.coop if you have any questions or \ H.a ~a:H.[a_href "https://git.robur.io/robur/builder-web/"]
[H.txt "builder-web"];
H.txt ". Contact team@robur.coop if you have any questions or \
suggestions."; suggestions.";
]; ];
form ~a:[a_action "/hash"; a_method `Get] H.form ~a:H.[a_action "/hash"; a_method `Get]
[ [
label [ H.label [
txt "Search artifact by SHA256"; H.txt "Search artifact by SHA256";
br (); H.br ();
input ~a:[ H.input ~a:H.[
a_input_type `Search; a_input_type `Search;
a_id "sha256"; a_id "sha256";
a_name "sha256"; a_name "sha256";
] (); ] ();
]; ];
input ~a:[ H.input ~a:H.[
a_input_type `Submit; a_input_type `Submit;
a_value "Search"; a_value "Search";
] (); ] ();
@ -222,36 +228,37 @@ module Builds = struct
] @ ] @
Utils.String_map.fold (fun section jobs acc -> Utils.String_map.fold (fun section jobs acc ->
acc @ [ acc @ [
h2 [ txt section ]; H.h2 [ H.txt section ];
ul (List.map (fun (job_name, synopsis, platform_builds) -> H.ul (List.map (fun (job_name, synopsis, platform_builds) ->
li ([ H.li ([
a ~a:[a_href ("job/" ^ job_name ^ "/")] [txt job_name]; H.a ~a:H.[a_href ("job/" ^ job_name ^ "/")]
br (); [H.txt job_name];
txt (Option.value ~default:"" synopsis); H.br ();
br () H.txt (Option.value ~default:"" synopsis);
H.br ()
] @ List.concat_map (fun (platform, latest_build, latest_artifact) -> ] @ List.concat_map (fun (platform, latest_build, latest_artifact) ->
[ [
check_icon latest_build.Builder_db.Build.result; check_icon latest_build.Builder_db.Build.result;
txt " "; H.txt " ";
a ~a:[ H.a ~a:[
Fmt.kstr a_href "job/%s/%a" Fmt.kstr H.a_href "job/%s/%a"
job_name job_name
pp_platform_query (Some platform)] pp_platform_query (Some platform)]
[txt platform]; [H.txt platform];
txt " "; H.txt " ";
a ~a:[ H.a ~a:[
Fmt.kstr a_href "job/%s/build/%a/" Fmt.kstr H.a_href "job/%s/build/%a/"
job_name job_name
Uuidm.pp latest_build.Builder_db.Build.uuid] Uuidm.pp latest_build.Builder_db.Build.uuid]
[txtf "%a" pp_ptime latest_build.Builder_db.Build.start]; [txtf "%a" pp_ptime latest_build.Builder_db.Build.start];
txt " "; H.txt " ";
] @ (match latest_artifact with ] @ (match latest_artifact with
| Some main_binary -> | Some main_binary ->
artifact ~basename:true job_name latest_build main_binary artifact ~basename:true job_name latest_build main_binary
| None -> | None ->
[ txtf "Build failure: %a" Builder.pp_execution_result [ txtf "Build failure: %a" Builder.pp_execution_result
latest_build.Builder_db.Build.result ] latest_build.Builder_db.Build.result ]
) @ [ br () ] ) @ [ H.br () ]
) )
platform_builds) platform_builds)
) )
@ -259,11 +266,11 @@ module Builds = struct
]) ])
section_job_map section_job_map
[] @ [] @
[ p [ [ H.p [
txt "View the latest failed builds "; H.txt "View the latest failed builds ";
a ~a:[a_href "/failed-builds/"] H.a ~a:H.[a_href "/failed-builds/"]
[txt "here"]; [H.txt "here"];
txt "." H.txt "."
]]) ]])
end end
@ -274,30 +281,30 @@ module Job = struct
layout layout
~nav:(`Job (name, platform)) ~nav:(`Job (name, platform))
~title:(Fmt.str "Job %s %a" name pp_platform platform) ~title:(Fmt.str "Job %s %a" name pp_platform platform)
((h1 [txtf "Job %s %a" name pp_platform platform] :: ((H.h1 [txtf "Job %s %a" name pp_platform platform] ::
(match readme with (match readme with
| None -> [] | None -> []
| Some data -> | Some data ->
[ [
h2 ~a:[a_id "readme"] [txt "README"]; H.h2 ~a:H.[a_id "readme"] [H.txt "README"];
a ~a:[a_href "#builds"] [txt "Skip to builds"]; H.a ~a:H.[a_href "#builds"] [H.txt "Skip to builds"];
Unsafe.data (Utils.Omd.html_of_string data) H.Unsafe.data (Utils.Omd.html_of_string data)
])) @ ])) @
[ [
h2 ~a:[a_id "builds"] [txt "Builds"]; H.h2 ~a:H.[a_id "builds"] [H.txt "Builds"];
a ~a:[a_href "#readme"] [txt "Back to readme"]; H.a ~a:H.[a_href "#readme"] [H.txt "Back to readme"];
ul (List.map (fun (build, main_binary) -> H.ul (List.map (fun (build, main_binary) ->
li ([ H.li ([
check_icon build.Builder_db.Build.result; check_icon build.Builder_db.Build.result;
txtf " %s " build.platform; txtf " %s " build.platform;
a ~a:[ H.a ~a:H.[
Fmt.kstr a_href "/job/%s/build/%a/" Fmt.kstr a_href "/job/%s/build/%a/"
name name
Uuidm.pp build.Builder_db.Build.uuid ] Uuidm.pp build.Builder_db.Build.uuid ]
[ [
txtf "%a" pp_ptime build.Builder_db.Build.start; txtf "%a" pp_ptime build.Builder_db.Build.start;
]; ];
txt " "; H.txt " ";
] @ match main_binary with ] @ match main_binary with
| Some main_binary -> | Some main_binary ->
artifact ~basename:true name build main_binary artifact ~basename:true name build main_binary
@ -306,15 +313,15 @@ module Job = struct
build.Builder_db.Build.result ])) build.Builder_db.Build.result ]))
builds); builds);
if failed then if failed then
p [ H.p [
txt "Excluding failed builds " ; H.txt "Excluding failed builds " ;
a ~a:[a_href "../"] [txt "here"] ; H.a ~a:H.[a_href "../"] [H.txt "here"] ;
txt "." ] H.txt "." ]
else else
p [ H.p [
txt "Including failed builds " ; H.txt "Including failed builds " ;
a ~a:[a_href "failed/"] [txt "here"] ; H.a ~a:H.[a_href "failed/"] [H.txt "here"] ;
txt "." ] H.txt "." ]
]) ])
end end
@ -338,48 +345,48 @@ module Job_build = struct
~latest ~next ~previous ~latest ~next ~previous
= =
[ [
h2 ~a:[a_id "build"] [txtf "Build %a" pp_ptime build.start]; H.h2 ~a:H.[a_id "build"] [txtf "Build %a" pp_ptime build.start];
p [txtf "Built on platform %s" build.platform ]; H.p [txtf "Built on platform %s" build.platform ];
p [txtf "Build took %a." Ptime.Span.pp delta ]; H.p [txtf "Build took %a." Ptime.Span.pp delta ];
p [txtf "Execution result: %a." Builder.pp_execution_result build.result]; H.p [txtf "Execution result: %a." Builder.pp_execution_result build.result];
h3 [txt "Build info"]; H.h3 [H.txt "Build info"];
ul [ H.ul [
li [ a ~a:[Fmt.kstr a_href "/job/%s/build/%a/console" name Uuidm.pp build.uuid] H.li [ H.a ~a:H.[Fmt.kstr a_href "/job/%s/build/%a/console" name Uuidm.pp build.uuid]
[txt "Console output"]; [H.txt "Console output"];
]; ];
li [ a ~a:[Fmt.kstr a_href "/job/%s/build/%a/script" name Uuidm.pp build.uuid] H.li [ H.a ~a:H.[Fmt.kstr a_href "/job/%s/build/%a/script" name Uuidm.pp build.uuid]
[txt "Build script"]; [H.txt "Build script"];
] ]
]; ];
h3 [txt "Build artifacts"]; H.h3 [H.txt "Build artifacts"];
dl (List.concat_map H.dl (List.concat_map
(fun { Builder_db.filepath; localpath=_; sha256; size } -> (fun { Builder_db.filepath; localpath=_; sha256; size } ->
let (`Hex sha256_hex) = Hex.of_cstruct sha256 in let (`Hex sha256_hex) = Hex.of_cstruct sha256 in
[ [
dt [a H.dt [H.a
~a:[Fmt.kstr a_href "f/%a" Fpath.pp filepath] ~a:H.[Fmt.kstr a_href "f/%a" Fpath.pp filepath]
[code [txtf "%a" Fpath.pp filepath]]]; [H.code [txtf "%a" Fpath.pp filepath]]];
dd [ H.dd [
code [txt "SHA256:"; txt sha256_hex]; H.code [H.txt "SHA256:"; H.txt sha256_hex];
txtf " (%a)" Fmt.byte_size size; txtf " (%a)" Fmt.byte_size size;
]; ];
]) ])
artifacts); artifacts);
h3 [ H.h3 [
txtf "Reproduced by %d builds" txtf "Reproduced by %d builds"
(List.length (same_input_same_output @ different_input_same_output))] ; (List.length (same_input_same_output @ different_input_same_output))] ;
ul H.ul
((List.map (fun { Builder_db.Build.start ; uuid ; platform ; _ } -> ((List.map (fun { Builder_db.Build.start ; uuid ; platform ; _ } ->
li [ H.li [
txtf "on %s, same input, " platform; txtf "on %s, same input, " platform;
a ~a:[Fmt.kstr a_href "/job/%s/build/%a/" name Uuidm.pp uuid] H.a ~a:H.[Fmt.kstr a_href "/job/%s/build/%a/" name Uuidm.pp uuid]
[txtf "%a" pp_ptime start] [txtf "%a" pp_ptime start]
]) ])
same_input_same_output) @ same_input_same_output) @
List.map (fun { Builder_db.Build.start ; uuid = other_uuid ; platform ; _ } -> List.map (fun { Builder_db.Build.start ; uuid = other_uuid ; platform ; _ } ->
li [ H.li [
txtf "on %s, different input, " platform; txtf "on %s, different input, " platform;
a ~a:[ H.a ~a:H.[
Fmt.kstr a_href "/compare/%a/%a/" Fmt.kstr a_href "/compare/%a/%a/"
Uuidm.pp other_uuid Uuidm.pp other_uuid
Uuidm.pp build.uuid] Uuidm.pp build.uuid]
@ -390,12 +397,12 @@ module Job_build = struct
@ (if same_input_different_output = [] then @ (if same_input_different_output = [] then
[] []
else else
[ h3 [txt "Same input, different output (not reproducible!)"]; [ H.h3 [H.txt "Same input, different output (not reproducible!)"];
ul ( H.ul (
List.map (fun { Builder_db.Build.start ; uuid = other_uuid ; platform ; _ } -> List.map (fun { Builder_db.Build.start ; uuid = other_uuid ; platform ; _ } ->
li [ H.li [
txtf "on %s, " platform ; txtf "on %s, " platform ;
a ~a:[ H.a ~a:H.[
Fmt.kstr a_href "/compare/%a/%a/" Fmt.kstr a_href "/compare/%a/%a/"
Uuidm.pp other_uuid Uuidm.pp other_uuid
Uuidm.pp build.uuid] Uuidm.pp build.uuid]
@ -405,18 +412,20 @@ module Job_build = struct
] ]
) )
@ [ @ [
h3 [txt "Comparisons with other builds on the same platform"]; H.h3 [H.txt "Comparisons with other builds on the same platform"];
let opt_build (ctx, build') = let opt_build (ctx, build') =
match build' with match build' with
| Some b when not (Uuidm.equal build.uuid b.Builder_db.Build.uuid) -> | Some b when not (Uuidm.equal build.uuid b.Builder_db.Build.uuid) ->
[ li [ txt ctx; [ H.li [ H.txt ctx;
a ~a:[Fmt.kstr a_href "/compare/%a/%a/" H.a ~a:[
Uuidm.pp b.uuid Uuidm.pp build.uuid] Fmt.kstr H.a_href "/compare/%a/%a/"
Uuidm.pp b.uuid
Uuidm.pp build.uuid ]
[txtf "%a" pp_ptime b.start]] [txtf "%a" pp_ptime b.start]]
] ]
| _ -> [] | _ -> []
in in
ul H.ul
(List.concat_map opt_build (List.concat_map opt_build
[ ("Latest build ", latest) ; [ ("Latest build ", latest) ;
("Later build with different output ", next) ; ("Later build with different output ", next) ;
@ -443,19 +452,19 @@ module Job_build = struct
let make_viz_section ~name ~artifacts ~uuid = let make_viz_section ~name ~artifacts ~uuid =
[ [
(* [ h3 [txt "Analysis"] ]; *) (* [ H.h3 [txt "Analysis"] ]; *)
[ p [ [ H.p [
let src = Fmt.str "/job/%s/build/%a/vizdependencies" name Uuidm.pp uuid in let src = Fmt.str "/job/%s/build/%a/vizdependencies" name Uuidm.pp uuid in
iframe ~a:[ H.iframe ~a:H.[
a_src src; a_src src;
a_title "Opam dependencies"; a_title "Opam dependencies";
a_style viz_style_deps a_style viz_style_deps
] [] ] []
]]; ]];
if not @@ contains_debug_bin artifacts then [] else [ if not @@ contains_debug_bin artifacts then [] else [
p [ H.p [
let src = Fmt.str "/job/%s/build/%a/viztreemap" name Uuidm.pp uuid in let src = Fmt.str "/job/%s/build/%a/viztreemap" name Uuidm.pp uuid in
iframe ~a:[ H.iframe ~a:H.[
a_src src; a_src src;
a_title "Binary dissection"; a_title "Binary dissection";
a_style viz_style_treemap a_style viz_style_treemap
@ -485,26 +494,26 @@ module Job_build = struct
~same_input_different_output ~same_input_different_output
~latest ~next ~previous ~latest ~next ~previous
in in
let style_grid = a_style "display: flex; " in let style_grid = H.a_style "display: flex; " in
let style_grid_container = a_style "\ let style_grid_container = H.a_style "\
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
min-width: 83em; min-width: 83em;
" "
in in
let style_col_container = a_style "" in let style_col_container = H.a_style "" in
let style_col_left = let style_col_left =
a_style "width: 45em; min-width: 43em; padding-left: 2%" in H.a_style "width: 45em; min-width: 43em; padding-left: 2%" in
let style_col_right = a_style "width: 50%" in let style_col_right = H.a_style "width: 50%" in
let body = [ let body = [
div ~a:[ style_grid_container ] [ H.div~a:[ style_grid_container ] [
div ~a:[ style_col_container ] [ H.div~a:[ style_col_container ] [
h1 [txtf "Job %s" name]; H.h1 [txtf "Job %s" name];
div ~a:[ style_grid ] [ H.div~a:[ style_grid ] [
(* div ~a:[ style_col_padding ] []; *) (* H.div~a:H.[ style_col_padding ] []; *)
div ~a:[ style_col_left ] left_column; H.div~a:[ style_col_left ] left_column;
div ~a:[ style_col_right ] right_column H.div~a:[ style_col_right ] right_column
] ]
] ]
] ]
@ -518,53 +527,53 @@ module Job_build = struct
end end
let key_values xs = let key_values xs =
List.concat_map (fun (k, v) -> [ txtf "%s %s" k v ; br () ]) xs List.concat_map (fun (k, v) -> [ txtf "%s %s" k v ; H.br () ]) xs
let key_value_changes xs = let key_value_changes xs =
List.concat_map (fun (k, v, v') -> [ txtf "%s %s->%s" k v v' ; br () ]) xs List.concat_map (fun (k, v, v') -> [ txtf "%s %s->%s" k v v' ; H.br () ]) xs
let packages packages = let packages packages =
OpamPackage.Set.elements packages OpamPackage.Set.elements packages
|> List.concat_map (fun p -> [ |> List.concat_map (fun p -> [
txtf "%a" Opamdiff.pp_opampackage p; txtf "%a" Opamdiff.pp_opampackage p;
br (); H.br ();
]) ])
let package_diffs diffs = let package_diffs diffs =
List.concat_map (fun pd -> [ List.concat_map (fun pd -> [
txtf "%a" Opamdiff.pp_version_diff pd; txtf "%a" Opamdiff.pp_version_diff pd;
br (); H.br ();
]) ])
diffs diffs
let opam_diffs diffs = let opam_diffs diffs =
List.concat_map (fun pd -> List.concat_map (fun pd ->
h4 [ txtf "%a" Opamdiff.pp_opam_diff pd ] :: H.h4 [ txtf "%a" Opamdiff.pp_opam_diff pd ] ::
(match pd.Opamdiff.build with None -> [] | Some a -> (match pd.Opamdiff.build with None -> [] | Some a ->
let l, r = Opamdiff.commands_to_strings a in let l, r = Opamdiff.commands_to_strings a in
[ [
h5 [ txt "build instruction (without common prefix) modifications, old:" ] ; H.h5 [ H.txt "build instruction (without common prefix) modifications, old:" ] ;
code (List.concat_map (fun s -> [ txt s ; br () ]) l) ; H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) l) ;
h5 [ txt "new" ] ; H.h5 [ H.txt "new" ] ;
code (List.concat_map (fun s -> [ txt s ; br () ]) r) H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) r)
]) @ ]) @
(match pd.Opamdiff.install with None -> [] | Some a -> (match pd.Opamdiff.install with None -> [] | Some a ->
let l, r = Opamdiff.commands_to_strings a in let l, r = Opamdiff.commands_to_strings a in
[ [
h5 [ txt "install instruction (without common prefix) modifications, old:" ] ; H.h5 [ H.txt "install instruction (without common prefix) modifications, old:" ] ;
code (List.concat_map (fun s -> [ txt s ; br () ]) l) ; H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) l) ;
h5 [ txt "new" ] ; H.h5 [ H.txt "new" ] ;
code (List.concat_map (fun s -> [ txt s ; br () ]) r) H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) r)
]) @ ]) @
(match pd.Opamdiff.url with None -> [] | Some a -> (match pd.Opamdiff.url with None -> [] | Some a ->
let l, r = Opamdiff.opt_url_to_string a in let l, r = Opamdiff.opt_url_to_string a in
[ [
h5 [ txt "URL" ] ; H.h5 [ H.txt "URL" ] ;
txtf "old: %s" l; txtf "old: %s" l;
br (); H.br ();
txtf "new: %s" r txtf "new: %s" r
]) @ ]) @
[ br () ]) [ H.br () ])
diffs diffs
let compare_builds job_left job_right let compare_builds job_left job_right
@ -577,10 +586,10 @@ let compare_builds job_left job_right
~title:(Fmt.str "Comparing builds %a and %a" ~title:(Fmt.str "Comparing builds %a and %a"
Uuidm.pp build_left.uuid Uuidm.pp build_right.uuid) Uuidm.pp build_left.uuid Uuidm.pp build_right.uuid)
([ ([
h1 [txt "Comparing builds"]; H.h1 [H.txt "Comparing builds"];
h2 [ H.h2 [
txt "Builds "; H.txt "Builds ";
a ~a:[a_href H.a ~a:H.[a_href
(Fmt.str "/job/%s/build/%a/" (Fmt.str "/job/%s/build/%a/"
job_left job_left
Uuidm.pp build_left.uuid)] Uuidm.pp build_left.uuid)]
@ -588,8 +597,8 @@ let compare_builds job_left job_right
job_left job_left
pp_ptime build_left.start pp_ptime build_left.start
pp_platform (Some build_left.platform)]; pp_platform (Some build_left.platform)];
txt " and "; H.txt " and ";
a ~a:[a_href H.a ~a:H.[a_href
(Fmt.str "/job/%s/build/%a/" (Fmt.str "/job/%s/build/%a/"
job_right job_right
Uuidm.pp build_right.uuid)] Uuidm.pp build_right.uuid)]
@ -598,110 +607,110 @@ let compare_builds job_left job_right
pp_ptime build_right.start pp_ptime build_right.start
pp_platform (Some build_right.platform)]; pp_platform (Some build_right.platform)];
]; ];
h3 [ a ~a:[ H.h3 [ H.a ~a:H.[
Fmt.kstr a_href "/compare/%a/%a/" Fmt.kstr a_href "/compare/%a/%a/"
Uuidm.pp build_right.uuid Uuidm.pp build_right.uuid
Uuidm.pp build_left.uuid ] Uuidm.pp build_left.uuid ]
[txt "Compare in reverse direction"]] ; [H.txt "Compare in reverse direction"]] ;
ul [ H.ul [
li [ H.li [
a ~a:[a_href "#opam-packages-removed"] H.a ~a:H.[a_href "#opam-packages-removed"]
[txtf "%d opam packages removed" [txtf "%d opam packages removed"
(OpamPackage.Set.cardinal left)] (OpamPackage.Set.cardinal left)]
]; ];
li [ H.li [
a ~a:[a_href "#opam-packages-installed"] H.a ~a:H.[a_href "#opam-packages-installed"]
[txtf "%d new opam packages installed" [txtf "%d new opam packages installed"
(OpamPackage.Set.cardinal right)] (OpamPackage.Set.cardinal right)]
]; ];
li [ H.li [
a ~a:[a_href "#opam-packages-version-diff"] H.a ~a:H.[a_href "#opam-packages-version-diff"]
[txtf "%d opam packages with version changes" [txtf "%d opam packages with version changes"
(List.length version_diff)] (List.length version_diff)]
]; ];
li [ H.li [
a ~a:[a_href "#opam-packages-opam-diff"] H.a ~a:H.[a_href "#opam-packages-opam-diff"]
[txtf "%d opam packages with changes in their opam file" [txtf "%d opam packages with changes in their opam file"
(List.length opam_diff)] (List.length opam_diff)]
]; ];
li [ H.li [
a ~a:[a_href "#opam-packages-unchanged"] H.a ~a:H.[a_href "#opam-packages-unchanged"]
[txtf "%d opam packages unchanged" (OpamPackage.Set.cardinal same)] [txtf "%d opam packages unchanged" (OpamPackage.Set.cardinal same)]
]; ];
li [ H.li [
a ~a:[a_href "#env-added"] H.a ~a:H.[a_href "#env-added"]
[ txtf "%d environment variables added" (List.length added_env)] [ txtf "%d environment variables added" (List.length added_env)]
]; ];
li [ H.li [
a ~a:[a_href "#env-removed"] H.a ~a:H.[a_href "#env-removed"]
[ txtf "%d environment variables removed" (List.length removed_env)] [ txtf "%d environment variables removed" (List.length removed_env)]
]; ];
li [ H.li [
a ~a:[a_href "#env-changed"] H.a ~a:H.[a_href "#env-changed"]
[ txtf "%d environment variables changed" (List.length changed_env)] [ txtf "%d environment variables changed" (List.length changed_env)]
]; ];
li [ H.li [
a ~a:[a_href "#pkgs-added"] H.a ~a:H.[a_href "#pkgs-added"]
[ txtf "%d system packages added" (List.length added_pkgs)] [ txtf "%d system packages added" (List.length added_pkgs)]
]; ];
li [ H.li [
a ~a:[a_href "#pkgs-removed"] H.a ~a:H.[a_href "#pkgs-removed"]
[ txtf "%d system packages removed" (List.length removed_pkgs)] [ txtf "%d system packages removed" (List.length removed_pkgs)]
]; ];
li [ H.li [
a ~a:[a_href "#pkgs-changed"] H.a ~a:H.[a_href "#pkgs-changed"]
[ txtf "%d system packages changed" (List.length changed_pkgs)] [ txtf "%d system packages changed" (List.length changed_pkgs)]
]; ];
]; ];
h3 ~a:[a_id "opam-packages-removed"] H.h3 ~a:H.[a_id "opam-packages-removed"]
[txt "Opam packages removed"]; [H.txt "Opam packages removed"];
code (packages left); H.code (packages left);
h3 ~a:[a_id "opam-packages-installed"] H.h3 ~a:H.[a_id "opam-packages-installed"]
[txt "New opam packages installed"]; [H.txt "New opam packages installed"];
code (packages right); H.code (packages right);
h3 ~a:[a_id "opam-packages-version-diff"] H.h3 ~a:H.[a_id "opam-packages-version-diff"]
[txt "Opam packages with version changes"]; [H.txt "Opam packages with version changes"];
code (package_diffs version_diff); H.code (package_diffs version_diff);
h3 ~a:[a_id "opam-packages-opam-diff"] H.h3 ~a:H.[a_id "opam-packages-opam-diff"]
[txt "Opam packages with changes in their opam file"]] @ [H.txt "Opam packages with changes in their opam file"]] @
opam_diffs opam_diff @ [ opam_diffs opam_diff @ [
h3 ~a:[a_id "opam-packages-unchanged"] H.h3 ~a:H.[a_id "opam-packages-unchanged"]
[txt "Unchanged opam packages"]; [H.txt "Unchanged opam packages"];
code (packages same); H.code (packages same);
h3 ~a:[a_id "env-added"] [txt "Environment variables added"]; H.h3 ~a:H.[a_id "env-added"] [H.txt "Environment variables added"];
code (key_values added_env); H.code (key_values added_env);
h3 ~a:[a_id "env-removed"] [txt "Environment variables removed"]; H.h3 ~a:H.[a_id "env-removed"] [H.txt "Environment variables removed"];
code (key_values removed_env); H.code (key_values removed_env);
h3 ~a:[a_id "env-changed"] [txt "Environment variables changed"]; H.h3 ~a:H.[a_id "env-changed"] [H.txt "Environment variables changed"];
code (key_value_changes changed_env); H.code (key_value_changes changed_env);
h3 ~a:[a_id "pkgs-added"] [txt "System packages added"]; H.h3 ~a:H.[a_id "pkgs-added"] [H.txt "System packages added"];
code (key_values added_pkgs); H.code (key_values added_pkgs);
h3 ~a:[a_id "pkgs-removed"] [txt "System packages removed"]; H.h3 ~a:H.[a_id "pkgs-removed"] [H.txt "System packages removed"];
code (key_values removed_pkgs); H.code (key_values removed_pkgs);
h3 ~a:[a_id "pkgs-changed"] [txt "System packages changed"]; H.h3 ~a:H.[a_id "pkgs-changed"] [H.txt "System packages changed"];
code (key_value_changes changed_pkgs); H.code (key_value_changes changed_pkgs);
]) ])
let failed_builds ~start ~count builds = let failed_builds ~start ~count builds =
let build (job_name, build) = let build (job_name, build) =
li [ H.li [
check_icon build.Builder_db.Build.result; check_icon build.Builder_db.Build.result;
txtf " %s %a " job_name pp_platform (Some build.platform); txtf " %s %a " job_name pp_platform (Some build.platform);
a ~a:[Fmt.kstr a_href "/job/%s/build/%a/" job_name Uuidm.pp build.uuid] H.a ~a:H.[Fmt.kstr a_href "/job/%s/build/%a/" job_name Uuidm.pp build.uuid]
[txtf "%a" pp_ptime build.start]; [txtf "%a" pp_ptime build.start];
txtf " %a" Builder.pp_execution_result build.result; txtf " %a" Builder.pp_execution_result build.result;
] ]
in in
layout ~title:"Failed builds" layout ~title:"Failed builds"
([ ([
h1 [txt "Failed builds"]; H.h1 [H.txt "Failed builds"];
ul (List.map build builds); H.ul (List.map build builds);
p [ txtf "View the next %d failed builds " count; H.p [ txtf "View the next %d failed builds " count;
a ~a:[ H.a ~a:H.[
Fmt.kstr a_href "/failed-builds/?count=%d&start=%d" Fmt.kstr a_href "/failed-builds/?count=%d&start=%d"
count (start + count) ] count (start + count) ]
[ txt "here"]; [ H.txt "here"];
txt "."; H.txt ".";
] ]
]) ])