Add SHA256 & SHA512 digests of build artifacts

This commit is contained in:
Reynir Björnsson 2020-12-14 08:18:13 +01:00
parent bac7f8019d
commit 5f8325b60b
4 changed files with 54 additions and 10 deletions

View file

@ -50,14 +50,14 @@ let routes (t : Model.t) =
let+ job_run = let+ job_run =
Lwt_result.lift (safe_seg job) >>= fun job -> Lwt_result.lift (safe_seg job) >>= fun job ->
Lwt_result.lift (safe_seg run) >>= fun run -> Lwt_result.lift (safe_seg run) >>= fun run ->
Model.read_full t job run in Model.read_full_with_digests t job run in
match job_run with match job_run with
| Error (`Msg e) -> | Error (`Msg e) ->
Log.warn (fun m -> m "Error getting job run: %s" e); Log.warn (fun m -> m "Error getting job run: %s" e);
Response.of_plain_text ~status:`Internal_server_error Response.of_plain_text ~status:`Internal_server_error
"Error getting job run" "Error getting job run"
| Ok job_run -> | Ok (job_run, digests) ->
Views.job_run job_run |> Response.of_html Views.job_run job_run digests |> Response.of_html
in in
[ [

View file

@ -24,12 +24,18 @@ type job_run_info = {
data : (Fpath.t * string) list data : (Fpath.t * string) list
} }
type t = { type digest = {
dir : Fpath.t; sha256 : string;
mutable cache : job_run_meta RunMap.t sha512 : string;
} }
let init dir = { dir; cache = RunMap.empty; } type t = {
dir : Fpath.t;
mutable meta_cache : job_run_meta RunMap.t;
mutable digest_cache : (Fpath.t * digest) list RunMap.t
}
let init dir = { dir; meta_cache = RunMap.empty; digest_cache = RunMap.empty; }
type job = { type job = {
path : Fpath.t; path : Fpath.t;
@ -46,17 +52,34 @@ let read_full t path run =
Builder.Asn.exec_of_cs (Cstruct.of_string s) Builder.Asn.exec_of_cs (Cstruct.of_string s)
>>| fun (job_info, uuid, out, start, finish, result, data) -> >>| fun (job_info, uuid, out, start, finish, result, data) ->
let meta = { job_info; uuid; start; finish; result } in let meta = { job_info; uuid; start; finish; result } in
t.cache <- RunMap.add (path, run) meta t.cache; t.meta_cache <- RunMap.add (path, run) meta t.meta_cache;
{ meta; out; data } { meta; out; data }
let digest (path, data) =
let module H = Mirage_crypto.Hash in
let data = Cstruct.of_string data in
(path, {
sha256 = H.SHA256.digest data |> Cstruct.to_string;
sha512 = H.SHA512.digest data |> Cstruct.to_string;
})
let read_full_with_digests t path run =
read_full t path run >|= fun ({ data; _ } as full) ->
match RunMap.find_opt (path, run) t.digest_cache with
| Some digests -> full, digests
| None ->
let digests = List.map digest data in
t.digest_cache <- RunMap.add (path, run) digests t.digest_cache;
full, digests
let read_full_meta t path run = let read_full_meta t path run =
match RunMap.find_opt (path, run) t.cache with match RunMap.find_opt (path, run) t.meta_cache with
| Some meta -> | Some meta ->
Lwt_result.lift (Bos.OS.File.exists Fpath.(t.dir // path // run / "full")) >>= fun exists -> Lwt_result.lift (Bos.OS.File.exists Fpath.(t.dir // path // run / "full")) >>= fun exists ->
if exists if exists
then Lwt_result.return meta then Lwt_result.return meta
else else
(t.cache <- RunMap.remove (path, run) t.cache; (t.meta_cache <- RunMap.remove (path, run) t.meta_cache;
Lwt_result.fail (`Msg "no such file")) Lwt_result.fail (`Msg "no such file"))
| None -> | None ->
read_full t path run >|= fun { meta; out = _; data = _ } -> read_full t path run >|= fun { meta; out = _; data = _ } ->

View file

@ -8,6 +8,11 @@ type job_run_meta = {
result : Builder.execution_result; result : Builder.execution_result;
} }
type digest = {
sha256 : string;
sha512 : string;
}
type job_run_info = { type job_run_info = {
meta : job_run_meta; meta : job_run_meta;
out : (int * string) list; out : (int * string) list;
@ -25,5 +30,8 @@ val job_name : job -> string
val read_full : t -> Fpath.t -> Fpath.t -> (job_run_info, [> `Msg of string ]) result Lwt.t val read_full : t -> Fpath.t -> Fpath.t -> (job_run_info, [> `Msg of string ]) result Lwt.t
val read_full_with_digests : t -> Fpath.t -> Fpath.t ->
(job_run_info * (Fpath.t * digest) list, [> `Msg of string ]) result Lwt.t
val job : t -> Fpath.t -> (job, [> `Msg of string]) result Lwt.t val job : t -> Fpath.t -> (job, [> `Msg of string]) result Lwt.t
val jobs : t -> (Fpath.t list, [> `Msg of string ]) result Lwt.t val jobs : t -> (Fpath.t list, [> `Msg of string ]) result Lwt.t

View file

@ -84,6 +84,7 @@ let job_run
Model.job_info = { Builder.name; _ }; Model.job_info = { Builder.name; _ };
start; finish; uuid = _; result }; start; finish; uuid = _; result };
out; data = _ } out; data = _ }
digests
= =
let ptime_pp = Ptime.pp_human () in let ptime_pp = Ptime.pp_human () in
let delta = Ptime.diff finish start in let delta = Ptime.diff finish start in
@ -91,6 +92,18 @@ let job_run
[ h1 [txtf "Job build %s %a" name ptime_pp start]; [ h1 [txtf "Job build %s %a" name ptime_pp start];
p [txtf "Build took %a." Ptime.Span.pp delta ]; p [txtf "Build took %a." Ptime.Span.pp delta ];
p [txtf "Execution result: %a." Builder.pp_execution_result result]; p [txtf "Execution result: %a." Builder.pp_execution_result result];
h3 [txt "Digests of build artifacts"];
dl (List.concat_map
(fun (path, { Model.sha256; sha512 }) -> [
dt [code [txtf "%a" Fpath.pp path];
txt "(SHA256)"];
dd [code [txtf "%s" (Base64.encode_string sha256)]];
dt [code [txtf "%a" Fpath.pp path];
txt "(SHA512)"];
dd [code [txtf "%s" (Base64.encode_string sha512)]];
])
digests);
h3 [txt "Build log"];
table table
(List.mapi (fun idx (ts, line) -> (List.mapi (fun idx (ts, line) ->
let ts_id = "L" ^ string_of_int idx in let ts_id = "L" ^ string_of_int idx in