@@ -67,26 +67,6 @@ module Build = struct
6767 (* Gets the pipeline name from the buildkite context *)
6868 Re2. create_exn {| buildkite/ ([\w_- ]+ )| }
6969
70- let git_ssh_re =
71- (* matches git ssh clone links *)
72- Re2. create_exn {|^ git@ ([A - Za - z0-9. - ]+ ):([A - Za - z0-9. _- ]+ )\/ ([A - Za - z0-9. _- ]+ )\.git$| }
73-
74- let git_ssh_to_https url =
75- match Re2. find_submatches_exn git_ssh_re url with
76- | exception exn -> util_error ~exn " failed to parse git ssh link %s" url
77- | [| Some _; Some url; Some user; Some repo |] -> sprintf " https://%s/%s/%s" url user repo
78- | _ -> util_error " failed to get repo details from the ssh link."
79-
80- let git_ssh_to_contents_url url =
81- match Re2. find_submatches_exn git_ssh_re url with
82- | exception exn -> util_error ~exn " failed to parse git ssh link %s" url
83- | [| Some _; Some " github.com" ; Some user; Some repo |] ->
84- sprintf " https://api.github.com/repos/%s/%s/contents/{+path}" user repo
85- | [| Some _; Some url; Some user; Some repo |] ->
86- (* GHE links *)
87- sprintf " https://%s/api/v3/repos/%s/%s/contents/{+path}" url user repo
88- | _ -> util_error " failed to get repo details from the ssh link."
89-
9070 let is_pipeline_step context = Re2. matches buildkite_is_step_re context
9171
9272 (* * For now we only care about buildkite pipelines and steps. Other CI systems are not supported yet. *)
258238module Webhook = struct
259239 type n = Buildkite_t .webhook_build_payload
260240
241+ type repo_details = {
242+ url : string ;
243+ user : string ;
244+ repo : string ;
245+ }
246+
247+ type repo =
248+ | Github of repo_details
249+ | GHE of repo_details
250+
251+ type failed_passed_steps = {
252+ failed_steps : FailedStepSet .t ;
253+ passed_steps : FailedStepSet .t ;
254+ }
255+
256+ let git_ssh_re =
257+ (* matches git ssh clone links *)
258+ Re2. create_exn {|^ git@ ([A - Za - z0-9. - ]+ ):([A - Za - z0-9. _- ]+ )\/ ([A - Za - z0-9. _- ]+ )\.git$| }
259+
260+ let git_ssh_to_repo url =
261+ match Re2. find_submatches_exn git_ssh_re url with
262+ | exception exn -> util_error ~exn " failed to parse git ssh link %s" url
263+ | [| Some _; Some " github.com" ; Some user; Some repo |] -> Github { url = " github.com" ; user; repo }
264+ | [| Some _; Some url; Some user; Some repo |] ->
265+ (* GHE links *)
266+ GHE { url; user; repo }
267+ | _ -> util_error " failed to get repo details from the ssh link."
268+
269+ let git_ssh_to_api_url ?(resource = " " ) url =
270+ match git_ssh_to_repo url with
271+ | Github { user; repo; _ } -> sprintf " https://api.github.com/repos/%s/%s%s" user repo resource
272+ | GHE { url; user; repo } -> sprintf " https://%s/api/v3/repos/%s/%s%s" url user repo resource
273+
274+ let git_ssh_to_https url =
275+ match git_ssh_to_repo url with
276+ | Github { url; user; repo } | GHE { url; user; repo } -> sprintf " https://%s/%s/%s" url user repo
277+
278+ let git_ssh_to_contents_url ssh_url = git_ssh_to_api_url ~resource: " /contents/{+path}" ssh_url
279+
280+ let git_ssh_to_commits_url ssh_url = git_ssh_to_api_url ~resource: " /commits{/sha}" ssh_url
281+
261282 let parse_signature_header header =
262283 let timestamp, signature =
263284 String. split_on_char ',' header
@@ -292,7 +313,7 @@ module Webhook = struct
292313 | Ok (timestamp , signature ) -> is_valid_signature ~secret ~timestamp ~signature body
293314
294315 let validate_repo_url (secrets : Config_t.secrets ) (n : Buildkite_t.webhook_build_payload ) =
295- let repo_url = Build. git_ssh_to_https n.pipeline.repository in
316+ let repo_url = git_ssh_to_https n.pipeline.repository in
296317 match List. exists (fun (r : Config_t.repo_config ) -> String. equal r.url repo_url) secrets.repos with
297318 | true -> repo_url
298319 | false -> util_error " unsupported repository %s" repo_url
@@ -382,33 +403,36 @@ module Webhook = struct
382403 let time_since t = Ptime. (Span. abs (diff (Ptime_clock. now () ) t))
383404 let is_past_span time span = Ptime.Span. compare (time_since time) span > 0
384405
385- type failed_passed_steps = {
386- failed_steps : FailedStepSet .t ;
387- passed_steps : FailedStepSet .t ;
388- }
406+ let get_commit_author ~get_commit (n : n ) sha =
407+ let repo_url = git_ssh_to_https n.pipeline.repository in
408+ let commits_url = git_ssh_to_commits_url n.pipeline.repository in
409+ let * (gh_commit : Github_t.api_commit ) = get_commit ~commits_url ~repo_url ~sha in
410+ Lwt. return_ok gh_commit.commit.author.email
389411
390- let to_failed_step ~(n : n ) (job : Buildkite_t.job ) =
412+ let to_failed_step ~(n : n ) ~ author (job : Buildkite_t.job ) =
391413 {
392414 Buildkite_t. id = Option. default job.name job.step_key;
393415 name = job.name;
394416 build_url = job.web_url;
395417 created_at = Timestamp. wrap_with_fallback n.build.created_at;
396- author = extract_metadata_email n.build.meta_data |> Option. default " " ;
418+ author;
397419 escalated_at = None ;
398420 }
399421
400- let to_failed_step_set jobs n = List. map (to_failed_step ~n ) jobs |> FailedStepSet. of_list
422+ let to_failed_step_set author jobs n = List. map (to_failed_step ~n ~author ) jobs |> FailedStepSet. of_list
401423
402- let new_failed_steps ~(cfg : Config_t.config ) ~(repo_state : State_t.repo_state ) ~get_build ~db_update (n : n ) =
424+ let new_failed_steps ~(cfg : Config_t.config ) ~(repo_state : State_t.repo_state ) ~get_build ~get_commit ~db_update
425+ (n : n ) =
403426 let org, pipeline, build_nr = Build. get_org_pipeline_build' n.build.web_url in
404427 let repo_key = repo_key org pipeline in
405428 let partition_build_steps () =
406429 log#info " Fetching failed steps for build %s/%s/%s" org pipeline build_nr;
407430 let * (build : Buildkite_t.get_build_res ) = get_build n.build.web_url in
431+ let * author = get_commit_author ~get_commit n build.sha in
408432 Lwt. return_ok
409433 {
410- failed_steps = to_failed_step_set (Build. filter_failed_jobs build.jobs) n;
411- passed_steps = to_failed_step_set (Build. filter_passed_jobs build.jobs) n;
434+ failed_steps = to_failed_step_set author (Build. filter_failed_jobs build.jobs) n;
435+ passed_steps = to_failed_step_set author (Build. filter_passed_jobs build.jobs) n;
412436 }
413437 in
414438 match Stringtbl. find_opt repo_state.failed_steps repo_key with
0 commit comments