diff --git a/bot-components/GitHub_GraphQL.ml b/bot-components/GitHub_GraphQL.ml index 959311ed..3c7165d6 100644 --- a/bot-components/GitHub_GraphQL.ml +++ b/bot-components/GitHub_GraphQL.ml @@ -3,8 +3,8 @@ (* Queries *) module PullRequest_Milestone_and_Cards = - [%graphql - {| +[%graphql +{| fragment Column on ProjectColumn { id databaseId @@ -34,8 +34,8 @@ module PullRequest_Milestone_and_Cards = |}] module PullRequest_ID = - [%graphql - {| +[%graphql +{| query prID($owner: String!, $repo: String!, $number: Int!) { repository(owner: $owner,name: $repo) { pullRequest(number: $number) { @@ -46,8 +46,8 @@ module PullRequest_ID = |}] module PullRequest_ID_and_Milestone = - [%graphql - {| +[%graphql +{| query prInfo($owner: String!, $repo: String!, $number: Int!) { repository(owner: $owner,name: $repo) { pullRequest(number: $number) { @@ -63,8 +63,8 @@ module PullRequest_ID_and_Milestone = |}] module TeamMembership = - [%graphql - {| +[%graphql +{| query teamMember($org: String!, $team: String!, $user: String!) { organization(login:$org) { team(slug:$team) { @@ -85,8 +85,8 @@ module ParseAsString = struct end module PullRequest_Refs = - [%graphql - {| +[%graphql +{| query prRefs($owner: String!, $repo: String!, $number: Int!) { repository(owner: $owner, name:$repo) { pullRequest(number: $number) { @@ -115,8 +115,8 @@ module PullRequest_Refs = |}] module Issue_Milestone = - [%graphql - {| +[%graphql +{| fragment Milestone on Milestone { id } @@ -151,8 +151,8 @@ module Issue_Milestone = |}] module PullRequestReviewsInfo = - [%graphql - {| +[%graphql +{| fragment Reviews on PullRequestReviewConnection { nodes { author { login } @@ -189,8 +189,8 @@ module PullRequestReviewsInfo = |}] module DefaultBranch = - [%graphql - {| +[%graphql +{| query defaultBranch($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { defaultBranchRef { @@ -201,8 +201,8 @@ module DefaultBranch = |}] module FileContent = - [%graphql - {| +[%graphql +{| query fileContent($owner: String!, $repo: String!, $file: String!) { repository(owner: $owner, name: $repo) { file:object(expression: $file) { @@ -215,8 +215,8 @@ module FileContent = |}] module RepoId = - [%graphql - {| +[%graphql +{| query repoId($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { id @@ -225,8 +225,8 @@ module RepoId = |}] module GetCheckRuns = - [%graphql - {| +[%graphql +{| query getCheckRuns($appId: Int!, $owner: String!, $repo: String!, $commit: String!, $context: String!) { repository(owner:$owner, name:$repo) { obj: object(expression: $commit) { @@ -252,8 +252,8 @@ module GetCheckRuns = |}] module GetLabel = - [%graphql - {| +[%graphql +{| query getLabels($owner: String!, $repo: String!, $label: String!) { repository(owner:$owner, name:$repo) { label(name: $label) { @@ -264,8 +264,8 @@ module GetLabel = |}] module GetOpenPullRequestWithLabel = - [%graphql - {| +[%graphql +{| query getOpenPullRequestWithLabel($owner: String!, $repo:String!, $label:String!, $cursor: String, $len: Int!) { repository(name: $repo,owner:$owner) { @@ -285,8 +285,8 @@ query getOpenPullRequestWithLabel($owner: String!, $repo:String!, $label:String! |}] module GetPullRequestLabelTimeline = - [%graphql - {| +[%graphql +{| fragment Label on Label { name } @@ -317,8 +317,8 @@ query getPullRequestLabelTimeline($owner: String!, $repo:String!, $prNumber: Int |}] module GetPullRequestLabels = - [%graphql - {| +[%graphql +{| query getPullRequestLabels($owner: String!, $repo:String!, $prNumber: Int!, $cursor: String, $len: Int!) { repository(name: $repo,owner:$owner) { @@ -339,8 +339,8 @@ query getPullRequestLabels($owner: String!, $repo:String!, $prNumber: Int!, $cur |}] module GetBaseAndHeadChecks = - [%graphql - {| +[%graphql +{| fragment CheckRuns on CheckRunConnection { nodes { name @@ -386,8 +386,8 @@ query getChecks($appId: Int!, $owner: String!, $repo:String!, $prNumber: Int!, $ |}] module GetPipelineSummary = - [%graphql - {| +[%graphql +{| query getChecks($appId: Int!, $owner: String!, $repo:String!, $head: String!) { repository(name: $repo,owner:$owner) { getPipelineSummaryCommit: object(expression: $head) { @@ -410,8 +410,8 @@ query getChecks($appId: Int!, $owner: String!, $repo:String!, $head: String!) { (* Mutations *) module MoveCardToColumn = - [%graphql - {| +[%graphql +{| mutation moveCard($card_id:ID!,$column_id:ID!) { moveProjectCard(input:{cardId:$card_id,columnId:$column_id}) { clientMutationId @@ -420,8 +420,8 @@ module MoveCardToColumn = |}] module PostComment = - [%graphql - {| +[%graphql +{| mutation addComment($id:ID!,$message:String!) { payload: addComment(input:{subjectId:$id,body:$message}) { commentEdge { @@ -434,8 +434,8 @@ module PostComment = |}] module UpdateMilestone = - [%graphql - {| +[%graphql +{| mutation updateMilestone($issue: ID!, $milestone: ID!) { updateIssue(input: {id: $issue, milestoneId: $milestone}) { clientMutationId @@ -444,8 +444,8 @@ module UpdateMilestone = |}] module MergePullRequest = - [%graphql - {| +[%graphql +{| mutation mergePullRequest($pr_id: ID!, $commit_headline: String, $commit_body: String, $merge_method: PullRequestMergeMethod) { mergePullRequest( @@ -462,8 +462,8 @@ module MergePullRequest = |}] module ClosePullRequest = - [%graphql - {| +[%graphql +{| mutation closePullRequest($pr_id: ID!) { closePullRequest( input: {pullRequestId: $pr_id}) { @@ -475,8 +475,8 @@ module ClosePullRequest = |}] module LabelIssue = - [%graphql - {| +[%graphql +{| mutation labelIssue($issue_id: ID!, $label_ids: [ID!]!) { addLabelsToLabelable( input: {labelableId: $issue_id, labelIds:$label_ids}) { @@ -486,8 +486,8 @@ module LabelIssue = |}] module UnlabelIssue = - [%graphql - {| +[%graphql +{| mutation unlabelIssue($issue_id: ID!, $label_ids: [ID!]!) { removeLabelsFromLabelable( input: {labelableId: $issue_id, labelIds:$label_ids}) { @@ -497,8 +497,8 @@ module UnlabelIssue = |}] module NewCheckRun = - [%graphql - {| +[%graphql +{| mutation newCheckRun($name: String!, $repoId: ID!, $headSha: String!, $status: RequestableCheckStatusState!, $title: String!, $text: String, $summary: String!, $url: String!, $conclusion: CheckConclusionState, $externalId: String) { @@ -525,8 +525,8 @@ module NewCheckRun = |}] module UpdateCheckRun = - [%graphql - {| +[%graphql +{| mutation updateCheckRun($checkRunId: ID!, $repoId: ID! $conclusion: CheckConclusionState!, $title: String!, $text: String, $url: String, $summary: String!) { diff --git a/bot-components/GitHub_queries.ml b/bot-components/GitHub_queries.ml index 7e897591..c8addfa8 100644 --- a/bot-components/GitHub_queries.ml +++ b/bot-components/GitHub_queries.ml @@ -116,28 +116,28 @@ let get_backported_pr_info ~bot_info number base_ref = >|= function | Ok (cards, milestone) -> (let open Option in - milestone - >>= fun milestone -> - milestone.description - >>= extract_backport_info ~bot_info - >>= (fun full_backport_info -> - full_backport_info.backport_info - |> List.find ~f:(fun {backport_to} -> - String.equal ("refs/heads/" ^ backport_to) base_ref ) ) - >>= fun {request_inclusion_column; backported_column} -> - List.find_map cards ~f:(fun card -> - if - card.column - >>= (fun column -> column.databaseId) - |> Option.equal Int.equal (Some request_inclusion_column) - then - List.find_map card.columns ~f:(fun column -> - if - Option.equal Int.equal (Some backported_column) - column.databaseId - then Some {card_id= card.id; column_id= column.id} - else None ) - else None ) ) + milestone + >>= fun milestone -> + milestone.description + >>= extract_backport_info ~bot_info + >>= (fun full_backport_info -> + full_backport_info.backport_info + |> List.find ~f:(fun {backport_to} -> + String.equal ("refs/heads/" ^ backport_to) base_ref ) ) + >>= fun {request_inclusion_column; backported_column} -> + List.find_map cards ~f:(fun card -> + if + card.column + >>= (fun column -> column.databaseId) + |> Option.equal Int.equal (Some request_inclusion_column) + then + List.find_map card.columns ~f:(fun column -> + if + Option.equal Int.equal (Some backported_column) + column.databaseId + then Some {card_id= card.id; column_id= column.id} + else None ) + else None ) ) |> fun res -> Ok res | Error err -> Error (f "Error in backported_pr_info: %s." err) diff --git a/bot-components/GitLab_GraphQL.ml b/bot-components/GitLab_GraphQL.ml index 06d30f5f..ab2910ca 100644 --- a/bot-components/GitLab_GraphQL.ml +++ b/bot-components/GitLab_GraphQL.ml @@ -1,6 +1,6 @@ module GetRetriedJobs = - [%graphql - {| +[%graphql +{| query getRetriedJobs($fullPath: ID!, $jobId: JobID!) { project(fullPath: $fullPath) { job(id: $jobId) { diff --git a/src/actions.ml b/src/actions.ml index 9f752733..1ccb038b 100644 --- a/src/actions.ml +++ b/src/actions.ml @@ -540,19 +540,19 @@ let job_failure ~bot_info job_info ~pr_num (gh_owner, gh_repo) project_id failure_reason >>= fun () -> ( if String.equal failure_reason "runner_system_failure" then - Lwt.return (Retry "Runner failure reported by GitLab CI") - else - Lwt_io.printlf - "Failure reason reported by GitLab CI: %s.\nRetrieving the trace..." - failure_reason - >>= fun () -> - GitLab_queries.get_build_trace ~bot_info ~gitlab_domain ~project_id - ~build_id - >>= function - | Ok trace -> - trace_action ~repo_full_name:gitlab_repo_full_name trace - | Error err -> - Lwt.return (Ignore (f "Error while retrieving the trace: %s." err)) ) + Lwt.return (Retry "Runner failure reported by GitLab CI") + else + Lwt_io.printlf + "Failure reason reported by GitLab CI: %s.\nRetrieving the trace..." + failure_reason + >>= fun () -> + GitLab_queries.get_build_trace ~bot_info ~gitlab_domain ~project_id + ~build_id + >>= function + | Ok trace -> + trace_action ~repo_full_name:gitlab_repo_full_name trace + | Error err -> + Lwt.return (Ignore (f "Error while retrieving the trace: %s." err)) ) >>= function | Warn trace -> Lwt_io.printf "Actual failure.\n" @@ -1189,13 +1189,13 @@ let accumulate_extra_minimizer_arguments options = let extra_args = getopts ~opt:"extra-arg" options in let inline_stdlib = getopt ~opt:"inline-stdlib" options in ( if String.equal inline_stdlib "yes" then Lwt.return ["--inline-coqlib"] - else - ( if not (String.equal inline_stdlib "") then - Lwt_io.printlf - "Ignoring invalid option to inline-stdlib '%s' not equal to 'yes'" - inline_stdlib - else Lwt.return_unit ) - >>= fun () -> Lwt.return_nil ) + else + ( if not (String.equal inline_stdlib "") then + Lwt_io.printlf + "Ignoring invalid option to inline-stdlib '%s' not equal to 'yes'" + inline_stdlib + else Lwt.return_unit ) + >>= fun () -> Lwt.return_nil ) >>= fun inline_stdlib_args -> inline_stdlib_args @ extra_args |> Lwt.return let minimize_failed_tests ~bot_info ~owner ~repo ~pr_number @@ -1452,7 +1452,7 @@ let minimize_failed_tests ~bot_info ~owner ~repo ~pr_number "I am now %s minimization at commit %s on %s. I'll come back \ to you with the results once it's done.%s" ( if Option.is_none bug_file_contents then "running" - else "resuming" ) + else "resuming" ) head (jobs_minimized |> String.concat ~sep:", ") note_some_head_unfinished_msg ) @@ -1560,7 +1560,7 @@ let minimize_failed_tests ~bot_info ~owner ~repo ~pr_number I'll come back to you with the results once it's done.%s\n\n\ %s" ( if Option.is_none bug_file_contents then "running" - else "resuming" ) + else "resuming" ) head (pluralize "target" successful_requests) (successful_requests |> String.concat ~sep:", ") @@ -2074,24 +2074,23 @@ let rec merge_pull_request_action ~bot_info ?(t = 1.) comment_info = let reasons_for_not_merging = List.filter_opt [ ( if String.equal comment_info.author pr.user then - Some "You are the author." - else if - List.exists - ~f:(String.equal comment_info.author) - comment_info.issue.assignees - then None - else Some "You are not among the assignees." ) + Some "You are the author." + else if + List.exists + ~f:(String.equal comment_info.author) + comment_info.issue.assignees + then None + else Some "You are not among the assignees." ) ; comment_info.issue.labels |> List.find ~f:(fun label -> string_match ~regexp:"needs:.*" label) |> Option.map ~f:(fun l -> f "There is still a `%s` label." l) ; ( if - comment_info.issue.labels - |> List.exists ~f:(fun label -> - string_match ~regexp:"kind:.*" label ) - then None - else Some "There is no `kind:` label." ) + comment_info.issue.labels + |> List.exists ~f:(fun label -> string_match ~regexp:"kind:.*" label) + then None + else Some "There is no `kind:` label." ) ; ( if comment_info.issue.milestoned then None - else Some "No milestone has been set." ) ] + else Some "No milestone has been set." ) ] in ( match reasons_for_not_merging with | _ :: _ -> @@ -2175,9 +2174,9 @@ let rec merge_pull_request_action ~bot_info ?(t = 1.) comment_info = comment_info.issue.title ) ~commit_body: ( List.fold_left reviews_info.approved_reviews ~init:"" - ~f:(fun s r -> s ^ f "Reviewed-by: %s\n" r ) + ~f:(fun s r -> s ^ f "Reviewed-by: %s\n" r) ^ List.fold_left reviews_info.comment_reviews ~init:"" - ~f:(fun s r -> s ^ f "Ack-by: %s\n" r ) + ~f:(fun s r -> s ^ f "Ack-by: %s\n" r) ^ f "Co-authored-by: %s <%s@users.noreply.github.com>\n" comment_info.author comment_info.author ) ~merge_method:MERGE () @@ -2278,17 +2277,17 @@ let remove_labels_if_present ~bot_info (issue : issue_info) labels = let mirror_action ~bot_info ?(force = true) ~gitlab_domain ~owner ~repo ~base_ref ~head_sha () = (let open Lwt_result.Infix in - let local_ref = base_ref ^ "-" ^ head_sha in - let gh_ref = - {repo_url= f "https://github.com/%s/%s" owner repo; name= base_ref} - in - (* TODO: generalize to use repository mappings, with enhanced security *) - gitlab_repo ~bot_info ~gitlab_domain ~gitlab_full_name:(owner ^ "/" ^ repo) - |> Lwt.return - >>= fun gl_repo -> - let gl_ref = {repo_url= gl_repo; name= base_ref} in - git_fetch gh_ref local_ref |> execute_cmd - >>= fun () -> git_push ~force ~remote_ref:gl_ref ~local_ref () |> execute_cmd + let local_ref = base_ref ^ "-" ^ head_sha in + let gh_ref = + {repo_url= f "https://github.com/%s/%s" owner repo; name= base_ref} + in + (* TODO: generalize to use repository mappings, with enhanced security *) + gitlab_repo ~bot_info ~gitlab_domain ~gitlab_full_name:(owner ^ "/" ^ repo) + |> Lwt.return + >>= fun gl_repo -> + let gl_ref = {repo_url= gl_repo; name= base_ref} in + git_fetch gh_ref local_ref |> execute_cmd + >>= fun () -> git_push ~force ~remote_ref:gl_ref ~local_ref () |> execute_cmd ) >>= function | Ok () -> @@ -2479,30 +2478,30 @@ let run_ci_action ~bot_info ~comment_info ?full_ci ~gitlab_mapping let team = "contributors" in (fun () -> (let open Lwt_result.Infix in - GitHub_queries.get_team_membership ~bot_info ~org:"coq" ~team - ~user:comment_info.author - >>= (fun is_member -> - if is_member then - let open Lwt.Syntax in - let* () = Lwt_io.printl "Authorized user: pushing to GitLab." in - match comment_info.pull_request with - | Some pr_info -> - update_pr ~skip_author_check:true pr_info ~bot_info - ~gitlab_mapping ~github_mapping - | None -> - let {owner; repo; number} = comment_info.issue.issue in - GitHub_queries.get_pull_request_refs ~bot_info ~owner ~repo - ~number - >>= fun pr_info -> - update_pr ?full_ci ~skip_author_check:true - {pr_info with issue= comment_info.issue} - ~bot_info ~gitlab_mapping ~github_mapping - else - (* We inform the author of the request that they are not authorized. *) - inform_user_not_in_contributors ~bot_info comment_info - |> Lwt_result.ok ) - |> Fn.flip Lwt_result.bind_lwt_error (fun err -> - Lwt_io.printf "Error: %s\n" err ) ) + GitHub_queries.get_team_membership ~bot_info ~org:"coq" ~team + ~user:comment_info.author + >>= (fun is_member -> + if is_member then + let open Lwt.Syntax in + let* () = Lwt_io.printl "Authorized user: pushing to GitLab." in + match comment_info.pull_request with + | Some pr_info -> + update_pr ~skip_author_check:true pr_info ~bot_info + ~gitlab_mapping ~github_mapping + | None -> + let {owner; repo; number} = comment_info.issue.issue in + GitHub_queries.get_pull_request_refs ~bot_info ~owner ~repo + ~number + >>= fun pr_info -> + update_pr ?full_ci ~skip_author_check:true + {pr_info with issue= comment_info.issue} + ~bot_info ~gitlab_mapping ~github_mapping + else + (* We inform the author of the request that they are not authorized. *) + inform_user_not_in_contributors ~bot_info comment_info + |> Lwt_result.ok ) + |> Fn.flip Lwt_result.bind_lwt_error (fun err -> + Lwt_io.printf "Error: %s\n" err ) ) >>= fun _ -> Lwt.return_unit ) |> Lwt.async ; Server.respond_string ~status:`OK @@ -2637,8 +2636,8 @@ let coq_push_action ~bot_info ~base_ref ~commits_msg = | Ok (Some (_, pr_id, {backport_info})) -> backport_info |> Lwt_list.iter_p - (fun - {backport_to; request_inclusion_column; backported_column} -> + (fun {backport_to; request_inclusion_column; backported_column} + -> if "refs/heads/" ^ backport_to |> String.equal base_ref then Lwt_io.printf "PR was merged into the backportig branch directly.\n" @@ -2821,15 +2820,15 @@ let run_bench ~bot_info ?key_value_pairs comment_info = (Str.quote "[bench](https://gitlab.inria.fr/coq/coq/-/jobs/") in ( if Helpers.string_match ~regexp summary then - Str.matched_group 1 summary - else raise @@ Stdlib.Failure "Could not find GitLab bench job ID" ) + Str.matched_group 1 summary + else raise @@ Stdlib.Failure "Could not find GitLab bench job ID" ) |> Stdlib.int_of_string in let project_id = let regexp = {|.*GitLab Project ID: \([0-9]*\)|} in ( if Helpers.string_match ~regexp summary then - Str.matched_group 1 summary - else raise @@ Stdlib.Failure "Could not find GitLab Project ID" ) + Str.matched_group 1 summary + else raise @@ Stdlib.Failure "Could not find GitLab Project ID" ) |> Int.of_string in Lwt.return_ok (build_id, project_id)