2022-02-03 11:54:02 +00:00
|
|
|
module H = Tyxml.Html
|
2020-12-02 13:33:15 +00:00
|
|
|
|
2021-11-17 14:44:41 +00:00
|
|
|
let pp_ptime ppf ptime =
|
|
|
|
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
|
2021-02-15 11:56:14 +00:00
|
|
|
|
2022-02-03 11:54:02 +00:00
|
|
|
let txtf fmt = Fmt.kstr H.txt fmt
|
|
|
|
let a_titlef fmt = Fmt.kstr H.a_title fmt
|
2020-12-07 09:17:49 +00:00
|
|
|
|
2020-12-07 15:45:19 +00:00
|
|
|
let check_icon result =
|
|
|
|
match result with
|
|
|
|
| Builder.Exited 0 ->
|
2022-02-03 11:54:02 +00:00
|
|
|
H.span ~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
a_style "color: green; cursor: pointer;";
|
|
|
|
a_titlef "%a" Builder.pp_execution_result result;
|
|
|
|
]
|
2022-02-03 11:54:02 +00:00
|
|
|
[H.txt "☑"]
|
2020-12-07 15:45:19 +00:00
|
|
|
| _ ->
|
2022-02-03 11:54:02 +00:00
|
|
|
H.span ~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
a_style "color: red; cursor: pointer;";
|
|
|
|
a_titlef "%a" Builder.pp_execution_result result;
|
|
|
|
]
|
2022-02-03 11:54:02 +00:00
|
|
|
[H.txt "☒"]
|
2020-12-07 15:33:19 +00:00
|
|
|
|
2021-11-12 11:11:08 +00:00
|
|
|
type nav = [
|
|
|
|
| `Default
|
|
|
|
| `Job of string * string option
|
|
|
|
| `Build of string * Builder_db.Build.t
|
|
|
|
| `Comparison of (string * Builder_db.Build.t) * (string * Builder_db.Build.t)
|
|
|
|
]
|
|
|
|
|
2022-02-02 22:27:25 +00:00
|
|
|
let pp_platform =
|
|
|
|
Fmt.(option ~none:(any "") (append (any "on ") string))
|
|
|
|
let pp_platform_query =
|
|
|
|
Fmt.(option ~none:(any "") (append (any "?platform=") string))
|
2021-11-12 11:11:08 +00:00
|
|
|
|
2021-12-13 16:46:37 +00:00
|
|
|
let static_css = Tyxml.Html.Unsafe.data {|
|
|
|
|
body {
|
|
|
|
margin: 40px auto;
|
|
|
|
line-height: 1.6;
|
|
|
|
color: #444;
|
2021-12-15 21:27:25 +00:00
|
|
|
background: rgb(200,200,200);
|
2021-12-13 16:46:37 +00:00
|
|
|
padding: 0 10px;
|
|
|
|
}
|
|
|
|
nav ul {
|
|
|
|
display: flex;
|
|
|
|
list-style: none;
|
|
|
|
}
|
|
|
|
nav ul li::before {
|
|
|
|
content: "→";
|
|
|
|
}
|
|
|
|
nav ul li:first-child::before {
|
|
|
|
content: "";
|
|
|
|
}
|
|
|
|
nav a {
|
|
|
|
padding: .5em 1em;
|
|
|
|
}
|
|
|
|
h1,h2,h3{line-height:1.2}
|
|
|
|
.output-ts {
|
|
|
|
white-space: nowrap;
|
|
|
|
cursor: pointer;
|
|
|
|
user-select: none;
|
|
|
|
}
|
|
|
|
.output-ts a {text-decoration: none;}
|
|
|
|
.output-ts a:hover {text-decoration: underline;}
|
|
|
|
.output-code {
|
|
|
|
overflow: visible;
|
|
|
|
white-space: pre;
|
|
|
|
}
|
|
|
|
.toggleable {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
.toggleable-descr {
|
|
|
|
cursor: pointer;
|
|
|
|
text-decoration: underline;
|
|
|
|
user-select: none;
|
|
|
|
}
|
|
|
|
:checked + .toggleable {
|
|
|
|
display: block;
|
|
|
|
}
|
|
|
|
|}
|
|
|
|
|
2022-02-07 15:38:12 +00:00
|
|
|
let make_breadcrumbs nav =
|
|
|
|
let to_nav kvs =
|
|
|
|
H.nav [
|
|
|
|
H.ul (
|
|
|
|
List.map (fun (desc, href) ->
|
|
|
|
H.li [H.a ~a:H.[a_href href] [desc]]
|
|
|
|
) kvs
|
|
|
|
)]
|
2021-11-12 11:11:08 +00:00
|
|
|
in
|
2022-02-07 15:38:12 +00:00
|
|
|
match nav with
|
|
|
|
| `Default ->
|
|
|
|
to_nav [H.txt "Home", "/"]
|
|
|
|
| `Job (job_name, platform) ->
|
|
|
|
to_nav [
|
|
|
|
H.txt "Home", "/";
|
|
|
|
txtf "Job %s" job_name, Fmt.str "/job/%s/" job_name ;
|
|
|
|
(
|
|
|
|
txtf "%a" pp_platform platform,
|
|
|
|
Fmt.str "/job/%s/%a" job_name pp_platform_query platform
|
|
|
|
)
|
|
|
|
]
|
|
|
|
| `Build (job_name, build) ->
|
|
|
|
to_nav [
|
|
|
|
H.txt "Home", "/";
|
|
|
|
txtf "Job %s" job_name, Fmt.str "/job/%s/" job_name;
|
|
|
|
(
|
|
|
|
txtf "%a" pp_platform (Some build.Builder_db.Build.platform),
|
|
|
|
Fmt.str "/job/%s/%a"
|
|
|
|
job_name
|
|
|
|
pp_platform_query (Some build.Builder_db.Build.platform)
|
|
|
|
);
|
|
|
|
(
|
|
|
|
txtf "Build %a" pp_ptime build.Builder_db.Build.start,
|
|
|
|
Fmt.str "/job/%s/build/%a/"
|
|
|
|
job_name
|
|
|
|
Uuidm.pp build.Builder_db.Build.uuid
|
|
|
|
);
|
|
|
|
]
|
|
|
|
| `Comparison ((job_left, build_left), (job_right, build_right)) ->
|
|
|
|
to_nav [
|
|
|
|
H.txt "Home", "/";
|
|
|
|
(
|
|
|
|
txtf "Comparison between %s@%a and %s@%a"
|
|
|
|
job_left pp_ptime build_left.Builder_db.Build.start
|
|
|
|
job_right pp_ptime build_right.Builder_db.Build.start,
|
|
|
|
Fmt.str "/compare/%a/%a/"
|
|
|
|
Uuidm.pp build_left.uuid
|
|
|
|
Uuidm.pp build_right.uuid
|
|
|
|
);
|
|
|
|
]
|
|
|
|
|
|
|
|
let layout
|
|
|
|
?include_static_css
|
|
|
|
?(nav=`Default)
|
|
|
|
?(manual_width=false)
|
|
|
|
~title
|
|
|
|
body
|
|
|
|
=
|
|
|
|
let breadcrumb = make_breadcrumbs nav in
|
2021-12-13 16:46:37 +00:00
|
|
|
(*> Note: Last declared CSS wins - so one can override here*)
|
2022-02-01 11:43:07 +00:00
|
|
|
let static_css = static_css :: Option.to_list include_static_css
|
2021-12-13 16:27:33 +00:00
|
|
|
in
|
2022-02-07 15:38:12 +00:00
|
|
|
let body =
|
|
|
|
let style_grid_container = H.a_style "\
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
min-width: 83em;
|
|
|
|
"
|
|
|
|
and style_grid = H.a_style @@
|
|
|
|
if manual_width then "" else "\
|
|
|
|
width: 76%;\
|
|
|
|
"
|
|
|
|
in
|
|
|
|
[ H.div ~a:[ style_grid_container ]
|
|
|
|
[ H.div ~a:[ style_grid ] body ]]
|
|
|
|
in
|
2022-02-03 11:54:02 +00:00
|
|
|
H.html
|
|
|
|
(H.head (H.title (H.txt title))
|
2022-02-03 13:00:24 +00:00
|
|
|
[H.style ~a:H.[a_mime_type "text/css"] static_css])
|
2022-02-03 11:54:02 +00:00
|
|
|
(H.body [
|
2022-02-03 18:39:51 +00:00
|
|
|
breadcrumb;
|
|
|
|
H.main body
|
|
|
|
])
|
2020-12-02 13:33:15 +00:00
|
|
|
|
2022-02-03 12:27:22 +00:00
|
|
|
let toggleable ?(hidden=true) ~id ~description content =
|
2022-02-03 11:54:02 +00:00
|
|
|
let checked = if hidden then [] else H.[a_checked ()] in
|
|
|
|
H.div [
|
|
|
|
H.label
|
|
|
|
~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
a_label_for id;
|
|
|
|
a_class ["toggleable-descr"];
|
|
|
|
]
|
2022-02-03 11:54:02 +00:00
|
|
|
[H.txt description];
|
|
|
|
H.input
|
|
|
|
~a:(checked @ H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
a_input_type `Checkbox;
|
|
|
|
a_id id;
|
|
|
|
a_style "display: none;";
|
|
|
|
]) ();
|
2022-02-03 11:54:02 +00:00
|
|
|
H.div
|
|
|
|
~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
a_class ["toggleable"]
|
|
|
|
]
|
2020-12-21 10:22:35 +00:00
|
|
|
content;
|
|
|
|
]
|
|
|
|
|
2022-02-02 22:27:25 +00:00
|
|
|
let artifact
|
2022-02-03 12:27:22 +00:00
|
|
|
~basename
|
|
|
|
~job_name
|
|
|
|
~build
|
|
|
|
~file:{ Builder_db.filepath; localpath = _; sha256; size }
|
2022-02-02 22:27:25 +00:00
|
|
|
=
|
|
|
|
let artifact_link =
|
|
|
|
Fmt.str "/job/%s/build/%a/f/%a"
|
|
|
|
job_name
|
|
|
|
Uuidm.pp build.Builder_db.Build.uuid
|
|
|
|
Fpath.pp filepath
|
|
|
|
in
|
2021-02-25 14:18:43 +00:00
|
|
|
[
|
2022-02-03 13:42:33 +00:00
|
|
|
H.a ~a:H.[a_href artifact_link] [
|
|
|
|
if basename then H.txt (Fpath.basename filepath)
|
|
|
|
else txtf "%a" Fpath.pp filepath
|
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.txt " ";
|
|
|
|
H.code [txtf "SHA256:%a" Hex.pp (Hex.of_cstruct sha256)];
|
2021-02-26 09:00:37 +00:00
|
|
|
txtf " (%a)" Fmt.byte_size size;
|
2021-02-25 14:18:43 +00:00
|
|
|
]
|
|
|
|
|
2022-02-09 15:23:05 +00:00
|
|
|
let resource_not_found ~text =
|
|
|
|
[
|
|
|
|
H.h2 ~a:[ H.a_style "padding-top: 33vh" ]
|
|
|
|
[ txtf "This resource does not exist" ];
|
|
|
|
H.p [
|
|
|
|
H.txt @@ Fmt.str "Error: '%s'" text
|
|
|
|
];
|
|
|
|
]
|
|
|
|
|> layout ~title:"Resource not found"
|
|
|
|
|
|
|
|
let page_not_found ~path ~referer =
|
|
|
|
[
|
|
|
|
H.h2 ~a:[ H.a_style "padding-top: 33vh" ]
|
|
|
|
[ txtf "This page does not exist" ];
|
|
|
|
H.p [
|
|
|
|
H.txt @@ Fmt.str "You requested the page %s" path
|
|
|
|
];
|
|
|
|
] @ (
|
|
|
|
match referer with
|
|
|
|
| None -> []
|
|
|
|
| Some prev_url -> [
|
|
|
|
H.p [
|
|
|
|
H.txt "Go back to ";
|
|
|
|
H.a ~a:H.[ a_href prev_url ] [ H.txt prev_url ];
|
|
|
|
];
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> layout ~title:"Page not found"
|
|
|
|
|
2022-02-07 13:51:56 +00:00
|
|
|
module Builds = struct
|
2020-12-21 10:22:35 +00:00
|
|
|
|
2022-03-01 20:54:31 +00:00
|
|
|
let data =
|
|
|
|
{|
|
|
|
|
# Reproducible OPAM builds
|
|
|
|
|
|
|
|
This website offers binary MirageOS unikernels and supplementary OS packages.
|
|
|
|
If you want to use our binary packages and setup unikernels, follow
|
|
|
|
[these instructions](https://robur.coop/Projects/Reproducible_builds).
|
|
|
|
The unikernels are statically linked executables where the execution target is
|
|
|
|
independent of the build platform - so even if they're compiled on a FreeBSD
|
|
|
|
system they can be run on a Linux or OpenBSD host. Many are executed using a
|
|
|
|
[solo5](https://github.com/solo5/solo5) tender.
|
|
|
|
The filename suffix of the unikernel binary indicate the expected execution environment:
|
|
|
|
- `.hvt`: hardware virtualized - requires `solo5-hvt`
|
|
|
|
([Linux KVM](https://www.linux-kvm.org/page/Main_Page),
|
|
|
|
[FreeBSD BHyve](https://wiki.freebsd.org/bhyve),
|
|
|
|
[OpenBSD VMM](https://man.openbsd.org/vmm)),
|
|
|
|
- `.spt`: sandboxed process - requires `solo5-spt` (Linux with seccomp),
|
|
|
|
- `.xen`: Xen PVH virtual machine (on a Xen or QubesOS host),
|
|
|
|
- `.virtio`: any virtio environment (qemu, GCE, KVM, BHyve),
|
|
|
|
- `.muen`: on [muen](https://muen.sk).
|
|
|
|
|
|
|
|
A persistent link to the latest successful build is available as
|
|
|
|
`/job/*jobname*/build/latest/`. Each build can be reproduced with
|
|
|
|
[orb](https://github.com/roburio/orb/). The builds are scheduled and executed
|
|
|
|
daily by [builder](https://github.com/roburio/builder/). This web interface is
|
|
|
|
[builder-web](https://git.robur.io/robur/builder-web/). Read further information
|
|
|
|
[on our project page](https://robur.coop/Projects/Reproducible_builds). This
|
|
|
|
work has been funded by the European Union under the
|
|
|
|
[NGI Pointer](https://pointer.ngi.eu) program. Contact team ATrobur.coop if you
|
|
|
|
have questions or suggestions.
|
|
|
|
|}
|
|
|
|
|
2022-02-03 12:50:32 +00:00
|
|
|
let make_header =
|
|
|
|
[
|
2022-03-01 20:54:31 +00:00
|
|
|
H.Unsafe.data (Utils.Omd.html_of_string data);
|
2022-02-03 13:42:33 +00:00
|
|
|
H.form ~a:H.[a_action "/hash"; a_method `Get] [
|
|
|
|
H.label [
|
|
|
|
H.txt "Search artifact by SHA256";
|
|
|
|
H.br ();
|
2022-02-03 12:50:32 +00:00
|
|
|
H.input ~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
a_input_type `Search;
|
|
|
|
a_id "sha256";
|
|
|
|
a_name "sha256";
|
|
|
|
] ();
|
2022-02-03 12:50:32 +00:00
|
|
|
];
|
2022-02-03 13:42:33 +00:00
|
|
|
H.input ~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
a_input_type `Submit;
|
|
|
|
a_value "Search";
|
|
|
|
] ();
|
2022-02-03 13:42:33 +00:00
|
|
|
];
|
2022-02-03 12:50:32 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
let make_platform_builds ~job_name (platform, latest_build, latest_artifact) =
|
|
|
|
[
|
|
|
|
check_icon latest_build.Builder_db.Build.result;
|
|
|
|
H.txt " ";
|
|
|
|
H.a ~a:[
|
|
|
|
Fmt.kstr H.a_href "job/%s/%a"
|
|
|
|
job_name
|
|
|
|
pp_platform_query (Some platform)]
|
|
|
|
[H.txt platform];
|
|
|
|
H.txt " ";
|
|
|
|
H.a ~a:[
|
|
|
|
Fmt.kstr H.a_href "job/%s/build/%a/"
|
|
|
|
job_name
|
|
|
|
Uuidm.pp latest_build.Builder_db.Build.uuid]
|
|
|
|
[txtf "%a" pp_ptime latest_build.Builder_db.Build.start];
|
|
|
|
H.txt " ";
|
2022-02-03 13:32:04 +00:00
|
|
|
]
|
|
|
|
@ (match latest_artifact with
|
2022-02-03 18:39:51 +00:00
|
|
|
| Some main_binary ->
|
|
|
|
artifact
|
|
|
|
~basename:true
|
|
|
|
~job_name
|
|
|
|
~build:latest_build
|
|
|
|
~file:main_binary
|
|
|
|
| None ->
|
|
|
|
[ txtf "Build failure: %a" Builder.pp_execution_result
|
|
|
|
latest_build.Builder_db.Build.result ]
|
|
|
|
)
|
2022-02-03 13:32:04 +00:00
|
|
|
@ [ H.br () ]
|
2022-02-03 12:50:32 +00:00
|
|
|
|
|
|
|
let make_jobs jobs =
|
|
|
|
jobs |> List.map (fun (job_name, synopsis, platform_builds) ->
|
2022-02-03 18:39:51 +00:00
|
|
|
H.li (
|
|
|
|
[
|
|
|
|
H.a ~a:H.[a_href ("job/" ^ job_name ^ "/")]
|
|
|
|
[H.txt job_name];
|
|
|
|
H.br ();
|
|
|
|
H.txt (Option.value ~default:"" synopsis);
|
|
|
|
H.br ()
|
|
|
|
]
|
|
|
|
@ List.concat_map (make_platform_builds ~job_name) platform_builds
|
|
|
|
)
|
2022-02-03 13:42:33 +00:00
|
|
|
)
|
2022-02-03 12:50:32 +00:00
|
|
|
|
|
|
|
let make_body section_job_map =
|
|
|
|
let aux section jobs acc =
|
|
|
|
acc @ [
|
|
|
|
H.h2 [ H.txt section ];
|
|
|
|
H.ul (make_jobs jobs)
|
|
|
|
]
|
|
|
|
in
|
|
|
|
Utils.String_map.fold aux section_job_map []
|
|
|
|
|
2022-02-03 13:42:33 +00:00
|
|
|
let make_failed_builds =
|
|
|
|
[ H.p [
|
2022-02-03 18:39:51 +00:00
|
|
|
H.txt "View the latest failed builds ";
|
|
|
|
H.a ~a:H.[a_href "/failed-builds/"]
|
|
|
|
[H.txt "here"];
|
|
|
|
H.txt "."
|
|
|
|
]]
|
2022-02-03 13:42:33 +00:00
|
|
|
|
2022-02-03 12:50:32 +00:00
|
|
|
let make section_job_map =
|
|
|
|
layout ~title:"Reproducible OPAM builds"
|
|
|
|
(make_header
|
|
|
|
@ make_body section_job_map
|
2022-02-03 13:42:33 +00:00
|
|
|
@ make_failed_builds)
|
2021-12-01 16:21:12 +00:00
|
|
|
|
2022-02-02 22:03:16 +00:00
|
|
|
end
|
2020-12-07 09:17:49 +00:00
|
|
|
|
2022-01-25 13:58:25 +00:00
|
|
|
module Job = struct
|
2022-02-01 11:43:07 +00:00
|
|
|
|
2022-02-03 13:50:17 +00:00
|
|
|
let make_header ~job_name ~platform ~readme =
|
2022-02-07 13:51:56 +00:00
|
|
|
H.h1 [txtf "Job %s %a" job_name pp_platform platform]
|
2022-02-03 13:50:17 +00:00
|
|
|
:: (
|
|
|
|
match readme with
|
|
|
|
| None -> []
|
|
|
|
| Some data ->
|
|
|
|
[
|
|
|
|
H.h2 ~a:H.[a_id "readme"] [H.txt "README"];
|
|
|
|
H.a ~a:H.[a_href "#builds"] [H.txt "Skip to builds"];
|
|
|
|
H.Unsafe.data (Utils.Omd.html_of_string data)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
let make_build ~job_name (build, main_binary) =
|
|
|
|
H.li (
|
|
|
|
[
|
|
|
|
check_icon build.Builder_db.Build.result;
|
|
|
|
txtf " %s " build.platform;
|
|
|
|
H.a ~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
Fmt.kstr a_href "/job/%s/build/%a/"
|
|
|
|
job_name
|
|
|
|
Uuidm.pp build.Builder_db.Build.uuid ]
|
2022-02-03 13:50:17 +00:00
|
|
|
[
|
|
|
|
txtf "%a" pp_ptime build.Builder_db.Build.start;
|
|
|
|
];
|
|
|
|
H.txt " ";
|
|
|
|
]
|
|
|
|
@ match main_binary with
|
|
|
|
| Some main_binary ->
|
|
|
|
artifact
|
|
|
|
~basename:true
|
|
|
|
~job_name
|
|
|
|
~build
|
|
|
|
~file:main_binary
|
|
|
|
| None ->
|
|
|
|
[ txtf "Build failure: %a" Builder.pp_execution_result
|
|
|
|
build.Builder_db.Build.result ]
|
|
|
|
)
|
2022-02-03 18:39:51 +00:00
|
|
|
|
2022-02-08 10:40:05 +00:00
|
|
|
let make_builds ~failed ~job_name ~platform builds =
|
2022-02-03 13:50:17 +00:00
|
|
|
[
|
|
|
|
H.h2 ~a:H.[a_id "builds"] [H.txt "Builds"];
|
|
|
|
H.a ~a:H.[a_href "#readme"] [H.txt "Back to readme"];
|
|
|
|
H.ul (builds |> List.map (make_build ~job_name));
|
|
|
|
if failed then
|
|
|
|
H.p [
|
|
|
|
H.txt "Excluding failed builds " ;
|
2022-02-08 10:40:05 +00:00
|
|
|
H.a ~a:H.[
|
|
|
|
a_href @@ Fmt.str "../%a" pp_platform_query platform
|
|
|
|
]
|
|
|
|
[H.txt "here"] ;
|
2022-02-03 13:50:17 +00:00
|
|
|
H.txt "." ]
|
|
|
|
else
|
|
|
|
H.p [
|
|
|
|
H.txt "Including failed builds " ;
|
2022-02-08 10:40:05 +00:00
|
|
|
H.a ~a:H.[
|
|
|
|
a_href @@ Fmt.str "failed/%a" pp_platform_query platform
|
|
|
|
]
|
|
|
|
[H.txt "here"] ;
|
2022-02-03 13:50:17 +00:00
|
|
|
H.txt "." ]
|
|
|
|
]
|
|
|
|
|
|
|
|
let make_body ~failed ~job_name ~platform ~readme builds =
|
|
|
|
make_header ~job_name ~platform ~readme
|
2022-02-08 10:40:05 +00:00
|
|
|
@ make_builds ~failed ~job_name ~platform builds
|
2022-02-03 13:50:17 +00:00
|
|
|
|
2022-02-03 12:27:22 +00:00
|
|
|
let make ~failed ~job_name ~platform ~readme builds =
|
2022-02-03 13:50:17 +00:00
|
|
|
let nav = `Job (job_name, platform) in
|
|
|
|
let title = Fmt.str "Job %s %a" job_name pp_platform platform in
|
|
|
|
layout ~nav ~title @@ make_body ~failed ~job_name ~platform ~readme builds
|
2022-02-03 18:39:51 +00:00
|
|
|
|
2020-12-07 09:17:49 +00:00
|
|
|
|
2022-02-02 22:03:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
module Job_build = struct
|
|
|
|
|
2022-01-25 13:58:25 +00:00
|
|
|
let contains_debug_bin artifacts =
|
|
|
|
let check f =
|
2022-02-01 11:43:07 +00:00
|
|
|
Fpath.has_ext "debug" f.Builder_db.filepath
|
2022-01-25 13:58:25 +00:00
|
|
|
in
|
2022-01-28 10:05:09 +00:00
|
|
|
List.exists check artifacts
|
2021-12-20 14:52:11 +00:00
|
|
|
|
2021-12-14 11:02:35 +00:00
|
|
|
let make_artifacts ~artifacts ~main_binary ~solo5_manifest =
|
|
|
|
let solo5_devices solo5_manifest =
|
|
|
|
let pp_devices =
|
|
|
|
let pp_device_name ppf = function
|
|
|
|
| Solo5_elftool.Dev_block_basic name | Solo5_elftool.Dev_net_basic name ->
|
|
|
|
Fmt.pf ppf "%S" name
|
|
|
|
in
|
|
|
|
Fmt.(list ~sep:(any ", ") pp_device_name)
|
|
|
|
in
|
|
|
|
match
|
|
|
|
List.partition (function Solo5_elftool.Dev_block_basic _ -> true | _ -> false)
|
|
|
|
solo5_manifest.Solo5_elftool.entries
|
|
|
|
with
|
|
|
|
| [], [] -> [txtf "with no devices in solo5 manifest"]
|
|
|
|
| (_::_) as block_devices, [] ->
|
|
|
|
[txtf "with block devices %a" pp_devices block_devices]
|
|
|
|
| [], ((_::_) as net_devices) ->
|
|
|
|
[txtf "with net devices %a" pp_devices net_devices]
|
|
|
|
| block_devices, net_devices ->
|
|
|
|
[txtf "with block devices %a, and net devices %a"
|
|
|
|
pp_devices block_devices pp_devices net_devices]
|
|
|
|
in
|
2022-02-03 19:06:55 +00:00
|
|
|
let aux (file:Builder_db.file) =
|
|
|
|
let (`Hex sha256_hex) = Hex.of_cstruct file.sha256 in
|
|
|
|
[
|
|
|
|
H.dt [
|
|
|
|
H.a ~a:H.[Fmt.kstr a_href "f/%a" Fpath.pp file.filepath]
|
|
|
|
[H.code [txtf "%a" Fpath.pp file.filepath]] ];
|
2021-12-14 11:02:35 +00:00
|
|
|
H.dd ([
|
|
|
|
H.code [H.txt "SHA256:"; H.txt sha256_hex];
|
|
|
|
txtf " (%a)" Fmt.byte_size file.size;
|
|
|
|
] @
|
|
|
|
match main_binary, solo5_manifest with
|
|
|
|
| Some main_binary, Some solo5_manifest when main_binary = file ->
|
|
|
|
(H.br () :: solo5_devices solo5_manifest)
|
|
|
|
| _ -> []);
|
2022-02-03 19:06:55 +00:00
|
|
|
]
|
|
|
|
in
|
|
|
|
[
|
|
|
|
H.h3 [H.txt "Build artifacts"];
|
|
|
|
H.dl (List.concat_map aux artifacts)
|
|
|
|
]
|
|
|
|
|
|
|
|
let make_reproductions
|
2022-02-02 22:03:16 +00:00
|
|
|
~name
|
2022-02-03 11:57:21 +00:00
|
|
|
~(build:Builder_db.Build.t)
|
2022-02-02 22:03:16 +00:00
|
|
|
~same_input_same_output
|
|
|
|
~different_input_same_output
|
|
|
|
=
|
2022-02-03 19:06:55 +00:00
|
|
|
let same_input_same_output_html =
|
|
|
|
List.map (fun (build:Builder_db.Build.t) ->
|
|
|
|
H.li [
|
|
|
|
txtf "on %s, same input, " build.platform;
|
|
|
|
H.a ~a:H.[Fmt.kstr a_href "/job/%s/build/%a/" name Uuidm.pp build.uuid]
|
|
|
|
[txtf "%a" pp_ptime build.start]
|
|
|
|
])
|
|
|
|
same_input_same_output
|
|
|
|
in
|
|
|
|
let different_input_same_output_html =
|
|
|
|
List.map (fun (build':Builder_db.Build.t) ->
|
|
|
|
H.li [
|
|
|
|
txtf "on %s, different input, " build'.platform;
|
|
|
|
H.a ~a:H.[
|
|
|
|
Fmt.kstr a_href "/compare/%a/%a/"
|
|
|
|
Uuidm.pp build'.uuid
|
|
|
|
Uuidm.pp build.uuid]
|
|
|
|
[txtf "%a" pp_ptime build'.start]
|
2022-02-03 18:39:51 +00:00
|
|
|
])
|
2022-02-03 19:06:55 +00:00
|
|
|
different_input_same_output
|
|
|
|
in
|
|
|
|
[
|
2022-02-03 11:54:02 +00:00
|
|
|
H.h3 [
|
2022-02-02 22:27:25 +00:00
|
|
|
txtf "Reproduced by %d builds"
|
|
|
|
(List.length (same_input_same_output @ different_input_same_output))] ;
|
2022-02-03 19:06:55 +00:00
|
|
|
H.ul @@ (
|
|
|
|
same_input_same_output_html
|
|
|
|
@ different_input_same_output_html
|
2022-02-03 13:00:24 +00:00
|
|
|
)
|
2022-02-03 19:06:55 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
let make_not_reproducible
|
|
|
|
~(build:Builder_db.Build.t)
|
|
|
|
~same_input_different_output
|
|
|
|
=
|
|
|
|
if same_input_different_output = [] then
|
|
|
|
[]
|
|
|
|
else
|
|
|
|
[ H.h3 [H.txt "Same input, different output (not reproducible!)"];
|
|
|
|
H.ul (
|
|
|
|
List.map (fun (build':Builder_db.Build.t) ->
|
|
|
|
H.li [
|
|
|
|
txtf "on %s, " build'.platform ;
|
|
|
|
H.a ~a:H.[
|
|
|
|
Fmt.kstr a_href "/compare/%a/%a/"
|
|
|
|
Uuidm.pp build'.uuid
|
|
|
|
Uuidm.pp build.uuid]
|
|
|
|
[txtf "%a" pp_ptime build'.start]
|
|
|
|
])
|
|
|
|
same_input_different_output)
|
|
|
|
]
|
|
|
|
|
|
|
|
let make_comparisons_same_platform
|
|
|
|
~(build:Builder_db.Build.t)
|
|
|
|
~previous
|
|
|
|
~latest
|
|
|
|
~next
|
|
|
|
=
|
|
|
|
[
|
2022-02-03 11:54:02 +00:00
|
|
|
H.h3 [H.txt "Comparisons with other builds on the same platform"];
|
2022-02-02 22:03:16 +00:00
|
|
|
let opt_build (ctx, build') =
|
|
|
|
match build' with
|
|
|
|
| Some b when not (Uuidm.equal build.uuid b.Builder_db.Build.uuid) ->
|
2022-02-03 11:54:02 +00:00
|
|
|
[ H.li [ H.txt ctx;
|
2022-02-03 13:00:24 +00:00
|
|
|
H.a ~a:[
|
|
|
|
Fmt.kstr H.a_href "/compare/%a/%a/"
|
|
|
|
Uuidm.pp b.uuid
|
|
|
|
Uuidm.pp build.uuid ]
|
|
|
|
[txtf "%a" pp_ptime b.start]]
|
2021-12-13 16:27:33 +00:00
|
|
|
]
|
2022-02-02 22:03:16 +00:00
|
|
|
| _ -> []
|
|
|
|
in
|
2022-02-03 11:54:02 +00:00
|
|
|
H.ul
|
2022-02-02 22:03:16 +00:00
|
|
|
(List.concat_map opt_build
|
2022-02-03 13:00:24 +00:00
|
|
|
[ ("Latest build ", latest) ;
|
|
|
|
("Later build with different output ", next) ;
|
|
|
|
("Earlier build with different output ", previous) ])
|
2022-02-02 22:03:16 +00:00
|
|
|
]
|
2022-01-25 13:58:25 +00:00
|
|
|
|
2022-02-03 19:06:55 +00:00
|
|
|
let make_build_info
|
|
|
|
~name
|
|
|
|
~delta
|
|
|
|
~(build:Builder_db.Build.t)
|
|
|
|
~artifacts
|
2021-12-14 11:02:35 +00:00
|
|
|
~main_binary
|
|
|
|
~solo5_manifest
|
2022-02-03 19:06:55 +00:00
|
|
|
~same_input_same_output
|
|
|
|
~different_input_same_output
|
|
|
|
~same_input_different_output
|
|
|
|
~latest ~next ~previous
|
|
|
|
=
|
|
|
|
[
|
|
|
|
H.h2 ~a:H.[a_id "build"] [txtf "Build %a" pp_ptime build.start];
|
|
|
|
H.p [txtf "Built on platform %s" build.platform ];
|
|
|
|
H.p [txtf "Build took %a." Ptime.Span.pp delta ];
|
|
|
|
H.p [txtf "Execution result: %a." Builder.pp_execution_result build.result];
|
|
|
|
H.h3 [H.txt "Build info"];
|
|
|
|
H.ul [
|
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[
|
|
|
|
Fmt.kstr a_href "/job/%s/build/%a/console" name Uuidm.pp build.uuid
|
|
|
|
] [H.txt "Console output"];
|
|
|
|
];
|
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[
|
|
|
|
Fmt.kstr a_href "/job/%s/build/%a/script" name Uuidm.pp build.uuid
|
|
|
|
] [H.txt "Build script"];
|
|
|
|
]
|
|
|
|
];
|
|
|
|
]
|
2021-12-14 11:02:35 +00:00
|
|
|
@ make_artifacts ~artifacts ~main_binary ~solo5_manifest
|
2022-02-03 19:06:55 +00:00
|
|
|
@ make_reproductions
|
|
|
|
~name
|
|
|
|
~build
|
|
|
|
~same_input_same_output
|
|
|
|
~different_input_same_output
|
|
|
|
@ make_not_reproducible ~build ~same_input_different_output
|
|
|
|
@ make_comparisons_same_platform
|
|
|
|
~build
|
|
|
|
~previous
|
|
|
|
~latest
|
|
|
|
~next
|
|
|
|
|
2022-02-02 22:03:16 +00:00
|
|
|
let viz_style_deps = "
|
2022-02-07 15:38:12 +00:00
|
|
|
width: 45em;
|
2022-01-26 20:11:57 +00:00
|
|
|
height: 45.4em;
|
|
|
|
max-width: 100%;
|
2022-02-07 15:38:12 +00:00
|
|
|
max-height: 49vw;
|
2022-01-26 20:11:57 +00:00
|
|
|
min-width: 38em;
|
2022-02-07 15:38:12 +00:00
|
|
|
min-height: 40em;
|
2022-01-26 20:11:57 +00:00
|
|
|
"
|
|
|
|
|
2022-02-02 22:03:16 +00:00
|
|
|
let viz_style_treemap = "
|
2022-01-25 13:58:25 +00:00
|
|
|
width: 46em;
|
2022-01-26 16:20:18 +00:00
|
|
|
height: 48.4em;
|
2022-01-25 13:58:25 +00:00
|
|
|
max-width: 100%;
|
|
|
|
max-height: 52vw;
|
|
|
|
min-width: 38em;
|
2022-02-07 15:38:12 +00:00
|
|
|
min-height: 43em;
|
2022-01-25 13:58:25 +00:00
|
|
|
"
|
2022-02-01 11:43:07 +00:00
|
|
|
|
2022-02-02 22:03:16 +00:00
|
|
|
let make_viz_section ~name ~artifacts ~uuid =
|
2022-02-03 19:11:36 +00:00
|
|
|
let viz_deps_iframe = [
|
|
|
|
let src = Fmt.str "/job/%s/build/%a/vizdependencies" name Uuidm.pp uuid in
|
|
|
|
H.iframe ~a:H.[
|
|
|
|
a_src src;
|
|
|
|
a_title "Opam dependencies";
|
|
|
|
a_style viz_style_deps
|
|
|
|
] []
|
|
|
|
]
|
|
|
|
in
|
|
|
|
let viz_treemap_iframe = lazy [
|
|
|
|
let src = Fmt.str "/job/%s/build/%a/viztreemap" name Uuidm.pp uuid in
|
|
|
|
H.iframe ~a:H.[
|
|
|
|
a_src src;
|
|
|
|
a_title "Binary dissection";
|
|
|
|
a_style viz_style_treemap
|
|
|
|
] []
|
|
|
|
]
|
|
|
|
in
|
|
|
|
List.flatten [
|
|
|
|
[ H.p viz_deps_iframe];
|
2022-02-02 22:03:16 +00:00
|
|
|
if not @@ contains_debug_bin artifacts then [] else [
|
2022-02-03 19:11:36 +00:00
|
|
|
H.p @@ Lazy.force viz_treemap_iframe ];
|
2022-02-07 13:51:56 +00:00
|
|
|
]
|
2022-01-25 13:58:25 +00:00
|
|
|
|
2022-02-02 22:03:16 +00:00
|
|
|
let make
|
|
|
|
~name
|
|
|
|
~(build:Builder_db.Build.t)
|
|
|
|
~artifacts
|
2021-12-14 11:02:35 +00:00
|
|
|
~main_binary
|
|
|
|
~solo5_manifest
|
2022-02-02 22:03:16 +00:00
|
|
|
~same_input_same_output
|
|
|
|
~different_input_same_output
|
|
|
|
~same_input_different_output
|
|
|
|
~latest ~next ~previous
|
|
|
|
=
|
|
|
|
let delta = Ptime.diff build.finish build.start in
|
|
|
|
let right_column = make_viz_section ~name ~artifacts ~uuid:build.uuid in
|
|
|
|
let left_column =
|
|
|
|
make_build_info
|
2022-01-25 13:58:25 +00:00
|
|
|
~name
|
2022-02-02 22:03:16 +00:00
|
|
|
~delta
|
|
|
|
~build
|
2022-01-25 13:58:25 +00:00
|
|
|
~artifacts
|
2021-12-14 11:02:35 +00:00
|
|
|
~main_binary
|
|
|
|
~solo5_manifest
|
2022-01-25 13:58:25 +00:00
|
|
|
~same_input_same_output
|
|
|
|
~different_input_same_output
|
|
|
|
~same_input_different_output
|
|
|
|
~latest ~next ~previous
|
2022-02-02 22:03:16 +00:00
|
|
|
in
|
2022-02-03 11:54:02 +00:00
|
|
|
let style_grid = H.a_style "display: flex; " in
|
2022-02-02 22:27:25 +00:00
|
|
|
let style_col_left =
|
2022-02-07 15:38:12 +00:00
|
|
|
H.a_style "width: 45em; min-width: 43em;" in
|
2022-02-03 11:54:02 +00:00
|
|
|
let style_col_right = H.a_style "width: 50%" in
|
2022-02-02 22:03:16 +00:00
|
|
|
let body = [
|
2022-02-07 15:38:12 +00:00
|
|
|
H.h1 [txtf "Job %s" name];
|
|
|
|
H.div~a:[ style_grid ] [
|
|
|
|
H.div~a:[ style_col_left ] left_column;
|
|
|
|
H.div~a:[ style_col_right ] right_column
|
2022-01-25 13:58:25 +00:00
|
|
|
]
|
2022-02-02 22:03:16 +00:00
|
|
|
]
|
|
|
|
in
|
|
|
|
layout
|
|
|
|
~nav:(`Build (name, build))
|
|
|
|
~title:(Fmt.str "Job %s %a" name pp_ptime build.start)
|
2022-02-07 15:38:12 +00:00
|
|
|
~manual_width:true
|
2022-02-02 22:03:16 +00:00
|
|
|
body
|
2021-02-10 13:43:32 +00:00
|
|
|
|
2022-01-25 13:58:25 +00:00
|
|
|
end
|
2022-02-01 11:43:07 +00:00
|
|
|
|
2021-07-06 08:34:17 +00:00
|
|
|
let key_values xs =
|
2022-02-03 11:54:02 +00:00
|
|
|
List.concat_map (fun (k, v) -> [ txtf "%s %s" k v ; H.br () ]) xs
|
2021-07-06 08:34:17 +00:00
|
|
|
|
|
|
|
let key_value_changes xs =
|
2022-02-03 11:54:02 +00:00
|
|
|
List.concat_map (fun (k, v, v') -> [ txtf "%s %s->%s" k v v' ; H.br () ]) xs
|
2021-07-06 08:34:17 +00:00
|
|
|
|
2021-02-10 13:43:32 +00:00
|
|
|
let packages packages =
|
|
|
|
OpamPackage.Set.elements packages
|
|
|
|
|> List.concat_map (fun p -> [
|
2022-02-03 18:39:51 +00:00
|
|
|
txtf "%a" Opamdiff.pp_opampackage p;
|
|
|
|
H.br ();
|
|
|
|
])
|
2021-02-10 13:43:32 +00:00
|
|
|
|
|
|
|
let package_diffs diffs =
|
|
|
|
List.concat_map (fun pd -> [
|
2022-02-03 18:39:51 +00:00
|
|
|
txtf "%a" Opamdiff.pp_version_diff pd;
|
|
|
|
H.br ();
|
|
|
|
])
|
2021-02-10 13:43:32 +00:00
|
|
|
diffs
|
|
|
|
|
2021-07-06 08:34:17 +00:00
|
|
|
let opam_diffs diffs =
|
|
|
|
List.concat_map (fun pd ->
|
2022-02-03 18:39:51 +00:00
|
|
|
H.h4 [ txtf "%a" Opamdiff.pp_opam_diff pd ] ::
|
|
|
|
(match pd.Opamdiff.build with None -> [] | Some a ->
|
|
|
|
let l, r = Opamdiff.commands_to_strings a in
|
|
|
|
[
|
2022-02-03 19:15:14 +00:00
|
|
|
H.h5 [ H.txt "build instruction (without common prefix) \
|
|
|
|
modifications, old:" ] ;
|
2022-02-03 18:39:51 +00:00
|
|
|
H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) l) ;
|
|
|
|
H.h5 [ H.txt "new" ] ;
|
|
|
|
H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) r)
|
|
|
|
]) @
|
|
|
|
(match pd.Opamdiff.install with None -> [] | Some a ->
|
|
|
|
let l, r = Opamdiff.commands_to_strings a in
|
|
|
|
[
|
2022-02-03 19:15:14 +00:00
|
|
|
H.h5 [ H.txt "install instruction (without common prefix) \
|
|
|
|
modifications, old:" ] ;
|
2022-02-03 18:39:51 +00:00
|
|
|
H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) l) ;
|
|
|
|
H.h5 [ H.txt "new" ] ;
|
|
|
|
H.code (List.concat_map (fun s -> [ H.txt s ; H.br () ]) r)
|
|
|
|
]) @
|
|
|
|
(match pd.Opamdiff.url with None -> [] | Some a ->
|
|
|
|
let l, r = Opamdiff.opt_url_to_string a in
|
|
|
|
[
|
|
|
|
H.h5 [ H.txt "URL" ] ;
|
|
|
|
txtf "old: %s" l;
|
|
|
|
H.br ();
|
|
|
|
txtf "new: %s" r
|
|
|
|
]) @
|
|
|
|
[ H.br () ])
|
2021-07-06 08:34:17 +00:00
|
|
|
diffs
|
|
|
|
|
2022-02-03 12:27:22 +00:00
|
|
|
let compare_builds
|
2022-02-03 12:28:16 +00:00
|
|
|
~job_left
|
|
|
|
~job_right
|
|
|
|
~(build_left : Builder_db.Build.t)
|
|
|
|
~(build_right : Builder_db.Build.t)
|
2022-02-03 12:27:22 +00:00
|
|
|
~env_diff:(added_env, removed_env, changed_env)
|
|
|
|
~pkg_diff:(added_pkgs, removed_pkgs, changed_pkgs)
|
|
|
|
~opam_diff:(same, opam_diff, version_diff, left, right)
|
|
|
|
=
|
2021-11-12 11:11:08 +00:00
|
|
|
layout
|
|
|
|
~nav:(`Comparison ((job_left, build_left), (job_right, build_right)))
|
2021-11-12 13:01:20 +00:00
|
|
|
~title:(Fmt.str "Comparing builds %a and %a"
|
2022-02-03 13:00:24 +00:00
|
|
|
Uuidm.pp build_left.uuid Uuidm.pp build_right.uuid)
|
2021-07-06 08:34:17 +00:00
|
|
|
([
|
2022-02-03 11:54:02 +00:00
|
|
|
H.h1 [H.txt "Comparing builds"];
|
|
|
|
H.h2 [
|
|
|
|
H.txt "Builds ";
|
|
|
|
H.a ~a:H.[a_href
|
2022-02-03 13:00:24 +00:00
|
|
|
(Fmt.str "/job/%s/build/%a/"
|
|
|
|
job_left
|
|
|
|
Uuidm.pp build_left.uuid)]
|
2022-02-02 22:27:25 +00:00
|
|
|
[ txtf "%s@%a %a"
|
|
|
|
job_left
|
|
|
|
pp_ptime build_left.start
|
|
|
|
pp_platform (Some build_left.platform)];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.txt " and ";
|
|
|
|
H.a ~a:H.[a_href
|
2022-02-03 13:00:24 +00:00
|
|
|
(Fmt.str "/job/%s/build/%a/"
|
|
|
|
job_right
|
|
|
|
Uuidm.pp build_right.uuid)]
|
2022-02-02 22:27:25 +00:00
|
|
|
[ txtf "%s@%a %a"
|
|
|
|
job_right
|
|
|
|
pp_ptime build_right.start
|
|
|
|
pp_platform (Some build_right.platform)];
|
2021-02-10 13:43:32 +00:00
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.h3 [ H.a ~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
Fmt.kstr a_href "/compare/%a/%a/"
|
|
|
|
Uuidm.pp build_right.uuid
|
|
|
|
Uuidm.pp build_left.uuid ]
|
|
|
|
[H.txt "Compare in reverse direction"]] ;
|
2022-02-03 11:54:02 +00:00
|
|
|
H.ul [
|
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#opam-packages-removed"]
|
2022-02-02 22:27:25 +00:00
|
|
|
[txtf "%d opam packages removed"
|
2022-02-03 13:00:24 +00:00
|
|
|
(OpamPackage.Set.cardinal left)]
|
2021-02-10 13:43:32 +00:00
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#opam-packages-installed"]
|
2022-02-02 22:27:25 +00:00
|
|
|
[txtf "%d new opam packages installed"
|
2022-02-03 13:00:24 +00:00
|
|
|
(OpamPackage.Set.cardinal right)]
|
2021-02-10 13:43:32 +00:00
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#opam-packages-version-diff"]
|
2022-02-02 22:27:25 +00:00
|
|
|
[txtf "%d opam packages with version changes"
|
2022-02-03 13:00:24 +00:00
|
|
|
(List.length version_diff)]
|
2021-02-10 13:43:32 +00:00
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#opam-packages-opam-diff"]
|
2022-02-02 22:27:25 +00:00
|
|
|
[txtf "%d opam packages with changes in their opam file"
|
2022-02-03 13:00:24 +00:00
|
|
|
(List.length opam_diff)]
|
2021-02-12 11:18:41 +00:00
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#opam-packages-unchanged"]
|
2021-11-12 13:01:20 +00:00
|
|
|
[txtf "%d opam packages unchanged" (OpamPackage.Set.cardinal same)]
|
2021-02-10 13:43:32 +00:00
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#env-added"]
|
2021-07-06 08:34:17 +00:00
|
|
|
[ txtf "%d environment variables added" (List.length added_env)]
|
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#env-removed"]
|
2021-07-06 08:34:17 +00:00
|
|
|
[ txtf "%d environment variables removed" (List.length removed_env)]
|
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#env-changed"]
|
2021-07-06 08:34:17 +00:00
|
|
|
[ txtf "%d environment variables changed" (List.length changed_env)]
|
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#pkgs-added"]
|
2021-07-06 08:34:17 +00:00
|
|
|
[ txtf "%d system packages added" (List.length added_pkgs)]
|
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#pkgs-removed"]
|
2021-07-06 08:34:17 +00:00
|
|
|
[ txtf "%d system packages removed" (List.length removed_pkgs)]
|
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
|
|
|
H.a ~a:H.[a_href "#pkgs-changed"]
|
2021-07-06 08:34:17 +00:00
|
|
|
[ txtf "%d system packages changed" (List.length changed_pkgs)]
|
|
|
|
];
|
2021-02-10 13:43:32 +00:00
|
|
|
];
|
2022-02-03 11:54:02 +00:00
|
|
|
H.h3 ~a:H.[a_id "opam-packages-removed"]
|
|
|
|
[H.txt "Opam packages removed"];
|
|
|
|
H.code (packages left);
|
|
|
|
H.h3 ~a:H.[a_id "opam-packages-installed"]
|
|
|
|
[H.txt "New opam packages installed"];
|
|
|
|
H.code (packages right);
|
|
|
|
H.h3 ~a:H.[a_id "opam-packages-version-diff"]
|
|
|
|
[H.txt "Opam packages with version changes"];
|
|
|
|
H.code (package_diffs version_diff);
|
|
|
|
H.h3 ~a:H.[a_id "opam-packages-opam-diff"]
|
|
|
|
[H.txt "Opam packages with changes in their opam file"]] @
|
2022-02-03 13:00:24 +00:00
|
|
|
opam_diffs opam_diff @ [
|
|
|
|
H.h3 ~a:H.[a_id "opam-packages-unchanged"]
|
|
|
|
[H.txt "Unchanged opam packages"];
|
|
|
|
H.code (packages same);
|
|
|
|
H.h3 ~a:H.[a_id "env-added"] [H.txt "Environment variables added"];
|
|
|
|
H.code (key_values added_env);
|
|
|
|
H.h3 ~a:H.[a_id "env-removed"] [H.txt "Environment variables removed"];
|
|
|
|
H.code (key_values removed_env);
|
|
|
|
H.h3 ~a:H.[a_id "env-changed"] [H.txt "Environment variables changed"];
|
|
|
|
H.code (key_value_changes changed_env);
|
|
|
|
H.h3 ~a:H.[a_id "pkgs-added"] [H.txt "System packages added"];
|
|
|
|
H.code (key_values added_pkgs);
|
|
|
|
H.h3 ~a:H.[a_id "pkgs-removed"] [H.txt "System packages removed"];
|
|
|
|
H.code (key_values removed_pkgs);
|
|
|
|
H.h3 ~a:H.[a_id "pkgs-changed"] [H.txt "System packages changed"];
|
|
|
|
H.code (key_value_changes changed_pkgs);
|
|
|
|
])
|
2021-11-17 14:02:04 +00:00
|
|
|
|
2021-11-17 15:54:13 +00:00
|
|
|
let failed_builds ~start ~count builds =
|
2021-11-17 14:33:05 +00:00
|
|
|
let build (job_name, build) =
|
2022-02-03 11:54:02 +00:00
|
|
|
H.li [
|
2021-11-17 16:00:58 +00:00
|
|
|
check_icon build.Builder_db.Build.result;
|
|
|
|
txtf " %s %a " job_name pp_platform (Some build.platform);
|
2022-02-03 11:54:02 +00:00
|
|
|
H.a ~a:H.[Fmt.kstr a_href "/job/%s/build/%a/" job_name Uuidm.pp build.uuid]
|
2021-11-17 14:33:05 +00:00
|
|
|
[txtf "%a" pp_ptime build.start];
|
|
|
|
txtf " %a" Builder.pp_execution_result build.result;
|
|
|
|
]
|
2021-11-17 14:02:04 +00:00
|
|
|
in
|
|
|
|
layout ~title:"Failed builds"
|
2022-02-02 22:27:25 +00:00
|
|
|
([
|
2022-02-03 11:54:02 +00:00
|
|
|
H.h1 [H.txt "Failed builds"];
|
|
|
|
H.ul (List.map build builds);
|
|
|
|
H.p [ txtf "View the next %d failed builds " count;
|
2022-02-03 13:00:24 +00:00
|
|
|
H.a ~a:H.[
|
2022-02-03 18:39:51 +00:00
|
|
|
Fmt.kstr a_href "/failed-builds/?count=%d&start=%d"
|
|
|
|
count (start + count) ]
|
2022-02-03 13:00:24 +00:00
|
|
|
[ H.txt "here"];
|
|
|
|
H.txt ".";
|
|
|
|
]
|
2021-11-17 15:54:13 +00:00
|
|
|
])
|
2022-02-01 11:43:07 +00:00
|
|
|
|