diff --git a/bot-components/GitHub_GraphQL.ml b/bot-components/GitHub_GraphQL.ml index 3c7165d6..67ce98f9 100644 --- a/bot-components/GitHub_GraphQL.ml +++ b/bot-components/GitHub_GraphQL.ml @@ -2,29 +2,17 @@ (* Queries *) -module PullRequest_Milestone_and_Cards = +module PullRequest_Cards = [%graphql {| - fragment Column on ProjectColumn { - id - databaseId - } - - query backportInfo($owner: String!, $repo: String!, $number: Int!) { + query prCards($owner: String!, $repo: String!, $number: Int!) { repository(owner: $owner,name: $repo) { pullRequest(number: $number) { - milestone { - title - description - } - projectCards(first:100) { - nodes { - id - column { ... Column } - project { - columns(first:100) { - nodes { ... Column } - } + projectItems(first: 100) { + items: nodes { + item_id: id + projectV2: project { + number } } } @@ -45,6 +33,21 @@ module PullRequest_ID = } |}] +module PullRequest_Milestone = +[%graphql +{| + query prInfo($pr_id: ID!) { + node(id: $pr_id) { + ... on PullRequest { + milestone { + title + description + } + } + } + } +|}] + module PullRequest_ID_and_Milestone = [%graphql {| @@ -52,7 +55,6 @@ module PullRequest_ID_and_Milestone = repository(owner: $owner,name: $repo) { pullRequest(number: $number) { id - databaseId milestone { title description @@ -62,6 +64,18 @@ module PullRequest_ID_and_Milestone = } |}] +module Milestone_ID = +[%graphql +{| + query milestoneID($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner,name: $repo) { + milestone(number: $number) { + id + } + } + } +|}] + module TeamMembership = [%graphql {| @@ -407,18 +421,69 @@ query getChecks($appId: Int!, $owner: String!, $repo:String!, $head: String!) { } |}] +module GetProjectFieldValues = +[%graphql +{| +query getProjectFieldValues($organization: String!, $project: Int!, $field: String!, $options: [String!]!) { + organization(login: $organization) { + projectV2(number: $project) { + id + field(name: $field) { + ... on ProjectV2SingleSelectField { + id + options(names: $options) { + id + name + } + } + } + } + } +} +|}] + (* Mutations *) -module MoveCardToColumn = +module AddCardToProject = +[%graphql +{| + mutation addCard($card_id:ID!, $project_id: ID!) { + addProjectV2ItemById(input:{contentId:$card_id,projectId:$project_id}) { + item { + id + } + } + } +|}] + +module UpdateFieldValue = [%graphql {| - mutation moveCard($card_id:ID!,$column_id:ID!) { - moveProjectCard(input:{cardId:$card_id,columnId:$column_id}) { + mutation updateFieldValue($card_id:ID!, $project_id: ID!, $field_id: ID!, $field_value_id: String!) { + updateProjectV2ItemFieldValue(input: {projectId: $project_id, itemId: $card_id, fieldId: $field_id, value: {singleSelectOptionId: $field_value_id}}) { clientMutationId } } |}] +module CreateNewReleaseManagementField = +[%graphql +{| + mutation createNewField($project_id: ID!, $field: String!) { + createProjectV2Field(input: {projectId: $project_id, dataType: SINGLE_SELECT, name: $field, singleSelectOptions: [{name: "Request inclusion", color: GREEN, description: "This merged pull request is proposed for inclusion."}, {name: "Shipped", color: PURPLE, description: "This pull request has been backported (or merged directly in the release branch)."}, {name: "Rejected", color: RED, description: "This merged pull request will not be included in this release."}]}) { + projectV2Field { + ... on ProjectV2SingleSelectField { + id + options(names: ["Request inclusion", "Shipped", "Rejected"]) { + id + name + } + } + } + } + } +|}] + module PostComment = [%graphql {| diff --git a/bot-components/GitHub_app.ml b/bot-components/GitHub_app.ml index 430bd549..22e06583 100644 --- a/bot-components/GitHub_app.ml +++ b/bot-components/GitHub_app.ml @@ -56,40 +56,26 @@ let post ~bot_info ~body ~token ~url = in Cohttp_lwt.Body.to_string body -let get_installation_token ~bot_info ~owner ~repo ~jwt : +let get_installation_token ~bot_info ~key ~app_id ~install_id : (string * float, string) Result.t Lwt.t = - get ~bot_info ~token:jwt - ~url:(f "https://api.github.com/repos/%s/%s/installation" owner repo) - >>= (fun body -> - try - let json = Yojson.Basic.from_string body in - let access_token_url = - Yojson.Basic.Util.(json |> member "access_tokens_url" |> to_string) - in - post ~bot_info ~body:None ~token:jwt ~url:access_token_url - >|= Result.return - with - | Yojson.Json_error err -> - Lwt.return_error (f "Json error: %s" err) - | Yojson.Basic.Util.Type_error (err, _) -> - Lwt.return_error (f "Json type error: %s" err) ) - >|= Result.bind ~f:(fun resp -> - try - let json = Yojson.Basic.from_string resp in - Ok - (* Installation tokens expire after one hour, let's stop using them after 40 minutes *) - ( Yojson.Basic.Util.(json |> member "token" |> to_string) - , Unix.time () +. (40. *. 60.) ) - with - | Yojson.Json_error err -> - Error (f "Json error: %s" err) - | Yojson.Basic.Util.Type_error (err, _) -> - Error (f "Json type error: %s" err) ) - -let get_installation_token ~bot_info ~key ~app_id ~owner ~repo = match make_jwt ~key ~app_id with - | Ok jwt -> - get_installation_token ~bot_info ~jwt ~owner ~repo + | Ok jwt -> ( + let access_token_url = + f "https://api.github.com/app/installations/%d/access_tokens" install_id + in + post ~bot_info ~body:None ~token:jwt ~url:access_token_url + >|= fun resp -> + try + let json = Yojson.Basic.from_string resp in + Ok + (* Installation tokens expire after one hour, let's stop using them after 40 minutes *) + ( Yojson.Basic.Util.(json |> member "token" |> to_string) + , Unix.time () +. (40. *. 60.) ) + with + | Yojson.Json_error err -> + Error (f "Json error: %s" err) + | Yojson.Basic.Util.Type_error (err, _) -> + Error (f "Json type error: %s" err) ) | Error e -> Lwt.return (Error e) @@ -104,7 +90,8 @@ let get_installations ~bot_info ~key ~app_id = Ok ( json |> to_list |> List.map ~f:(fun json -> - json |> member "account" |> member "login" |> to_string ) ) + ( json |> member "account" |> member "login" |> to_string + , json |> member "id" |> to_int ) ) ) with | Yojson.Json_error err -> Error (f "Json error: %s" err) diff --git a/bot-components/GitHub_app.mli b/bot-components/GitHub_app.mli index 1ad71a41..b9e40058 100644 --- a/bot-components/GitHub_app.mli +++ b/bot-components/GitHub_app.mli @@ -2,12 +2,11 @@ val get_installation_token : bot_info:Bot_info.t -> key:Mirage_crypto_pk.Rsa.priv -> app_id:int - -> owner:string - -> repo:string + -> install_id:int -> (string * float, string) result Lwt.t val get_installations : bot_info:Bot_info.t -> key:Mirage_crypto_pk.Rsa.priv -> app_id:int - -> (string list, string) result Lwt.t + -> ((string * int) list, string) result Lwt.t diff --git a/bot-components/GitHub_mutations.ml b/bot-components/GitHub_mutations.ml index 62423cd8..c46a659f 100644 --- a/bot-components/GitHub_mutations.ml +++ b/bot-components/GitHub_mutations.ml @@ -6,21 +6,71 @@ open Utils let send_graphql_query = GraphQL_query.send_graphql_query ~api:GitHub -let mv_card_to_column ~bot_info ({card_id; column_id} : mv_card_to_column_input) - = - let open GitHub_GraphQL.MoveCardToColumn in +let add_card_to_project ~bot_info ~card_id ~project_id = + let open GitHub_GraphQL.AddCardToProject in makeVariables ~card_id:(GitHub_ID.to_string card_id) - ~column_id:(GitHub_ID.to_string column_id) + ~project_id:(GitHub_ID.to_string project_id) () |> serializeVariables |> variablesToJson |> send_graphql_query ~bot_info ~query ~parse:(Fn.compose parse unsafe_fromJson) >>= function + | Ok result -> ( + match result.addProjectV2ItemById with + | None -> + Lwt.return_error "No item ID returned." + | Some {item} -> ( + match item with + | None -> + Lwt.return_error "No item ID returned." + | Some item -> + Lwt.return_ok (GitHub_ID.of_string item.id) ) ) + | Error err -> + Lwt.return (Error ("Error while adding card to project: " ^ err)) + +let update_field_value ~bot_info ~card_id ~project_id ~field_id ~field_value_id + = + let open GitHub_GraphQL.UpdateFieldValue in + makeVariables + ~card_id:(GitHub_ID.to_string card_id) + ~project_id:(GitHub_ID.to_string project_id) + ~field_id:(GitHub_ID.to_string field_id) + ~field_value_id () + |> serializeVariables |> variablesToJson + |> send_graphql_query ~bot_info ~query + ~parse:(Fn.compose parse unsafe_fromJson) + >>= function | Ok _ -> Lwt.return_unit | Error err -> - Lwt_io.printlf "Error while moving project card: %s" err + Lwt_io.printlf "Error while updating field value: %s" err + +let create_new_release_management_field ~bot_info ~project_id ~field = + let open GitHub_GraphQL.CreateNewReleaseManagementField in + makeVariables ~project_id:(GitHub_ID.to_string project_id) ~field () + |> serializeVariables |> variablesToJson + |> send_graphql_query ~bot_info ~query + ~parse:(Fn.compose parse unsafe_fromJson) + >>= function + | Ok result -> ( + match result.createProjectV2Field with + | None -> + Lwt.return_error "No field returned after creation." + | Some result -> ( + match result.projectV2Field with + | None -> + Lwt.return_error "No field returned after creation." + | Some (`ProjectV2SingleSelectField result) -> + Lwt.return_ok + ( GitHub_ID.of_string result.id + , result.options |> Array.to_list + |> List.map ~f:(fun {name; id} -> (name, id)) ) + | Some _ -> + Lwt.return_error + "Field returned after creation is not of type single select." ) ) + | Error err -> + Lwt.return_error (f "Error while creating new field: %s" err) let post_comment ~bot_info ~id ~message = let open GitHub_GraphQL.PostComment in @@ -212,21 +262,17 @@ let remove_labels ~bot_info ~labels ~issue = (* TODO: use GraphQL API *) -let update_milestone ~bot_info new_milestone (issue : issue) = +let remove_milestone ~bot_info (issue : issue) = let headers = headers (github_header bot_info) bot_info.github_name in let uri = f "https://api.github.com/repos/%s/%s/issues/%d" issue.owner issue.repo issue.number |> Uri.of_string in - let body = - f {|{"milestone": %s}|} new_milestone |> Cohttp_lwt.Body.of_string - in + let body = {|{"milestone": null}|} |> Cohttp_lwt.Body.of_string in Lwt_io.printf "Sending patch request.\n" >>= fun () -> Client.patch ~headers ~body uri >>= print_response -let remove_milestone = update_milestone "null" - let send_status_check ~bot_info ~repo_full_name ~commit ~state ~url ~context ~description = Lwt_io.printf "Sending status check to %s (commit %s, state %s)\n" @@ -243,17 +289,3 @@ let send_status_check ~bot_info ~repo_full_name ~commit ~state ~url ~context |> Uri.of_string in send_request ~body ~uri (github_header bot_info) bot_info.github_name - -let add_pr_to_column ~bot_info ~pr_id ~column_id = - let body = - f {|{"content_id":%d, "content_type": "PullRequest"}|} pr_id - |> Cohttp_lwt.Body.of_string - in - let uri = - "https://api.github.com/projects/columns/" ^ Int.to_string column_id - ^ "/cards" - |> Uri.of_string - in - send_request ~body ~uri - (project_api_preview_header @ github_header bot_info) - bot_info.github_name diff --git a/bot-components/GitHub_mutations.mli b/bot-components/GitHub_mutations.mli index 07faaf84..56e55614 100644 --- a/bot-components/GitHub_mutations.mli +++ b/bot-components/GitHub_mutations.mli @@ -1,7 +1,24 @@ open GitHub_types -val mv_card_to_column : - bot_info:Bot_info.t -> mv_card_to_column_input -> unit Lwt.t +val add_card_to_project : + bot_info:Bot_info.t + -> card_id:GitHub_ID.t + -> project_id:GitHub_ID.t + -> (GitHub_ID.t, string) result Lwt.t + +val update_field_value : + bot_info:Bot_info.t + -> card_id:GitHub_ID.t + -> project_id:GitHub_ID.t + -> field_id:GitHub_ID.t + -> field_value_id:string + -> unit Lwt.t + +val create_new_release_management_field : + bot_info:Bot_info.t + -> project_id:GitHub_ID.t + -> field:string + -> (GitHub_ID.t * (string * string) list, string) result Lwt.t val post_comment : bot_info:Bot_info.t @@ -64,7 +81,11 @@ val remove_labels : -> issue:GitHub_ID.t -> unit Lwt.t -val update_milestone : bot_info:Bot_info.t -> string -> issue -> unit Lwt.t +val update_milestone : + bot_info:Bot_info.t + -> issue:GitHub_ID.t + -> milestone:GitHub_ID.t + -> unit Lwt.t val remove_milestone : bot_info:Bot_info.t -> issue -> unit Lwt.t @@ -77,6 +98,3 @@ val send_status_check : -> context:string -> description:string -> unit Lwt.t - -val add_pr_to_column : - bot_info:Bot_info.t -> pr_id:int -> column_id:int -> unit Lwt.t diff --git a/bot-components/GitHub_queries.ml b/bot-components/GitHub_queries.ml index c8addfa8..1af574e9 100644 --- a/bot-components/GitHub_queries.ml +++ b/bot-components/GitHub_queries.ml @@ -7,68 +7,37 @@ open Utils let send_graphql_query = GraphQL_query.send_graphql_query ~api:GitHub let extract_backport_info ~(bot_info : Bot_info.t) description : - full_backport_info option = - let project_column_regexp = - "https://github.com/[^/]*/[^/]*/projects/[0-9]+#column-\\([0-9]+\\)" - in - let regexp = - bot_info.github_name - ^ ": backport to \\([^ ]*\\) (request inclusion column: " - ^ project_column_regexp ^ "; backported column: " ^ project_column_regexp - ^ "; move rejected PRs to: " + backport_info list = + let main_regexp = + "backport to \\([^ ]*\\) (.*move rejected PRs to: " ^ "https://github.com/[^/]*/[^/]*/milestone/\\([0-9]+\\)" ^ ")" in - if string_match ~regexp description then - let backport_to = Str.matched_group 1 description in - let request_inclusion_column = - Str.matched_group 2 description |> Int.of_string - in - let backported_column = Str.matched_group 3 description |> Int.of_string in - let rejected_milestone = Str.matched_group 4 description in - Some - { backport_info= - [{backport_to; request_inclusion_column; backported_column}] - ; rejected_milestone } - else - let begin_regexp = bot_info.github_name ^ ": \\(.*\\)$" in - let backport_info_unit = - "backport to \\([^ ]*\\) (request inclusion column: " - ^ project_column_regexp ^ "; backported column: " ^ project_column_regexp - ^ "); \\(.*\\)$" - in - let end_regexp = - "move rejected PRs to: \ - https://github.com/[^/]*/[^/]*/milestone/\\([0-9]+\\)" - in - let rec aux string = - if string_match ~regexp:backport_info_unit string then - let backport_to = Str.matched_group 1 string in - let request_inclusion_column = - Str.matched_group 2 string |> Int.of_string - in - let backported_column = Str.matched_group 3 string |> Int.of_string in - Str.matched_group 4 string |> aux - |> Option.map ~f:(fun {backport_info; rejected_milestone} -> - { backport_info= - {backport_to; request_inclusion_column; backported_column} - :: backport_info - ; rejected_milestone } ) - else if string_match ~regexp:end_regexp string then - let rejected_milestone = Str.matched_group 1 string in - Some {backport_info= []; rejected_milestone} - else None - in - if string_match ~regexp:begin_regexp description then - Str.matched_group 1 description |> aux - else None - -let convertMilestone milestone = - let open GitHub_GraphQL.PullRequest_Milestone_and_Cards.BackportInfo in - {milestone_title= milestone.title; description= milestone.description} + let begin_regexp = bot_info.github_name ^ ": \\(.*\\)$" in + let backport_info_unit = main_regexp ^ "; \\(.*\\)$" in + let end_regexp = main_regexp in + let rec aux description = + if string_match ~regexp:backport_info_unit description then + let backport_to = Str.matched_group 1 description in + let rejected_milestone = + Str.matched_group 2 description |> Int.of_string + in + Str.matched_group 3 description + |> aux + |> List.cons {backport_to; rejected_milestone} + else if string_match ~regexp:end_regexp description then + let backport_to = Str.matched_group 1 description in + let rejected_milestone = + Str.matched_group 2 description |> Int.of_string + in + [{backport_to; rejected_milestone}] + else [] + in + if string_match ~regexp:begin_regexp description then + Str.matched_group 1 description |> aux + else [] -let get_pull_request_milestone_and_cards ~bot_info ~owner ~repo ~number = - let open GitHub_GraphQL.PullRequest_Milestone_and_Cards in - let open BackportInfo in +let get_pull_request_cards ~bot_info ~owner ~repo ~number = + let open GitHub_GraphQL.PullRequest_Cards in makeVariables ~owner ~repo ~number () |> serializeVariables |> variablesToJson |> send_graphql_query ~bot_info ~query @@ -79,30 +48,16 @@ let get_pull_request_milestone_and_cards ~bot_info ~owner ~repo ~number = | Some result -> ( match result.pullRequest with | Some result -> - let cards = - match result.projectCards.nodes with + let items = + match result.projectItems.items with | None -> [] - | Some cards -> - cards |> Array.to_list |> List.filter_opt - |> List.map ~f:(fun card -> - { id= GitHub_ID.of_string card.id - ; column= - Option.map card.column ~f:(fun column -> - { GitHub_types.id= GitHub_ID.of_string column.id - ; databaseId= column.databaseId } ) - ; columns= - ( match card.project.columns.nodes with - | None -> - [] - | Some columns -> - columns |> Array.to_list |> List.filter_opt - |> List.map ~f:(fun column -> - { GitHub_types.id= - GitHub_ID.of_string column.Column.id - ; databaseId= column.databaseId } ) ) } ) + | Some items -> + items |> Array.to_list |> List.filter_opt + |> List.map ~f:(fun item -> + (GitHub_ID.of_string item.item_id, item.projectV2.number) ) in - Ok (cards, Option.map ~f:convertMilestone result.milestone) + Ok items | None -> Error (f "Pull request %s/%s#%d does not exist." owner repo number) ) | None -> @@ -110,37 +65,27 @@ let get_pull_request_milestone_and_cards ~bot_info ~owner ~repo ~number = | Error err -> Error err -let get_backported_pr_info ~bot_info number base_ref = - get_pull_request_milestone_and_cards ~bot_info ~owner:"coq" ~repo:"coq" - ~number - >|= 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 ) ) - |> fun res -> Ok res - | Error err -> - Error (f "Error in backported_pr_info: %s." err) +let get_pull_request_milestone ~bot_info ~pr_id = + let open GitHub_GraphQL.PullRequest_Milestone in + let pr_id = GitHub_ID.to_string pr_id in + makeVariables ~pr_id () |> serializeVariables |> variablesToJson + |> send_graphql_query ~bot_info ~query + ~parse:(Fn.compose parse unsafe_fromJson) + >|= Result.bind ~f:(fun result -> + match result.node with + | Some (`PullRequest result) -> ( + match result.milestone with + | Some milestone -> + Ok + ( milestone.description + |> Option.map ~f:(extract_backport_info ~bot_info) + |> Option.value ~default:[] ) + | None -> + Ok [] ) + | Some _ -> + Error (f "Node %s is not a pull request." pr_id) + | None -> + Error (f "Pull request %s does not exist." pr_id) ) let get_pull_request_id_and_milestone ~bot_info ~owner ~repo ~number = let open GitHub_GraphQL.PullRequest_ID_and_Milestone in @@ -158,26 +103,17 @@ let get_pull_request_id_and_milestone ~bot_info ~owner ~repo ~number = Error (f "Pull request %s/%s#%d does not exist." owner repo number) | Some pr -> ( - match (pr.databaseId, pr.milestone) with - | None, _ -> - Error - (f "Pull request %s/%s#%d does not have a database ID." - owner repo number ) - | _, None -> + match pr.milestone with + | None -> Error (f "Pull request %s/%s#%d does not have a milestone." owner repo number ) - | Some db_id, Some milestone -> + | Some milestone -> Ok - ( match milestone.description with - | Some description -> ( - match extract_backport_info ~bot_info description with - | Some bp_info -> - Some (GitHub_ID.of_string pr.id, db_id, bp_info) - | _ -> - None ) - | _ -> - None ) ) ) ) + ( GitHub_ID.of_string pr.id + , milestone.description + |> Option.map ~f:(extract_backport_info ~bot_info) + |> Option.value ~default:[] ) ) ) ) let get_pull_request_id ~bot_info ~owner ~repo ~number = let open GitHub_GraphQL.PullRequest_ID in @@ -197,6 +133,25 @@ let get_pull_request_id ~bot_info ~owner ~repo ~number = | Some pr -> Ok (GitHub_ID.of_string pr.id) ) ) +let get_milestone_id ~bot_info ~owner ~repo ~number = + let open GitHub_GraphQL.Milestone_ID in + makeVariables ~owner ~repo ~number () + |> serializeVariables |> variablesToJson + |> send_graphql_query ~bot_info ~query + ~parse:(Fn.compose parse unsafe_fromJson) + >|= Result.bind ~f:(fun result -> + match result.repository with + | None -> + Error (f "Repository %s/%s does not exist." owner repo) + | Some result -> ( + match result.milestone with + | None -> + Error + (f "Milestone %d does not exist in repository %s/%s." number + owner repo ) + | Some milestone -> + Ok (GitHub_ID.of_string milestone.id) ) ) + let team_membership_of_resp ~org ~team ~user resp = let open GitHub_GraphQL.TeamMembership in match resp.organization with @@ -874,27 +829,6 @@ let get_pipeline_summary ~bot_info ~owner ~repo ~head = %s/%s@%s." owner repo head ) ) ) ) ) -(* TODO: use GraphQL API *) - -let get_cards_in_column column_id = - generic_get - ("projects/columns/" ^ Int.to_string column_id ^ "/cards") - ~header_list:project_api_preview_header - (fun json -> - let open Yojson.Basic.Util in - json |> to_list - |> List.filter_map ~f:(fun json -> - let card_id = json |> member "id" |> to_int in - let content_url = - json |> member "content_url" |> to_string_option - |> Option.value ~default:"" - in - let regexp = "https://api.github.com/repos/.*/\\([0-9]*\\)" in - if string_match ~regexp content_url then - let pr_number = Str.matched_group 1 content_url in - Some (pr_number, card_id) - else None ) ) - let get_list getter = let rec get_list_aux cursor accu = getter cursor @@ -903,11 +837,11 @@ let get_list getter = let accu = List.rev_append ans accu in match cursor with | None -> - Lwt.return (Ok (List.rev accu)) + Lwt.return_ok (List.rev accu) | Some cursor -> get_list_aux (Some cursor) accu ) | Error err -> - Lwt.return @@ Error err + Lwt.return_error err in get_list_aux None [] @@ -939,12 +873,11 @@ let get_open_pull_requests_with_label ~bot_info ~owner ~repo ~label = in List.filter_map ~f:map (Array.to_list data) in - Lwt.return (Ok (data, next)) + Lwt.return_ok (data, next) | None -> - Lwt.return @@ Error (f "Repository %s/%s does not exist." owner repo) - ) + Lwt.return_error (f "Repository %s/%s does not exist." owner repo) ) | Error err -> - Lwt.return @@ Error err + Lwt.return_error err in get_list getter @@ -987,15 +920,14 @@ let get_pull_request_label_timeline ~bot_info ~owner ~repo ~pr_number = in List.filter_map ~f:map (Array.to_list data) in - Lwt.return (Ok (data, next)) + Lwt.return_ok (data, next) | None -> - Lwt.return - @@ Error (f "Unknown pull request %s/%s#%d" owner repo pr_number) ) + Lwt.return_error + (f "Unknown pull request %s/%s#%d" owner repo pr_number) ) | None -> - Lwt.return @@ Error (f "Repository %s/%s does not exist." owner repo) - ) + Lwt.return_error (f "Repository %s/%s does not exist." owner repo) ) | Error err -> - Lwt.return @@ Error err + Lwt.return_error err in get_list getter @@ -1043,16 +975,49 @@ let get_pull_request_labels ~bot_info ~owner ~repo ~pr_number = let map o = Option.map ~f:(fun o -> o.name) o in List.filter_map ~f:map (Array.to_list data) in - Lwt.return (Ok (data, next)) + Lwt.return_ok (data, next) | None -> - Lwt.return @@ Error (f "Error querying labels") ) + Lwt.return_error (f "Error querying labels") ) | None -> Lwt.return @@ Error (f "Unknown pull request %s/%s#%d" owner repo pr_number) ) | None -> - Lwt.return @@ Error (f "Repository %s/%s does not exist." owner repo) - ) + Lwt.return_error (f "Repository %s/%s does not exist." owner repo) ) | Error err -> - Lwt.return @@ Error err + Lwt.return_error err in get_list getter + +let get_project_field_values ~bot_info ~organization ~project ~field ~options = + let open GitHub_GraphQL.GetProjectFieldValues in + makeVariables ~organization ~project ~field ~options () + |> serializeVariables |> variablesToJson + |> send_graphql_query ~bot_info ~query + ~parse:(Fn.compose parse unsafe_fromJson) + >>= function + | Ok result -> ( + match result.organization with + | Some result -> ( + match result.projectV2 with + | Some project -> ( + match project.field with + | Some (`ProjectV2SingleSelectField field) -> + let options = field.options |> Array.to_list in + Lwt.return_ok + ( GitHub_ID.of_string project.id + , Some + ( GitHub_ID.of_string field.id + , List.map ~f:(fun {name; id} -> (name, id)) options ) ) + | Some _ -> + Lwt.return_error (f "Field %s is not a single select field." field) + | None -> + (* We consider the field not existing in the project to be + acceptable, because it can be created then. *) + Lwt.return_ok (GitHub_ID.of_string project.id, None) ) + | None -> + Lwt.return_error + (f "Unknown project %d of organization %s" project organization) ) + | None -> + Lwt.return_error (f "Organization %s does not exist." organization) ) + | Error err -> + Lwt.return_error err diff --git a/bot-components/GitHub_queries.mli b/bot-components/GitHub_queries.mli index 25f3fee2..b9b569e4 100644 --- a/bot-components/GitHub_queries.mli +++ b/bot-components/GitHub_queries.mli @@ -1,24 +1,23 @@ open GitHub_types -val get_pull_request_milestone_and_cards : +val get_pull_request_cards : bot_info:Bot_info.t -> owner:string -> repo:string -> number:int - -> (project_card list * milestone option, string) result Lwt.t + -> ((GitHub_ID.t * int) list, string) result Lwt.t -val get_backported_pr_info : +val get_pull_request_milestone : bot_info:Bot_info.t - -> int - -> string - -> (mv_card_to_column_input option, string) result Lwt.t + -> pr_id:GitHub_ID.t + -> (backport_info list, string) result Lwt.t val get_pull_request_id_and_milestone : bot_info:Bot_info.t -> owner:string -> repo:string -> number:int - -> ((GitHub_ID.t * int * full_backport_info) option, string) result Lwt.t + -> (GitHub_ID.t * backport_info list, string) result Lwt.t val get_pull_request_id : bot_info:Bot_info.t @@ -27,6 +26,13 @@ val get_pull_request_id : -> number:int -> (GitHub_ID.t, string) result Lwt.t +val get_milestone_id : + bot_info:Bot_info.t + -> owner:string + -> repo:string + -> number:int + -> (GitHub_ID.t, string) result Lwt.t + val get_team_membership : bot_info:Bot_info.t -> org:string @@ -106,9 +112,6 @@ val get_pipeline_summary : -> head:string -> (string, string) result Lwt.t -val get_cards_in_column : - int -> bot_info:Bot_info.t -> ((string * int) list, string) result Lwt.t - val get_open_pull_requests_with_label : bot_info:Bot_info.t -> owner:string @@ -137,3 +140,14 @@ val get_pull_request_labels : -> repo:string -> pr_number:int -> (string list, string) result Lwt.t + +val get_project_field_values : + bot_info:Bot_info.t + -> organization:string + -> project:int + -> field:string + -> options:string array + -> ( GitHub_ID.t * (GitHub_ID.t * (string * string) list) option + , string ) + result + Lwt.t diff --git a/bot-components/GitHub_subscriptions.ml b/bot-components/GitHub_subscriptions.ml index 0d19619e..2bb5b757 100644 --- a/bot-components/GitHub_subscriptions.ml +++ b/bot-components/GitHub_subscriptions.ml @@ -49,25 +49,6 @@ let pull_request_info_of_json json = (match pr_json |> member "merged_at" with `Null -> false | _ -> true) ; last_commit_message= None } -let project_card_of_json json = - let card_json = json |> member "project_card" in - let column_id = card_json |> member "column_id" |> to_int in - let regexp = - "https://api.github.com/repos/\\([^/]*\\)/\\([^/]*\\)/issues/\\([0-9]*\\)" - in - match card_json |> member "content_url" with - | `Null -> - Ok {issue= None; column_id} - | `String content_url when string_match ~regexp content_url -> - let owner = Str.matched_group 1 content_url in - let repo = Str.matched_group 2 content_url in - let number = Str.matched_group 3 content_url |> Int.of_string in - Ok {issue= Some {owner; repo; number}; column_id} - | `String _ -> - Error "Could not parse content_url field." - | _ -> - Error "content_url field has unexpected type." - let comment_info_of_json ?(review_comment = false) json = let comment_json = if review_comment then json |> member "review" else json |> member "comment" @@ -153,7 +134,7 @@ let push_event_info_of_json json = type msg = | IssueOpened of issue_info | IssueClosed of issue_info - | RemovedFromProject of project_card_issue + | PullRequestCardEdited of pull_request_card_info | PullRequestUpdated of pull_request_action * issue_info pull_request_info | BranchCreated of remote_ref_info | TagCreated of remote_ref_info @@ -184,9 +165,27 @@ let github_action ~event ~action json = Ok (IssueOpened (issue_info_of_json json)) | "issues", "closed" -> Ok (IssueClosed (issue_info_of_json json)) - | "project_card", "deleted" -> - json |> project_card_of_json - |> Result.map ~f:(fun card -> RemovedFromProject card) + | "projects_v2_item", "edited" + when String.equal "PullRequest" + ( json |> member "projects_v2_item" |> member "content_type" + |> to_string ) + && String.equal "single_select" + ( json |> member "changes" |> member "field_value" + |> member "field_type" |> to_string ) -> + let card_json = json |> member "projects_v2_item" in + let changes_json = json |> member "changes" |> member "field_value" in + Ok + (PullRequestCardEdited + { pr_id= card_json |> member "content_node_id" |> GitHub_ID.of_json + ; card_id= card_json |> member "node_id" |> GitHub_ID.of_json + ; project_id= + card_json |> member "project_node_id" |> GitHub_ID.of_json + ; project_number= changes_json |> member "project_number" |> to_int + ; field= changes_json |> member "field_name" |> to_string + ; old_value= + changes_json |> member "from" |> member "name" |> to_string + ; new_value= + changes_json |> member "to" |> member "name" |> to_string } ) | "issue_comment", "created" -> Ok (CommentCreated (comment_info_of_json json)) | "pull_request_review", "submitted" -> @@ -204,7 +203,7 @@ let github_event ~event json = match event with | "pull_request" | "issues" - | "project_card" + | "projects_v2_item" | "issue_comment" | "pull_request_review" | "check_run" @@ -228,24 +227,30 @@ let github_event ~event json = Ok (UnsupportedEvent "Unsupported GitHub event.") let receive_github ~secret headers body = - let open Result in - ( match Header.get headers "X-Hub-Signature" with - | Some signature -> - let expected = - Mirage_crypto.Hash.SHA1.hmac ~key:(Cstruct.of_string secret) - (Cstruct.of_string body) - |> Hex.of_cstruct |> Hex.show |> f "sha1=%s" - in - if Eqaf.equal signature expected then return true - else Error "Webhook signed but with wrong signature." - | None -> - return false ) - >>= fun signed -> + let open Result.Monad_infix in match Header.get headers "X-GitHub-Event" with | Some event -> ( try let json = Yojson.Basic.from_string body in - github_event ~event json |> Result.map ~f:(fun r -> (signed, r)) + ( try + let install_id = + json |> member "installation" |> member "id" |> to_int + in + (* if there is an install id, the webhook should be signed *) + match Header.get headers "X-Hub-Signature" with + | Some signature -> + let expected = + Mirage_crypto.Hash.SHA1.hmac ~key:(Cstruct.of_string secret) + (Cstruct.of_string body) + |> Hex.of_cstruct |> Hex.show |> f "sha1=%s" + in + if Eqaf.equal signature expected then Ok (Some install_id) + else Error "Webhook signed but with wrong signature." + | None -> + Error "Webhook comes from a GitHub App, but it is not signed." + with Yojson.Json_error _ | Type_error _ -> Ok None ) + >>= fun install_id -> + github_event ~event json |> Result.map ~f:(fun r -> (install_id, r)) with | Yojson.Json_error err -> Error (f "Json error: %s" err) diff --git a/bot-components/GitHub_subscriptions.mli b/bot-components/GitHub_subscriptions.mli index 9db61dbf..7ca8b11a 100644 --- a/bot-components/GitHub_subscriptions.mli +++ b/bot-components/GitHub_subscriptions.mli @@ -3,7 +3,7 @@ open GitHub_types type msg = | IssueOpened of issue_info | IssueClosed of issue_info - | RemovedFromProject of project_card_issue + | PullRequestCardEdited of pull_request_card_info | PullRequestUpdated of pull_request_action * issue_info pull_request_info | BranchCreated of remote_ref_info | TagCreated of remote_ref_info @@ -17,4 +17,7 @@ type msg = | UnsupportedEvent of string val receive_github : - secret:string -> Cohttp.Header.t -> string -> (bool * msg, string) result + secret:string + -> Cohttp.Header.t + -> string + -> (int option * msg, string) result diff --git a/bot-components/GitHub_types.mli b/bot-components/GitHub_types.mli index 1301d053..c8f37f77 100644 --- a/bot-components/GitHub_types.mli +++ b/bot-components/GitHub_types.mli @@ -7,14 +7,16 @@ type project_column = {id: GitHub_ID.t; databaseId: int option} type merge_method = MERGE | REBASE | SQUASH -type backport_info = - {backport_to: string; request_inclusion_column: int; backported_column: int} - -type full_backport_info = - {backport_info: backport_info list; rejected_milestone: string} - -type project_card = - {id: GitHub_ID.t; column: project_column option; columns: project_column list} +type backport_info = {backport_to: string; rejected_milestone: int} + +type pull_request_card_info = + { pr_id: GitHub_ID.t + ; card_id: GitHub_ID.t + ; project_id: GitHub_ID.t + ; project_number: int + ; field: string + ; old_value: string + ; new_value: string } type mv_card_to_column_input = {card_id: GitHub_ID.t; column_id: GitHub_ID.t} diff --git a/bot-components/github-schema.json b/bot-components/github-schema.json index 62a3008b..1bc90456 100644 --- a/bot-components/github-schema.json +++ b/bot-components/github-schema.json @@ -17111,6 +17111,90 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "ConvertProjectV2DraftIssueItemToIssueInput", + "description": "Autogenerated input type of ConvertProjectV2DraftIssueItemToIssue", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "itemId", + "description": "The ID of the draft issue ProjectV2Item to convert.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "repositoryId", + "description": "The ID of the repository to create the issue in.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ConvertProjectV2DraftIssueItemToIssuePayload", + "description": "Autogenerated return type of ConvertProjectV2DraftIssueItemToIssue.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "item", + "description": "The updated project item.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ProjectV2Item", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "ConvertPullRequestToDraftInput", @@ -20186,6 +20270,116 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "CreateProjectV2StatusUpdateInput", + "description": "Autogenerated input type of CreateProjectV2StatusUpdate", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "projectId", + "description": "The ID of the Project to create the status update in.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "startDate", + "description": "The start date of the status update.", + "type": { + "kind": "SCALAR", + "name": "Date", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "targetDate", + "description": "The target date of the status update.", + "type": { + "kind": "SCALAR", + "name": "Date", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "status", + "description": "The status of the status update.", + "type": { + "kind": "ENUM", + "name": "ProjectV2StatusUpdateStatus", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "body", + "description": "The body of the status update.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CreateProjectV2StatusUpdatePayload", + "description": "Autogenerated return type of CreateProjectV2StatusUpdate.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "statusUpdate", + "description": "The status update updated in the project.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdate", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "CreatePullRequestInput", @@ -24399,6 +24593,88 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "DeleteProjectV2StatusUpdateInput", + "description": "Autogenerated input type of DeleteProjectV2StatusUpdate", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "statusUpdateId", + "description": "The ID of the status update to be removed.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DeleteProjectV2StatusUpdatePayload", + "description": "Autogenerated return type of DeleteProjectV2StatusUpdate.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "deletedStatusUpdateId", + "description": "The ID of the deleted status update.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "projectV2", + "description": "The project the deleted status update was in.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ProjectV2", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "DeleteProjectV2WorkflowInput", @@ -58055,6 +58331,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "convertProjectV2DraftIssueItemToIssue", + "description": "Converts a projectV2 draft issue item to an issue.", + "args": [ + { + "name": "input", + "description": "Parameters for ConvertProjectV2DraftIssueItemToIssue", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ConvertProjectV2DraftIssueItemToIssueInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ConvertProjectV2DraftIssueItemToIssuePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "convertPullRequestToDraft", "description": "Converts a pull request to draft", @@ -58595,6 +58898,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "createProjectV2StatusUpdate", + "description": "Creates a status update within a Project.", + "args": [ + { + "name": "input", + "description": "Parameters for CreateProjectV2StatusUpdate", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CreateProjectV2StatusUpdateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CreateProjectV2StatusUpdatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createPullRequest", "description": "Create a new pull request", @@ -59378,6 +59708,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "deleteProjectV2StatusUpdate", + "description": "Deletes a project status update.", + "args": [ + { + "name": "input", + "description": "Parameters for DeleteProjectV2StatusUpdate", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DeleteProjectV2StatusUpdateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DeleteProjectV2StatusUpdatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "deleteProjectV2Workflow", "description": "Deletes a project workflow.", @@ -62888,6 +63245,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "updateProjectV2StatusUpdate", + "description": "Updates a status update within a Project.", + "args": [ + { + "name": "input", + "description": "Parameters for UpdateProjectV2StatusUpdate", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "UpdateProjectV2StatusUpdateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "UpdateProjectV2StatusUpdatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updatePullRequest", "description": "Update a pull request", @@ -64168,6 +64552,11 @@ "name": "ProjectV2SingleSelectField", "ofType": null }, + { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdate", + "ofType": null + }, { "kind": "OBJECT", "name": "ProjectV2View", @@ -85996,6 +86385,73 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "statusUpdates", + "description": "List of the status updates in the project.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "orderBy", + "description": "Order for connection", + "type": { + "kind": "INPUT_OBJECT", + "name": "ProjectV2StatusOrder", + "ofType": null + }, + "defaultValue": "{field: CREATED_AT, direction: DESC}" + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdateConnection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "teams", "description": "The teams the project is linked to.", @@ -90781,7 +91237,505 @@ "args": [], "type": { "kind": "OBJECT", - "name": "ProjectV2SortBy", + "name": "ProjectV2SortBy", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProjectV2SortByField", + "description": "Represents a sort by field and direction.", + "fields": [ + { + "name": "direction", + "description": "The direction of the sorting. Possible values are ASC and DESC.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "OrderDirection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "field", + "description": "The field by which items are sorted.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "UNION", + "name": "ProjectV2FieldConfiguration", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProjectV2SortByFieldConnection", + "description": "The connection type for ProjectV2SortByField.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectV2SortByFieldEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectV2SortByField", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "totalCount", + "description": "Identifies the total count of items in the connection.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProjectV2SortByFieldEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ProjectV2SortByField", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "ProjectV2State", + "description": "The possible states of a project v2.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "OPEN", + "description": "A project v2 that is still open", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CLOSED", + "description": "A project v2 that has been closed", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "ProjectV2StatusOrder", + "description": "Ways in which project v2 status updates can be ordered.", + "fields": null, + "inputFields": [ + { + "name": "field", + "description": "The field by which to order nodes.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "ProjectV2StatusUpdateOrderField", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "direction", + "description": "The direction in which to order nodes.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "OrderDirection", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdate", + "description": "A status update within a project.", + "fields": [ + { + "name": "body", + "description": "The body of the status update.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "bodyHTML", + "description": "The body of the status update rendered to HTML.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "HTML", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "createdAt", + "description": "Identifies the date and time when the object was created.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "creator", + "description": "The actor who created the status update.", + "args": [], + "type": { + "kind": "INTERFACE", + "name": "Actor", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "databaseId", + "description": "Identifies the primary key from the database.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "The Node ID of the ProjectV2StatusUpdate object", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "project", + "description": "The project that contains this status update.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectV2", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startDate", + "description": "The start date of the status update.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Date", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "status", + "description": "The status of the status update.", + "args": [], + "type": { + "kind": "ENUM", + "name": "ProjectV2StatusUpdateStatus", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "targetDate", + "description": "The target date of the status update.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Date", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatedAt", + "description": "Identifies the date and time when the object was last updated.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null + } + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdateConnection", + "description": "The connection type for ProjectV2StatusUpdate.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdateEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdate", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "totalCount", + "description": "Identifies the total count of items in the connection.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdateEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdate", "ofType": null }, "isDeprecated": false, @@ -90794,179 +91748,57 @@ "possibleTypes": null }, { - "kind": "OBJECT", - "name": "ProjectV2SortByField", - "description": "Represents a sort by field and direction.", - "fields": [ - { - "name": "direction", - "description": "The direction of the sorting. Possible values are ASC and DESC.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "OrderDirection", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, + "kind": "ENUM", + "name": "ProjectV2StatusUpdateOrderField", + "description": "Properties by which project v2 status updates can be ordered.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ { - "name": "field", - "description": "The field by which items are sorted.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "UNION", - "name": "ProjectV2FieldConfiguration", - "ofType": null - } - }, + "name": "CREATED_AT", + "description": "Allows chronological ordering of project v2 status updates.", "isDeprecated": false, "deprecationReason": null } ], - "inputFields": null, - "interfaces": [], - "enumValues": null, "possibleTypes": null }, { - "kind": "OBJECT", - "name": "ProjectV2SortByFieldConnection", - "description": "The connection type for ProjectV2SortByField.", - "fields": [ - { - "name": "edges", - "description": "A list of edges.", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "ProjectV2SortByFieldEdge", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, + "kind": "ENUM", + "name": "ProjectV2StatusUpdateStatus", + "description": "The possible statuses of a project v2.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ { - "name": "nodes", - "description": "A list of nodes.", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "ProjectV2SortByField", - "ofType": null - } - }, + "name": "INACTIVE", + "description": "A project v2 that is inactive.", "isDeprecated": false, "deprecationReason": null }, { - "name": "pageInfo", - "description": "Information to aid in pagination.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "PageInfo", - "ofType": null - } - }, + "name": "ON_TRACK", + "description": "A project v2 that is on track with no risks.", "isDeprecated": false, "deprecationReason": null }, { - "name": "totalCount", - "description": "Identifies the total count of items in the connection.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ProjectV2SortByFieldEdge", - "description": "An edge in a connection.", - "fields": [ - { - "name": "cursor", - "description": "A cursor for use in pagination.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, + "name": "AT_RISK", + "description": "A project v2 that is at risk and encountering some challenges.", "isDeprecated": false, "deprecationReason": null }, { - "name": "node", - "description": "The item at the end of the edge.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "ProjectV2SortByField", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "ProjectV2State", - "description": "The possible states of a project v2.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "OPEN", - "description": "A project v2 that is still open", + "name": "OFF_TRACK", + "description": "A project v2 that is off track and needs attention.", "isDeprecated": false, "deprecationReason": null }, { - "name": "CLOSED", - "description": "A project v2 that has been closed", + "name": "COMPLETE", + "description": "A project v2 that is complete.", "isDeprecated": false, "deprecationReason": null } @@ -92194,6 +93026,18 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "source", + "description": "The source of the property. Choose 'custom' or 'system'. Defaults to 'custom' if not specified", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -92242,6 +93086,16 @@ } }, "defaultValue": null + }, + { + "name": "source", + "description": "The source of the property. Choose 'custom' or 'system'. Defaults to 'custom' if not specified", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null } ], "interfaces": null, @@ -150930,6 +151784,116 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "UpdateProjectV2StatusUpdateInput", + "description": "Autogenerated input type of UpdateProjectV2StatusUpdate", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "statusUpdateId", + "description": "The ID of the status update to be updated.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "startDate", + "description": "The start date of the status update.", + "type": { + "kind": "SCALAR", + "name": "Date", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "targetDate", + "description": "The target date of the status update.", + "type": { + "kind": "SCALAR", + "name": "Date", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "status", + "description": "The status of the status update.", + "type": { + "kind": "ENUM", + "name": "ProjectV2StatusUpdateStatus", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "body", + "description": "The body of the status update.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "UpdateProjectV2StatusUpdatePayload", + "description": "Autogenerated return type of UpdateProjectV2StatusUpdate.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "statusUpdate", + "description": "The status update updated in the project.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ProjectV2StatusUpdate", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "UpdatePullRequestBranchInput", diff --git a/bot-components/gitlab-schema.json b/bot-components/gitlab-schema.json index 52e1b2af..1b4099a0 100644 --- a/bot-components/gitlab-schema.json +++ b/bot-components/gitlab-schema.json @@ -2012,19 +2012,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -2357,19 +2353,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -3464,19 +3456,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -3835,6 +3823,16 @@ }, "defaultValue": null }, + { + "name": "sort", + "description": "List starred projects by sort order.", + "type": { + "kind": "ENUM", + "name": "ProjectSort", + "ofType": null + }, + "defaultValue": "NAME_ASC" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -5258,6 +5256,35 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "AiAcceptedSelfHostedModels", + "description": "LLMs supported by the self-hosted model features.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "MISTRAL", + "description": "Mistral7B model from Mistral AI.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "MIXTRAL", + "description": "Mixtral8x22B model from Mistral AI.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CODEGEMMA", + "description": "CodeGemma 2b or 7b model.", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "ENUM", "name": "AiAction", @@ -6986,22 +7013,6 @@ }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "codeSuggestionsUsageRate", - "description": "Percentage of contributors who used GitLab Duo Code Suggestions features.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -7051,7 +7062,7 @@ "fields": [ { "name": "createdAt", - "description": "Date of creation.", + "description": "Timestamp of creation.", "args": [], "type": { "kind": "NON_NULL", @@ -7067,7 +7078,7 @@ }, { "name": "endpoint", - "description": "Endpoint of the Self-Hosted model server.", + "description": "Endpoint of the self-hosted model server.", "args": [], "type": { "kind": "NON_NULL", @@ -7083,7 +7094,7 @@ }, { "name": "hasApiToken", - "description": "Indicates if an API key is set for the Self-Hosted model server.", + "description": "Indicates if an API key is set for the self-hosted model server.", "args": [], "type": { "kind": "NON_NULL", @@ -7099,7 +7110,7 @@ }, { "name": "id", - "description": "ID of the Self-Hosted model server.", + "description": "ID of the self-hosted model server.", "args": [], "type": { "kind": "NON_NULL", @@ -7115,7 +7126,7 @@ }, { "name": "model", - "description": "Model running the Self-Hosted model server.", + "description": "AI model deployed.", "args": [], "type": { "kind": "NON_NULL", @@ -7130,15 +7141,15 @@ "deprecationReason": null }, { - "name": "modifiedAt", - "description": "Date of last modification.", + "name": "name", + "description": "Deployment name of the self-hosted model.", "args": [], "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "Time", + "name": "String", "ofType": null } }, @@ -7146,17 +7157,13 @@ "deprecationReason": null }, { - "name": "name", - "description": "Given name of the Self-Hosted model server.", + "name": "updatedAt", + "description": "Timestamp of last update.", "args": [], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "Time", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -7226,6 +7233,138 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "AiSelfHostedModelCreateInput", + "description": "Autogenerated input type of AiSelfHostedModelCreate", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "name", + "description": "Deployment name of the self-hosted model.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "model", + "description": "AI model deployed.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "AiAcceptedSelfHostedModels", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "endpoint", + "description": "Endpoint of the self-hosted model.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "apiToken", + "description": "API token to access the self-hosted model, if any.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "AiSelfHostedModelCreatePayload", + "description": "Autogenerated return type of AiSelfHostedModelCreate.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "selfHostedModel", + "description": "Self-hosted model after mutation.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "AiSelfHostedModel", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "AiSelfHostedModelEdge", @@ -7277,62 +7416,65 @@ }, { "kind": "INPUT_OBJECT", - "name": "AiSummarizeCommentsInput", - "description": null, + "name": "AiSelfHostedModelUpdateInput", + "description": "Autogenerated input type of AiSelfHostedModelUpdate", "fields": null, "inputFields": [ { - "name": "resourceId", - "description": "Global ID of the resource to mutate.", + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": "Global ID of the self-hosted model to update.", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "AiModelID", + "name": "AiSelfHostedModelID", "ofType": null } }, "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "AiSummarizeNewMergeRequestInput", - "description": "Summarize a new merge request based on two branches. Returns `null` if the `add_ai_summary_for_new_mr` feature flag is disabled.", - "fields": null, - "inputFields": [ + }, { - "name": "resourceId", - "description": "Global ID of the resource to mutate.", + "name": "name", + "description": "Deployment name of the self-hosted model.", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "AiModelID", + "name": "String", "ofType": null } }, "defaultValue": null }, { - "name": "sourceProjectId", - "description": "ID of the project where the changes are from.", + "name": "model", + "description": "AI model deployed.", "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "AiAcceptedSelfHostedModels", + "ofType": null + } }, "defaultValue": null }, { - "name": "sourceBranch", - "description": "Source branch of the changes.", + "name": "endpoint", + "description": "Endpoint of the self-hosted model.", "type": { "kind": "NON_NULL", "name": null, @@ -7345,27 +7487,170 @@ "defaultValue": null }, { - "name": "targetBranch", - "description": "Target branch of where the changes will be merged into.", + "name": "apiToken", + "description": "API token to access the self-hosted model, if any.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "AiSelfHostedModelUpdatePayload", + "description": "Autogenerated return type of AiSelfHostedModelUpdate.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "selfHostedModel", + "description": "Self-hosted model after mutation.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "AiSelfHostedModel", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null } ], - "interfaces": null, + "inputFields": null, + "interfaces": [], "enumValues": null, "possibleTypes": null }, { "kind": "INPUT_OBJECT", - "name": "AiSummarizeReviewInput", + "name": "AiSummarizeCommentsInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "resourceId", + "description": "Global ID of the resource to mutate.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "AiModelID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "AiSummarizeNewMergeRequestInput", + "description": "Summarize a new merge request based on two branches. Returns `null` if the `add_ai_summary_for_new_mr` feature flag is disabled.", + "fields": null, + "inputFields": [ + { + "name": "resourceId", + "description": "Global ID of the resource to mutate.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "AiModelID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "sourceProjectId", + "description": "ID of the project where the changes are from.", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sourceBranch", + "description": "Source branch of the changes.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "targetBranch", + "description": "Target branch of where the changes will be merged into.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "AiSummarizeReviewInput", "description": null, "fields": null, "inputFields": [ @@ -13673,40 +13958,10 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "SCALAR", - "name": "AuditEventsInstanceExternalAuditEventDestinationID", - "description": "A `AuditEventsInstanceExternalAuditEventDestinationID` is a global ID. It is encoded as a string.\n\nAn example `AuditEventsInstanceExternalAuditEventDestinationID` is: `\"gid://gitlab/AuditEvents::InstanceExternalAuditEventDestination/1\"`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "AuditEventsInstanceExternalStreamingDestinationID", - "description": "A `AuditEventsInstanceExternalStreamingDestinationID` is a global ID. It is encoded as a string.\n\nAn example `AuditEventsInstanceExternalStreamingDestinationID` is: `\"gid://gitlab/AuditEvents::Instance::ExternalStreamingDestination/1\"`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "AuditEventsInstanceGoogleCloudLoggingConfigurationID", - "description": "A `AuditEventsInstanceGoogleCloudLoggingConfigurationID` is a global ID. It is encoded as a string.\n\nAn example `AuditEventsInstanceGoogleCloudLoggingConfigurationID` is: `\"gid://gitlab/AuditEvents::Instance::GoogleCloudLoggingConfiguration/1\"`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, { "kind": "INPUT_OBJECT", - "name": "AuditEventsStreamingDestinationEventsAddInput", - "description": "Autogenerated input type of AuditEventsStreamingDestinationEventsAdd", + "name": "AuditEventsInstanceDestinationNamespaceFilterCreateInput", + "description": "Autogenerated input type of AuditEventsInstanceDestinationNamespaceFilterCreate", "fields": null, "inputFields": [ { @@ -13720,38 +13975,26 @@ "defaultValue": null }, { - "name": "eventTypeFilters", - "description": "List of event type filters to add for streaming.", + "name": "destinationId", + "description": "Destination ID.", "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } + "kind": "SCALAR", + "name": "AuditEventsInstanceExternalStreamingDestinationID", + "ofType": null } }, "defaultValue": null }, { - "name": "destinationId", - "description": "Destination id.", + "name": "namespacePath", + "description": "Full path of the namespace. Project or group namespaces only.", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "AuditEventsExternalAuditEventDestinationID", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "defaultValue": null } @@ -13762,8 +14005,8 @@ }, { "kind": "OBJECT", - "name": "AuditEventsStreamingDestinationEventsAddPayload", - "description": "Autogenerated return type of AuditEventsStreamingDestinationEventsAdd.", + "name": "AuditEventsInstanceDestinationNamespaceFilterCreatePayload", + "description": "Autogenerated return type of AuditEventsInstanceDestinationNamespaceFilterCreate.", "fields": [ { "name": "clientMutationId", @@ -13802,21 +14045,13 @@ "deprecationReason": null }, { - "name": "eventTypeFilters", - "description": "List of event type filters for the audit event external destination.", + "name": "namespaceFilter", + "description": "Namespace filter to be created.", "args": [], "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } + "kind": "OBJECT", + "name": "InstanceAuditEventNamespaceFilter", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -13829,8 +14064,8 @@ }, { "kind": "INPUT_OBJECT", - "name": "AuditEventsStreamingDestinationEventsRemoveInput", - "description": "Autogenerated input type of AuditEventsStreamingDestinationEventsRemove", + "name": "AuditEventsInstanceDestinationNamespaceFilterDeleteInput", + "description": "Autogenerated input type of AuditEventsInstanceDestinationNamespaceFilterDelete", "fields": null, "inputFields": [ { @@ -13844,36 +14079,14 @@ "defaultValue": null }, { - "name": "eventTypeFilters", - "description": "List of event type filters to remove from streaming.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - }, - "defaultValue": null - }, - { - "name": "destinationId", - "description": "Destination id.", + "name": "namespaceFilterId", + "description": "Namespace filter ID.", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "AuditEventsExternalAuditEventDestinationID", + "name": "AuditEventsInstanceNamespaceFilterID", "ofType": null } }, @@ -13886,8 +14099,8 @@ }, { "kind": "OBJECT", - "name": "AuditEventsStreamingDestinationEventsRemovePayload", - "description": "Autogenerated return type of AuditEventsStreamingDestinationEventsRemove.", + "name": "AuditEventsInstanceDestinationNamespaceFilterDeletePayload", + "description": "Autogenerated return type of AuditEventsInstanceDestinationNamespaceFilterDelete.", "fields": [ { "name": "clientMutationId", @@ -13931,10 +14144,50 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "AuditEventsInstanceExternalAuditEventDestinationID", + "description": "A `AuditEventsInstanceExternalAuditEventDestinationID` is a global ID. It is encoded as a string.\n\nAn example `AuditEventsInstanceExternalAuditEventDestinationID` is: `\"gid://gitlab/AuditEvents::InstanceExternalAuditEventDestination/1\"`.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "AuditEventsInstanceExternalStreamingDestinationID", + "description": "A `AuditEventsInstanceExternalStreamingDestinationID` is a global ID. It is encoded as a string.\n\nAn example `AuditEventsInstanceExternalStreamingDestinationID` is: `\"gid://gitlab/AuditEvents::Instance::ExternalStreamingDestination/1\"`.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "AuditEventsInstanceGoogleCloudLoggingConfigurationID", + "description": "A `AuditEventsInstanceGoogleCloudLoggingConfigurationID` is a global ID. It is encoded as a string.\n\nAn example `AuditEventsInstanceGoogleCloudLoggingConfigurationID` is: `\"gid://gitlab/AuditEvents::Instance::GoogleCloudLoggingConfiguration/1\"`.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "AuditEventsInstanceNamespaceFilterID", + "description": "A `AuditEventsInstanceNamespaceFilterID` is a global ID. It is encoded as a string.\n\nAn example `AuditEventsInstanceNamespaceFilterID` is: `\"gid://gitlab/AuditEvents::Instance::NamespaceFilter/1\"`.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", - "name": "AuditEventsStreamingDestinationInstanceEventsAddInput", - "description": "Autogenerated input type of AuditEventsStreamingDestinationInstanceEventsAdd", + "name": "AuditEventsStreamingDestinationEventsAddInput", + "description": "Autogenerated input type of AuditEventsStreamingDestinationEventsAdd", "fields": null, "inputFields": [ { @@ -13977,7 +14230,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "AuditEventsInstanceExternalAuditEventDestinationID", + "name": "AuditEventsExternalAuditEventDestinationID", "ofType": null } }, @@ -13990,8 +14243,8 @@ }, { "kind": "OBJECT", - "name": "AuditEventsStreamingDestinationInstanceEventsAddPayload", - "description": "Autogenerated return type of AuditEventsStreamingDestinationInstanceEventsAdd.", + "name": "AuditEventsStreamingDestinationEventsAddPayload", + "description": "Autogenerated return type of AuditEventsStreamingDestinationEventsAdd.", "fields": [ { "name": "clientMutationId", @@ -14057,8 +14310,8 @@ }, { "kind": "INPUT_OBJECT", - "name": "AuditEventsStreamingDestinationInstanceEventsRemoveInput", - "description": "Autogenerated input type of AuditEventsStreamingDestinationInstanceEventsRemove", + "name": "AuditEventsStreamingDestinationEventsRemoveInput", + "description": "Autogenerated input type of AuditEventsStreamingDestinationEventsRemove", "fields": null, "inputFields": [ { @@ -14101,7 +14354,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "AuditEventsInstanceExternalAuditEventDestinationID", + "name": "AuditEventsExternalAuditEventDestinationID", "ofType": null } }, @@ -14114,8 +14367,236 @@ }, { "kind": "OBJECT", - "name": "AuditEventsStreamingDestinationInstanceEventsRemovePayload", - "description": "Autogenerated return type of AuditEventsStreamingDestinationInstanceEventsRemove.", + "name": "AuditEventsStreamingDestinationEventsRemovePayload", + "description": "Autogenerated return type of AuditEventsStreamingDestinationEventsRemove.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "AuditEventsStreamingDestinationInstanceEventsAddInput", + "description": "Autogenerated input type of AuditEventsStreamingDestinationInstanceEventsAdd", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventTypeFilters", + "description": "List of event type filters to add for streaming.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "defaultValue": null + }, + { + "name": "destinationId", + "description": "Destination id.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "AuditEventsInstanceExternalAuditEventDestinationID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "AuditEventsStreamingDestinationInstanceEventsAddPayload", + "description": "Autogenerated return type of AuditEventsStreamingDestinationInstanceEventsAdd.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "eventTypeFilters", + "description": "List of event type filters for the audit event external destination.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "AuditEventsStreamingDestinationInstanceEventsRemoveInput", + "description": "Autogenerated input type of AuditEventsStreamingDestinationInstanceEventsRemove", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "eventTypeFilters", + "description": "List of event type filters to remove from streaming.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "defaultValue": null + }, + { + "name": "destinationId", + "description": "Destination id.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "AuditEventsInstanceExternalAuditEventDestinationID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "AuditEventsStreamingDestinationInstanceEventsRemovePayload", + "description": "Autogenerated return type of AuditEventsStreamingDestinationInstanceEventsRemove.", "fields": [ { "name": "clientMutationId", @@ -15404,19 +15885,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -15749,19 +16226,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -16871,19 +17344,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -17242,6 +17711,16 @@ }, "defaultValue": null }, + { + "name": "sort", + "description": "List starred projects by sort order.", + "type": { + "kind": "ENUM", + "name": "ProjectSort", + "ofType": null + }, + "defaultValue": "NAME_ASC" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -25422,6 +25901,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "description", + "description": "Description of the input.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "name", "description": "Name of the input.", @@ -25434,6 +25925,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "regex", + "description": "Pattern that the input value must match. Only applicable to string inputs.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "required", "description": "Indicates if an input is required.", @@ -25445,6 +25948,18 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "type", + "description": "Type of the input.", + "args": [], + "type": { + "kind": "ENUM", + "name": "CiCatalogResourceComponentInputType", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -25452,6 +25967,41 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "CiCatalogResourceComponentInputType", + "description": "Available input types", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ARRAY", + "description": "Array input", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "BOOLEAN", + "description": "Boolean input", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NUMBER", + "description": "Number input", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "STRING", + "description": "String input", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "CiCatalogResourceConnection", @@ -32186,15 +32736,15 @@ }, { "name": "upgradeStatus", - "description": "Availability of upgrades for the runner. Introduced in GitLab 14.10: **Status**: Experiment.", + "description": "Availability of upgrades for the runner.", "args": [], "type": { "kind": "ENUM", "name": "CiRunnerUpgradeStatus", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 14.10." + "isDeprecated": false, + "deprecationReason": null }, { "name": "userPermissions", @@ -40940,32 +41490,24 @@ }, { "name": "minimumAccessLevelForDelete", - "description": "Minimum GitLab access level to allow to push container images to the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`. Introduced in GitLab 16.6: **Status**: Experiment.", + "description": "Minimum GitLab access level to allow to delete container images from the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`. If the value is `nil`, the minimum access level for delete is ignored. Users with at least the Developer role are allowed to delete container images. Introduced in GitLab 16.6: **Status**: Experiment.", "args": [], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "ContainerRegistryProtectionRuleAccessLevel", - "ofType": null - } + "kind": "ENUM", + "name": "ContainerRegistryProtectionRuleAccessLevel", + "ofType": null }, "isDeprecated": true, "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.6." }, { "name": "minimumAccessLevelForPush", - "description": "Minimum GitLab access level to allow to push container images to the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`. Introduced in GitLab 16.6: **Status**: Experiment.", + "description": "Minimum GitLab access level to allow to push container images to the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`. If the value is `nil`, the minimum access level for push is ignored. Users with at least the Developer role are allowed to push container images. Introduced in GitLab 16.6: **Status**: Experiment.", "args": [], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "ContainerRegistryProtectionRuleAccessLevel", - "ofType": null - } + "kind": "ENUM", + "name": "ContainerRegistryProtectionRuleAccessLevel", + "ofType": null }, "isDeprecated": true, "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.6." @@ -42374,6 +42916,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "mediaType", + "description": "Media type of the tag.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "name", "description": "Name of the tag.", @@ -43980,7 +44534,7 @@ }, { "name": "repositoryPathPattern", - "description": "Container repository path pattern protected by the protection rule. For example, `my-project/my-container-*`. Wildcard character `*` allowed.", + "description": "Container repository path pattern protected by the protection rule. For example, `my-project/my-container-*`. Wildcard character `*` allowed. Introduced in GitLab 16.6: **Status**: Experiment.", "type": { "kind": "NON_NULL", "name": null, @@ -43993,30 +44547,22 @@ "defaultValue": null }, { - "name": "minimumAccessLevelForPush", - "description": "Minimum GitLab access level to allow to push container images to the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`.", + "name": "minimumAccessLevelForDelete", + "description": "Minimum GitLab access level to allow to delete container images from the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`. If the value is `nil`, the minimum access level for delete is ignored. Users with at least the Developer role are allowed to delete container images. Introduced in GitLab 16.6: **Status**: Experiment.", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "ContainerRegistryProtectionRuleAccessLevel", - "ofType": null - } + "kind": "ENUM", + "name": "ContainerRegistryProtectionRuleAccessLevel", + "ofType": null }, "defaultValue": null }, { - "name": "minimumAccessLevelForDelete", - "description": "Minimum GitLab access level to allow to delete container images in the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`.", + "name": "minimumAccessLevelForPush", + "description": "Minimum GitLab access level to allow to push container images to the container registry. For example, `MAINTAINER`, `OWNER`, or `ADMIN`. If the value is `nil`, the minimum access level for push is ignored. Users with at least the Developer role are allowed to push container images. Introduced in GitLab 16.6: **Status**: Experiment.", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "ContainerRegistryProtectionRuleAccessLevel", - "ofType": null - } + "kind": "ENUM", + "name": "ContainerRegistryProtectionRuleAccessLevel", + "ofType": null }, "defaultValue": null } @@ -46385,19 +46931,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -46730,19 +47272,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -47857,19 +48395,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -48228,166 +48762,176 @@ }, "defaultValue": null }, - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "ProjectConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "state", - "description": "State of the user.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "UserState", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "status", - "description": "User status.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "UserStatus", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timelogs", - "description": "Time logged by the user.", - "args": [ - { - "name": "startDate", - "description": "List timelogs within a date range where the logged date is equal to or after startDate.", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "endDate", - "description": "List timelogs within a date range where the logged date is equal to or before endDate.", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "startTime", - "description": "List timelogs within a time range where the logged time is equal to or after startTime.", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "endTime", - "description": "List timelogs within a time range where the logged time is equal to or before endTime.", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "projectId", - "description": "List timelogs for a project.", - "type": { - "kind": "SCALAR", - "name": "ProjectID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "groupId", - "description": "List timelogs for a group.", - "type": { - "kind": "SCALAR", - "name": "GroupID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "username", - "description": "List timelogs for a user.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, { "name": "sort", - "description": "List timelogs in a particular order.", + "description": "List starred projects by sort order.", "type": { "kind": "ENUM", - "name": "TimelogSort", + "name": "ProjectSort", "ofType": null }, - "defaultValue": "SPENT_AT_ASC" + "defaultValue": "NAME_ASC" + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ProjectConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "state", + "description": "State of the user.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "UserState", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "status", + "description": "User status.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "UserStatus", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timelogs", + "description": "Time logged by the user.", + "args": [ + { + "name": "startDate", + "description": "List timelogs within a date range where the logged date is equal to or after startDate.", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endDate", + "description": "List timelogs within a date range where the logged date is equal to or before endDate.", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startTime", + "description": "List timelogs within a time range where the logged time is equal to or after startTime.", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endTime", + "description": "List timelogs within a time range where the logged time is equal to or before endTime.", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "projectId", + "description": "List timelogs for a project.", + "type": { + "kind": "SCALAR", + "name": "ProjectID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "groupId", + "description": "List timelogs for a group.", + "type": { + "kind": "SCALAR", + "name": "GroupID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "username", + "description": "List timelogs for a user.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sort", + "description": "List timelogs in a particular order.", + "type": { + "kind": "ENUM", + "name": "TimelogSort", + "ofType": null + }, + "defaultValue": "SPENT_AT_ASC" }, { "name": "after", @@ -83316,6 +83860,59 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "importSourceUsers", + "description": "Import source users of the namespace. This field can only be resolved for one namespace in any single request. Introduced in GitLab 17.2: **Status**: Experiment.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ImportSourceUserConnection", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, { "name": "isAdjournedDeletionEnabled", "description": "Indicates if delayed group deletion is enabled. Introduced in GitLab 16.11: **Status**: Experiment.", @@ -84644,19 +85241,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -91953,12 +92546,835 @@ "deprecationReason": null }, { - "name": "integration", - "description": "HTTP integration.", + "name": "integration", + "description": "HTTP integration.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "AlertManagementHttpIntegration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "HttpIntegrationResetTokenInput", + "description": "Autogenerated input type of HttpIntegrationResetToken", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": "ID of the integration to mutate.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "AlertManagementHttpIntegrationID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "HttpIntegrationResetTokenPayload", + "description": "Autogenerated return type of HttpIntegrationResetToken.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "integration", + "description": "HTTP integration.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "AlertManagementHttpIntegration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "HttpIntegrationUpdateInput", + "description": "Autogenerated input type of HttpIntegrationUpdate", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": "ID of the integration to mutate.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "AlertManagementHttpIntegrationID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "name", + "description": "Name of the integration.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "active", + "description": "Whether the integration is receiving alerts.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "payloadExample", + "description": "Example of an alert payload.", + "type": { + "kind": "SCALAR", + "name": "JsonString", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "payloadAttributeMappings", + "description": "Custom mapping of GitLab alert attributes to fields from the payload example.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AlertManagementPayloadAlertFieldInput", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "HttpIntegrationUpdatePayload", + "description": "Autogenerated return type of HttpIntegrationUpdate.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "integration", + "description": "HTTP integration.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "AlertManagementHttpIntegration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "ID", + "description": "Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"VXNlci0xMA==\"`) or integer (such as `4`) input value will be accepted as an ID.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "ISO8601Date", + "description": "An ISO 8601-encoded date", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "ISO8601DateTime", + "description": "An ISO 8601-encoded datetime", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Ide", + "description": "IDE settings and feature flags.", + "fields": [ + { + "name": "codeSuggestionsEnabled", + "description": "Indicates whether AI assisted code suggestions are enabled.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "ImportSource", + "description": "Import source", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "NONE", + "description": "Not imported", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GITLAB_MIGRATION", + "description": "Gitlab Migration", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GITLAB_PROJECT", + "description": "Gitlab Project", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GITLAB_GROUP", + "description": "Gitlab Group", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GITHUB", + "description": "Github", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "BITBUCKET", + "description": "Bitbucket", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "BITBUCKET_SERVER", + "description": "Bitbucket Server", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FOGBUGZ", + "description": "Fogbugz", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GITEA", + "description": "Gitea", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GIT", + "description": "Git", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "MANIFEST", + "description": "Manifest", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CUSTOM_TEMPLATE", + "description": "Custom Template", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ImportSourceUser", + "description": null, + "fields": [ + { + "name": "id", + "description": "Global ID of the mapping of a user on source instance to a user on destination instance.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ImportSourceUserID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "importType", + "description": "Name of the importer.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "ImportSource", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "placeholderUser", + "description": "Placeholder user associated with the import source user.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "UserCore", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "reassignToUser", + "description": "User that contributions are reassigned to.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "UserCore", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "reassignedByUser", + "description": "User that did the reassignment.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "UserCore", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceHostname", + "description": "Source instance hostname.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceName", + "description": "Name of user in the source instance.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceUserIdentifier", + "description": "ID of the user in the source instance.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sourceUsername", + "description": "Username of user in the source instance.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "status", + "description": "Status of the mapping.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "ImportSourceUserStatus", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "ImportSourceUserCancelReassignmentInput", + "description": "Autogenerated input type of ImportSourceUserCancelReassignment", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": "Global ID of the mapping of a user on source instance to a user on destination instance.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ImportSourceUserID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ImportSourceUserCancelReassignmentPayload", + "description": "Autogenerated return type of ImportSourceUserCancelReassignment.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "importSourceUser", + "description": "Mapping of a user on source instance to a user on destination instance after mutation.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ImportSourceUser", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ImportSourceUserConnection", + "description": "The connection type for ImportSourceUser.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ImportSourceUserEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ImportSourceUser", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ImportSourceUserEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ImportSourceUser", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "ImportSourceUserID", + "description": "A `ImportSourceUserID` is a global ID. It is encoded as a string.\n\nAn example `ImportSourceUserID` is: `\"gid://gitlab/Import::SourceUser/1\"`.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "ImportSourceUserKeepAsPlaceholderInput", + "description": "Autogenerated input type of ImportSourceUserKeepAsPlaceholder", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": "Global ID of the mapping of a user on source instance to a user on destination instance.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ImportSourceUserID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ImportSourceUserKeepAsPlaceholderPayload", + "description": "Autogenerated return type of ImportSourceUserKeepAsPlaceholder.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "importSourceUser", + "description": "Mapping of a user on source instance to a user on destination instance after mutation.", "args": [], "type": { "kind": "OBJECT", - "name": "AlertManagementHttpIntegration", + "name": "ImportSourceUser", "ofType": null }, "isDeprecated": false, @@ -91972,8 +93388,8 @@ }, { "kind": "INPUT_OBJECT", - "name": "HttpIntegrationResetTokenInput", - "description": "Autogenerated input type of HttpIntegrationResetToken", + "name": "ImportSourceUserReassignInput", + "description": "Autogenerated input type of ImportSourceUserReassign", "fields": null, "inputFields": [ { @@ -91988,159 +93404,31 @@ }, { "name": "id", - "description": "ID of the integration to mutate.", + "description": "Global ID of the mapping of a user on source instance to a user on destination instance.", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "AlertManagementHttpIntegrationID", + "name": "ImportSourceUserID", "ofType": null } }, "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HttpIntegrationResetTokenPayload", - "description": "Autogenerated return type of HttpIntegrationResetToken.", - "fields": [ - { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "integration", - "description": "HTTP integration.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "AlertManagementHttpIntegration", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "HttpIntegrationUpdateInput", - "description": "Autogenerated input type of HttpIntegrationUpdate", - "fields": null, - "inputFields": [ - { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null }, { - "name": "id", - "description": "ID of the integration to mutate.", + "name": "assigneeUserId", + "description": "Global ID of the assignee user.", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "AlertManagementHttpIntegrationID", + "name": "UserID", "ofType": null } }, "defaultValue": null - }, - { - "name": "name", - "description": "Name of the integration.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "active", - "description": "Whether the integration is receiving alerts.", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "payloadExample", - "description": "Example of an alert payload.", - "type": { - "kind": "SCALAR", - "name": "JsonString", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "payloadAttributeMappings", - "description": "Custom mapping of GitLab alert attributes to fields from the payload example.", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "AlertManagementPayloadAlertFieldInput", - "ofType": null - } - } - }, - "defaultValue": null } ], "interfaces": null, @@ -92149,8 +93437,8 @@ }, { "kind": "OBJECT", - "name": "HttpIntegrationUpdatePayload", - "description": "Autogenerated return type of HttpIntegrationUpdate.", + "name": "ImportSourceUserReassignPayload", + "description": "Autogenerated return type of ImportSourceUserReassign.", "fields": [ { "name": "clientMutationId", @@ -92189,12 +93477,12 @@ "deprecationReason": null }, { - "name": "integration", - "description": "HTTP integration.", + "name": "importSourceUser", + "description": "Mapping of a user on source instance to a user on destination instance after mutation.", "args": [], "type": { "kind": "OBJECT", - "name": "AlertManagementHttpIntegration", + "name": "ImportSourceUser", "ofType": null }, "isDeprecated": false, @@ -92206,140 +93494,53 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "SCALAR", - "name": "ID", - "description": "Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"VXNlci0xMA==\"`) or integer (such as `4`) input value will be accepted as an ID.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ISO8601Date", - "description": "An ISO 8601-encoded date", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ISO8601DateTime", - "description": "An ISO 8601-encoded datetime", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Ide", - "description": "IDE settings and feature flags.", - "fields": [ - { - "name": "codeSuggestionsEnabled", - "description": "Indicates whether AI assisted code suggestions are enabled.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, { "kind": "ENUM", - "name": "ImportSource", - "description": "Import source", + "name": "ImportSourceUserStatus", + "description": null, "fields": null, "inputFields": null, "interfaces": null, "enumValues": [ { - "name": "NONE", - "description": "Not imported", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "GITLAB_MIGRATION", - "description": "Imported from Gitlab Migration.", + "name": "PENDING_ASSIGNMENT", + "description": "An import source user mapping that is pending assignment.", "isDeprecated": false, "deprecationReason": null }, { - "name": "GITLAB_PROJECT", - "description": "Imported from Gitlab Project.", + "name": "AWAITING_APPROVAL", + "description": "An import source user mapping that is awaiting approval.", "isDeprecated": false, "deprecationReason": null }, { - "name": "GITLAB_GROUP", - "description": "Imported from Gitlab Group.", + "name": "REASSIGNMENT_IN_PROGRESS", + "description": "An import source user mapping that is reassignment in progress.", "isDeprecated": false, "deprecationReason": null }, { - "name": "GITHUB", - "description": "Imported from Github.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "BITBUCKET", - "description": "Imported from Bitbucket.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "BITBUCKET_SERVER", - "description": "Imported from Bitbucket Server.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FOGBUGZ", - "description": "Imported from Fogbugz.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "GITEA", - "description": "Imported from Gitea.", + "name": "REJECTED", + "description": "An import source user mapping that is rejected.", "isDeprecated": false, "deprecationReason": null }, { - "name": "GIT", - "description": "Imported from Git.", + "name": "FAILED", + "description": "An import source user mapping that is failed.", "isDeprecated": false, "deprecationReason": null }, { - "name": "MANIFEST", - "description": "Imported from Manifest.", + "name": "COMPLETED", + "description": "An import source user mapping that is completed.", "isDeprecated": false, "deprecationReason": null }, { - "name": "CUSTOM_TEMPLATE", - "description": "Imported from Custom Template.", + "name": "KEEP_AS_PLACEHOLDER", + "description": "An import source user mapping that is keep as placeholder.", "isDeprecated": false, "deprecationReason": null } @@ -93597,6 +94798,65 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "InstanceAuditEventNamespaceFilter", + "description": "Represents a subgroup or project filter that belongs to an instance level external audit event streaming destination.", + "fields": [ + { + "name": "externalStreamingDestination", + "description": "Destination to which the filter belongs.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "InstanceAuditEventStreamingDestination", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the filter.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "namespace", + "description": "Group or project namespace the filter belongs to.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Namespace", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "InstanceAuditEventStreamingDestination", @@ -93689,6 +94949,26 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "namespaceFilters", + "description": "List of subgroup or project filters for the destination.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "InstanceAuditEventNamespaceFilter", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -95778,6 +97058,18 @@ "name": "IntegrationExclusion", "description": "An integration to override the level settings of instance specific integrations.", "fields": [ + { + "name": "group", + "description": "Group that has been excluded from the instance specific integration.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Group", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "project", "description": "Project that has been excluded from the instance specific integration.", @@ -95889,19 +97181,33 @@ "name": "projectIds", "description": "IDs of projects to exclude up to a maximum of 100.", "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ProjectID", - "ofType": null - } + "kind": "SCALAR", + "name": "ProjectID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "groupIds", + "description": "IDs of groups to exclude up to a maximum of 100.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "GroupID", + "ofType": null } } }, @@ -96013,19 +97319,33 @@ "name": "projectIds", "description": "IDs of excluded projects.", "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ProjectID", - "ofType": null - } + "kind": "SCALAR", + "name": "ProjectID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "groupIds", + "description": "IDs of excluded groups.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "GroupID", + "ofType": null } } }, @@ -106830,6 +108150,35 @@ ], "possibleTypes": null }, + { + "kind": "ENUM", + "name": "MemberApprovalStatusType", + "description": "Types of member approval status.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "APPROVED", + "description": "Approved promotion request.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "DENIED", + "description": "Denied promotion request.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PENDING", + "description": "Pending promotion request.", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "INTERFACE", "name": "MemberInterface", @@ -107696,6 +109045,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "READ_RUNNERS", + "description": "Allows read-only access to group or project runners, including the runner fleet dashboard.", + "isDeprecated": false, + "deprecationReason": null + }, { "name": "READ_VULNERABILITY", "description": "Read vulnerability reports and security dashboards.", @@ -109899,6 +111254,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "retargeted", + "description": "Indicates if merge request was retargeted.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "reviewers", "description": "Users from whom a review has been requested.", @@ -110943,19 +112310,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -111288,19 +112651,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -112395,19 +113754,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -112766,6 +114121,16 @@ }, "defaultValue": null }, + { + "name": "sort", + "description": "List starred projects by sort order.", + "type": { + "kind": "ENUM", + "name": "ProjectSort", + "ofType": null + }, + "defaultValue": "NAME_ASC" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -113691,19 +115056,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -114036,19 +115397,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -115143,19 +116500,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -115514,6 +116867,16 @@ }, "defaultValue": null }, + { + "name": "sort", + "description": "List starred projects by sort order.", + "type": { + "kind": "ENUM", + "name": "ProjectSort", + "ofType": null + }, + "defaultValue": "NAME_ASC" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -116433,59 +117796,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "reviewLlmSummaries", - "description": "Review summaries generated by AI.", - "args": [ - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "MergeRequestReviewLlmSummaryConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "updatedAt", "description": "Timestamp of when the diff was updated.", @@ -117182,19 +118492,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -117527,19 +118833,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -118634,19 +119936,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -119005,6 +120303,16 @@ }, "defaultValue": null }, + { + "name": "sort", + "description": "List starred projects by sort order.", + "type": { + "kind": "ENUM", + "name": "ProjectSort", + "ofType": null + }, + "defaultValue": "NAME_ASC" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -119937,235 +121245,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "MergeRequestReviewLlmSummary", - "description": "A review summary generated by AI.", - "fields": [ - { - "name": "content", - "description": "Content of the review summary.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "contentHtml", - "description": "HTML content of the review summary, converted from Markdown.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "Timestamp of when the review summary was created.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mergeRequestDiffId", - "description": "ID of the Merge Request diff associated with the review summary.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "provider", - "description": "AI provider that generated the summary.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "reviewer", - "description": "User who authored the review associated with the review summary.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "UserCore", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updatedAt", - "description": "Timestamp of when the review summary was updated.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "user", - "description": "User associated with the review summary.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "UserCore", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "MergeRequestReviewLlmSummaryConnection", - "description": "The connection type for MergeRequestReviewLlmSummary.", - "fields": [ - { - "name": "edges", - "description": "A list of edges.", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MergeRequestReviewLlmSummaryEdge", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "nodes", - "description": "A list of nodes.", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MergeRequestReviewLlmSummary", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "Information to aid in pagination.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "PageInfo", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "MergeRequestReviewLlmSummaryEdge", - "description": "An edge in a connection.", - "fields": [ - { - "name": "cursor", - "description": "A cursor for use in pagination.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "node", - "description": "The item at the end of the edge.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "MergeRequestReviewLlmSummary", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, { "kind": "ENUM", "name": "MergeRequestReviewState", @@ -120371,19 +121450,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -120716,19 +121791,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -121823,19 +122894,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -122194,6 +123261,16 @@ }, "defaultValue": null }, + { + "name": "sort", + "description": "List starred projects by sort order.", + "type": { + "kind": "ENUM", + "name": "ProjectSort", + "ofType": null + }, + "defaultValue": "NAME_ASC" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -124661,6 +125738,20 @@ "name": "cars", "description": "Cars queued in the train. Introduced in GitLab 17.1: **Status**: Experiment.", "args": [ + { + "name": "activityStatus", + "description": "Filter by the high-level status of the cars. Defaults to ACTIVE.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "MergeTrainStatus", + "ofType": null + } + }, + "defaultValue": "ACTIVE" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -124700,20 +125791,6 @@ "ofType": null }, "defaultValue": null - }, - { - "name": "activityStatus", - "description": "Filter cars by their high-level status. Defaults to ACTIVE.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "MergeTrainStatus", - "ofType": null - } - }, - "defaultValue": "ACTIVE" } ], "type": { @@ -128946,6 +130023,60 @@ "isDeprecated": true, "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.10." }, + { + "name": "aiSelfHostedModelCreate", + "description": null, + "args": [ + { + "name": "input", + "description": "Parameters for AiSelfHostedModelCreate", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AiSelfHostedModelCreateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "AiSelfHostedModelCreatePayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.1." + }, + { + "name": "aiSelfHostedModelUpdate", + "description": "Updates a self-hosted model. Introduced in GitLab 17.2: **Status**: Experiment.", + "args": [ + { + "name": "input", + "description": "Parameters for AiSelfHostedModelUpdate", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AiSelfHostedModelUpdateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "AiSelfHostedModelUpdatePayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, { "name": "alertSetAssignees", "description": null, @@ -129432,6 +130563,60 @@ "isDeprecated": true, "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.0." }, + { + "name": "auditEventsInstanceDestinationNamespaceFilterCreate", + "description": null, + "args": [ + { + "name": "input", + "description": "Parameters for AuditEventsInstanceDestinationNamespaceFilterCreate", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AuditEventsInstanceDestinationNamespaceFilterCreateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "AuditEventsInstanceDestinationNamespaceFilterCreatePayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, + { + "name": "auditEventsInstanceDestinationNamespaceFilterDelete", + "description": null, + "args": [ + { + "name": "input", + "description": "Parameters for AuditEventsInstanceDestinationNamespaceFilterDelete", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AuditEventsInstanceDestinationNamespaceFilterDeleteInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "AuditEventsInstanceDestinationNamespaceFilterDeletePayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, { "name": "auditEventsStreamingDestinationEventsAdd", "description": null, @@ -133374,6 +134559,87 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "importSourceUserCancelReassignment", + "description": null, + "args": [ + { + "name": "input", + "description": "Parameters for ImportSourceUserCancelReassignment", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ImportSourceUserCancelReassignmentInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ImportSourceUserCancelReassignmentPayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, + { + "name": "importSourceUserKeepAsPlaceholder", + "description": null, + "args": [ + { + "name": "input", + "description": "Parameters for ImportSourceUserKeepAsPlaceholder", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ImportSourceUserKeepAsPlaceholderInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ImportSourceUserKeepAsPlaceholderPayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, + { + "name": "importSourceUserReassign", + "description": null, + "args": [ + { + "name": "input", + "description": "Parameters for ImportSourceUserReassign", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ImportSourceUserReassignInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ImportSourceUserReassignPayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, { "name": "instanceAuditEventStreamingDestinationsCreate", "description": null, @@ -135750,6 +137016,33 @@ "isDeprecated": true, "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.3." }, + { + "name": "processUserBillablePromotionRequest", + "description": null, + "args": [ + { + "name": "input", + "description": "Parameters for ProcessUserBillablePromotionRequest", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ProcessUserBillablePromotionRequestInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ProcessUserBillablePromotionRequestPayload", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, { "name": "productAnalyticsProjectSettingsUpdate", "description": null, @@ -135968,7 +137261,7 @@ }, { "name": "projectSetComplianceFramework", - "description": "Assign (or unset) a compliance framework to a project.", + "description": "Assign (or unset) a compliance framework to a project. This mutation raises an error if the project has more than one compliance framework associated with it.", "args": [ { "name": "input", @@ -136692,8 +137985,8 @@ "name": "RunnersExportUsagePayload", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.7." + "isDeprecated": false, + "deprecationReason": null }, { "name": "runnersRegistrationTokenReset", @@ -139588,6 +140881,59 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "importSourceUsers", + "description": "Import source users of the namespace. This field can only be resolved for one namespace in any single request. Introduced in GitLab 17.2: **Status**: Experiment.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ImportSourceUserConnection", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, { "name": "lfsEnabled", "description": "Indicates if Large File Storage (LFS) is enabled for namespace.", @@ -145238,6 +146584,100 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "OrganizationGroupProjectDisplay", + "description": "Default list view for organization groups and projects.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "PROJECTS", + "description": "Display organization projects list. Introduced in GitLab 17.2: **Status**: Experiment.", + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, + { + "name": "GROUPS", + "description": "Display organization groups list. Introduced in GitLab 17.2: **Status**: Experiment.", + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + } + ], + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "OrganizationGroupProjectSort", + "description": "Values for sorting organization groups and projects.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "NAME_DESC", + "description": "Name descending order. Introduced in GitLab 17.2: **Status**: Experiment.", + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, + { + "name": "NAME_ASC", + "description": "Name ascending order. Introduced in GitLab 17.2: **Status**: Experiment.", + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, + { + "name": "updated_desc", + "description": "Updated at descending order. Deprecated in GitLab 13.5: This was renamed.", + "isDeprecated": true, + "deprecationReason": "This was renamed. Please use `UPDATED_DESC`. Deprecated in GitLab 13.5." + }, + { + "name": "updated_asc", + "description": "Updated at ascending order. Deprecated in GitLab 13.5: This was renamed.", + "isDeprecated": true, + "deprecationReason": "This was renamed. Please use `UPDATED_ASC`. Deprecated in GitLab 13.5." + }, + { + "name": "created_desc", + "description": "Created at descending order. Deprecated in GitLab 13.5: This was renamed.", + "isDeprecated": true, + "deprecationReason": "This was renamed. Please use `CREATED_DESC`. Deprecated in GitLab 13.5." + }, + { + "name": "created_asc", + "description": "Created at ascending order. Deprecated in GitLab 13.5: This was renamed.", + "isDeprecated": true, + "deprecationReason": "This was renamed. Please use `CREATED_ASC`. Deprecated in GitLab 13.5." + }, + { + "name": "UPDATED_DESC", + "description": "Updated at descending order.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "UPDATED_ASC", + "description": "Updated at ascending order.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CREATED_DESC", + "description": "Created at descending order.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CREATED_ASC", + "description": "Created at ascending order.", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "ENUM", "name": "OrganizationSort", @@ -145958,22 +147398,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "packageProtectionRuleExists", - "description": "Whether any matching package protection rule exists for this package. Available only when feature flag `packages_protected_packages` is enabled. Deprecated in GitLab 17.0: Use `protectionRuleExists`.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `protectionRuleExists`. Deprecated in GitLab 17.0." - }, { "name": "packageType", "description": "Package type.", @@ -146287,22 +147711,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "packageProtectionRuleExists", - "description": "Whether any matching package protection rule exists for this package. Available only when feature flag `packages_protected_packages` is enabled. Deprecated in GitLab 17.0: Use `protectionRuleExists`.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `protectionRuleExists`. Deprecated in GitLab 17.0." - }, { "name": "packageType", "description": "Package type.", @@ -147260,22 +148668,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "packageProtectionRuleExists", - "description": "Whether any matching package protection rule exists for this package. Available only when feature flag `packages_protected_packages` is enabled. Deprecated in GitLab 17.0: Use `protectionRuleExists`.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `protectionRuleExists`. Deprecated in GitLab 17.0." - }, { "name": "packageType", "description": "Package type.", @@ -151860,6 +153252,59 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "manualVariables", + "description": "CI/CD variables added to a manual pipeline.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CiManualVariableConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "mergeRequest", "description": "The MR which the Pipeline is attached to", @@ -157553,6 +158998,114 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "ProcessUserBillablePromotionRequestInput", + "description": "Autogenerated input type of ProcessUserBillablePromotionRequest", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "userId", + "description": "Global ID of user to be promoted.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "UserID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "status", + "description": "Status for the member approval request (approved, denied, pending).", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "MemberApprovalStatusType", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProcessUserBillablePromotionRequestPayload", + "description": "Autogenerated return type of ProcessUserBillablePromotionRequest.", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "result", + "description": "Status of the user promotion process (success, partial_success, failed).", + "args": [], + "type": { + "kind": "ENUM", + "name": "UserPromotionStatusType", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "ProductAnalyticsProjectSettings", @@ -163522,19 +165075,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -163756,13 +165305,13 @@ "args": [ { "name": "status", - "description": "Filter merge trains by a specific status. Defaults to ACTIVE.", + "description": "Filter merge trains by a specific status.", "type": { "kind": "ENUM", "name": "MergeTrainStatus", "ofType": null }, - "defaultValue": "ACTIVE" + "defaultValue": null }, { "name": "targetBranches", @@ -168522,6 +170071,18 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "pushRepositoryForJobTokenAllowed", + "description": "Indicates the ability to push to the original project repository using a job token", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -168579,6 +170140,16 @@ }, "defaultValue": null }, + { + "name": "pushRepositoryForJobTokenAllowed", + "description": "Indicates the ability to push to the original project repository using a job token", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, { "name": "mergePipelinesEnabled", "description": "Indicates if merged results pipelines are enabled for the project.", @@ -175352,7 +176923,7 @@ }, { "name": "aiSelfHostedModels", - "description": "List of Self-Hosted LLM servers. Introduced in GitLab 17.1: **Status**: Experiment.", + "description": "List of self-hosted LLM servers. Introduced in GitLab 17.1: **Status**: Experiment.", "args": [ { "name": "after", @@ -178162,7 +179733,7 @@ }, { "name": "runnerUsage", - "description": "Runner usage by runner. Introduced in GitLab 16.9: **Status**: Experiment.", + "description": "Runner usage by runner.", "args": [ { "name": "runnerType", @@ -178228,12 +179799,12 @@ } } }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.9." + "isDeprecated": false, + "deprecationReason": null }, { "name": "runnerUsageByProject", - "description": "Runner usage by project. Introduced in GitLab 16.9: **Status**: Experiment.", + "description": "Runner usage by project.", "args": [ { "name": "runnerType", @@ -178299,8 +179870,8 @@ } } }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.9." + "isDeprecated": false, + "deprecationReason": null }, { "name": "runners", @@ -180030,63 +181601,63 @@ "fields": [ { "name": "p50", - "description": "50th percentile. 50% of the durations are lower than this value. Introduced in GitLab 16.4: **Status**: Experiment.", + "description": "50th percentile. 50% of the durations are lower than this value.", "args": [], "type": { "kind": "SCALAR", "name": "Duration", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.4." + "isDeprecated": false, + "deprecationReason": null }, { "name": "p75", - "description": "75th percentile. 75% of the durations are lower than this value. Introduced in GitLab 16.4: **Status**: Experiment.", + "description": "75th percentile. 75% of the durations are lower than this value.", "args": [], "type": { "kind": "SCALAR", "name": "Duration", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.4." + "isDeprecated": false, + "deprecationReason": null }, { "name": "p90", - "description": "90th percentile. 90% of the durations are lower than this value. Introduced in GitLab 16.4: **Status**: Experiment.", + "description": "90th percentile. 90% of the durations are lower than this value.", "args": [], "type": { "kind": "SCALAR", "name": "Duration", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.4." + "isDeprecated": false, + "deprecationReason": null }, { "name": "p95", - "description": "95th percentile. 95% of the durations are lower than this value. Introduced in GitLab 16.4: **Status**: Experiment.", + "description": "95th percentile. 95% of the durations are lower than this value.", "args": [], "type": { "kind": "SCALAR", "name": "Duration", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.4." + "isDeprecated": false, + "deprecationReason": null }, { "name": "p99", - "description": "99th percentile. 99% of the durations are lower than this value. Introduced in GitLab 16.4: **Status**: Experiment.", + "description": "99th percentile. 99% of the durations are lower than this value.", "args": [], "type": { "kind": "SCALAR", "name": "Duration", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "**Status**: Experiment. Introduced in GitLab 16.4." + "isDeprecated": false, + "deprecationReason": null }, { "name": "time", @@ -206027,19 +207598,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -206372,19 +207939,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -207467,19 +209030,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -207647,29 +209206,190 @@ ], "type": { "kind": "OBJECT", - "name": "MergeRequestConnection", + "name": "MergeRequestConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "savedReplies", + "description": "Saved replies authored by the user.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SavedReplyConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "savedReply", + "description": "Saved reply authored by the user.", + "args": [ + { + "name": "id", + "description": "ID of a saved reply.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "UsersSavedReplyID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SavedReply", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "snippets", + "description": "Snippets authored by the user.", + "args": [ + { + "name": "ids", + "description": "Array of global snippet IDs. For example, `gid://gitlab/ProjectSnippet/1`.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "SnippetID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "visibility", + "description": "Visibility of the snippet.", + "type": { + "kind": "ENUM", + "name": "VisibilityScopesEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": "Type of snippet.", + "type": { + "kind": "ENUM", + "name": "TypeEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SnippetConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "savedReplies", - "description": "Saved replies authored by the user.", + "name": "starredProjects", + "description": "Projects starred by the user.", "args": [ { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", + "name": "search", + "description": "Search query.", "type": { "kind": "SCALAR", "name": "String", @@ -207678,165 +209398,14 @@ "defaultValue": null }, { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "SavedReplyConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "savedReply", - "description": "Saved reply authored by the user.", - "args": [ - { - "name": "id", - "description": "ID of a saved reply.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "UsersSavedReplyID", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "SavedReply", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "snippets", - "description": "Snippets authored by the user.", - "args": [ - { - "name": "ids", - "description": "Array of global snippet IDs. For example, `gid://gitlab/ProjectSnippet/1`.", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "SnippetID", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "visibility", - "description": "Visibility of the snippet.", - "type": { - "kind": "ENUM", - "name": "VisibilityScopesEnum", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "type", - "description": "Type of snippet.", + "name": "sort", + "description": "List starred projects by sort order.", "type": { "kind": "ENUM", - "name": "TypeEnum", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "SnippetConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "starredProjects", - "description": "Projects starred by the user.", - "args": [ - { - "name": "search", - "description": "Search query.", - "type": { - "kind": "SCALAR", - "name": "String", + "name": "ProjectSort", "ofType": null }, - "defaultValue": null + "defaultValue": "NAME_ASC" }, { "name": "after", @@ -210347,19 +211916,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -210692,19 +212257,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -211787,19 +213348,15 @@ "defaultValue": null }, { - "name": "labels", - "description": "Array of label names. All resolved merge requests will have all of these labels.", + "name": "labelName", + "description": "Labels applied to the merge request.", "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -212158,6 +213715,16 @@ }, "defaultValue": null }, + { + "name": "sort", + "description": "List starred projects by sort order.", + "type": { + "kind": "ENUM", + "name": "ProjectSort", + "ofType": null + }, + "defaultValue": "NAME_ASC" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -213096,6 +214663,34 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "organizationGroupsProjectsDisplay", + "description": "Default list view for organization groups and projects. Introduced in GitLab 17.2: **Status**: Experiment.", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "OrganizationGroupProjectDisplay", + "ofType": null + } + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, + { + "name": "organizationGroupsProjectsSort", + "description": "Sort order for organization groups and projects. Introduced in GitLab 17.2: **Status**: Experiment.", + "args": [], + "type": { + "kind": "ENUM", + "name": "OrganizationGroupProjectSort", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "**Status**: Experiment. Introduced in GitLab 17.2." + }, { "name": "useWebIdeExtensionMarketplace", "description": "Whether Web IDE Extension Marketplace is enabled for the user. Deprecated in GitLab 16.11: Use `extensions_marketplace_opt_in_status` instead.", @@ -213250,6 +214845,35 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "UserPromotionStatusType", + "description": "Types of User Promotion States.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "SUCCESS", + "description": "Successfully applied all promotion requests for user.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PARTIAL_SUCCESS", + "description": "User promotion was successful, but all promotion requests were not successfully applied.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FAILED", + "description": "Failed to apply promotion requests for user.", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "UserSetNamespaceCommitEmailInput", diff --git a/src/actions.ml b/src/actions.ml index 1ccb038b..4a2bd919 100644 --- a/src/actions.ml +++ b/src/actions.ml @@ -1963,11 +1963,11 @@ let coq_bug_minimizer_results_action ~bot_info ~ci ~key ~app_id body = let stamp = Str.matched_group 1 body in let message = Str.matched_group 2 body in match Str.split (Str.regexp " ") stamp with - | [id; author; repo_name; branch_name; owner; repo; _ (*pr_number*)] - | [id; author; repo_name; branch_name; owner; repo] -> + | [id; author; repo_name; branch_name; owner; _repo; _ (*pr_number*)] + | [id; author; repo_name; branch_name; owner; _repo] -> (fun () -> Github_installations.action_as_github_app ~bot_info ~key ~app_id - ~owner ~repo + ~owner (GitHub_mutations.post_comment ~id:(GitHub_ID.of_string id) ~message:(if ci then message else f "@%s, %s" author message) ) >>= GitHub_mutations.report_on_posting_comment @@ -2015,7 +2015,7 @@ let coq_bug_minimizer_resume_ci_minimization_action ~bot_info ~key ~app_id body init_git_bare_repository ~bot_info >>= fun () -> Github_installations.action_as_github_app ~bot_info ~key ~app_id - ~owner ~repo + ~owner (run_ci_minimization ~comment_thread_id:(GitHub_ID.of_string comment_thread_id) ~owner ~repo ~base ~pr_number ~head @@ -2596,54 +2596,123 @@ let rec adjust_milestone ~bot_info ~issue ~sleep_time = | Error err -> Lwt_io.print (f "Error: %s\n" err) -let project_action ~bot_info ~(issue : issue) ~column_id = - GitHub_queries.get_pull_request_id_and_milestone ~bot_info ~owner:"coq" - ~repo:"coq" ~number:issue.number +let project_action ~bot_info ~pr_id ~backport_to () = + GitHub_queries.get_pull_request_milestone ~bot_info ~pr_id >>= function | Error err -> Lwt_io.printf "Error: %s\n" err - | Ok None -> - Lwt_io.printf "Could not find backporting info for PR.\n" - | Ok (Some (id, _, {backport_info; rejected_milestone})) - when List.exists backport_info ~f:(fun {request_inclusion_column} -> - Int.equal request_inclusion_column column_id ) -> + | Ok backport_info -> ( + match + List.find_map backport_info + ~f:(fun {backport_to= backport_to'; rejected_milestone} -> + if String.equal backport_to backport_to' then Some rejected_milestone + else None ) + with + | None -> + Lwt_io.printf + "PR already not in milestone with backporting info for branch %s.\n" + backport_to + | Some rejected_milestone -> ( + Lwt_io.printf + "PR is in milestone for which backporting to %s was rejected.\n\ + Change of milestone requested.\n" + backport_to + >>= fun () -> + GitHub_queries.get_milestone_id ~bot_info ~owner:"coq" ~repo:"coq" + ~number:rejected_milestone + >>= function + | Ok milestone -> + GitHub_mutations.update_milestone ~bot_info ~issue:pr_id ~milestone + <&> ( GitHub_mutations.post_comment ~bot_info ~id:pr_id + ~message: + "This PR was postponed. Please update accordingly the \ + milestone of any issue that this fixes as this cannot \ + be done automatically." + >>= GitHub_mutations.report_on_posting_comment ) + | Error err -> + Lwt_io.printlf "Error while obtaining milestone ID: %s" err ) ) + +let add_to_column ~bot_info ~backport_to id option = + let field = backport_to ^ " status" in + GitHub_queries.get_project_field_values ~bot_info ~organization:"coq" + ~project:11 ~field ~options:[|option|] + >>= fun project_info -> + ( match project_info with + | Ok (project_id, Some (field_id, [(option', field_value_id)])) + when String.equal option option' -> + Lwt.return_ok (project_id, field_id, field_value_id) + | Ok (_, Some (_, [])) -> + Lwt.return_error + (f "Error: Could not find '%s' option in the field." option) + | Ok (_, Some _) -> + Lwt.return_error + (f "Error: Unexpected result when looking for '%s'." option) + | Ok (project_id, None) -> ( Lwt_io.printf - "This was a request inclusion column: PR was rejected.\n\ - Change of milestone requested to: %s\n" - rejected_milestone + "Required backporting field '%s' does not exist yet. Creating it..." + field >>= fun () -> - GitHub_mutations.update_milestone rejected_milestone issue ~bot_info - <&> ( GitHub_mutations.post_comment ~bot_info ~id - ~message: - "This PR was postponed. Please update accordingly the \ - milestone of any issue that this fixes as this cannot be done \ - automatically." - >>= GitHub_mutations.report_on_posting_comment ) - | _ -> - Lwt_io.printf "This was not a request inclusion column: ignoring.\n" + GitHub_mutations.create_new_release_management_field ~bot_info ~project_id + ~field + >>= function + | Ok (field_id, options) -> ( + match + List.find_map options ~f:(fun (option', field_value_id) -> + if String.equal option option' then Some field_value_id else None ) + with + | Some field_value_id -> + Lwt.return_ok (project_id, field_id, field_value_id) + | None -> + Lwt.return_error + (f + "Error new field '%s status' was created, but does not have a \ + '%s' option." + field option ) ) + | Error err -> + Lwt.return_error + (f "Error while creating new backporting field '%s': %s" field err) + ) + | Error err -> + Lwt.return_error (f "Error while getting project field values: %s" err) ) + >>= function + | Ok (project_id, field_id, field_value_id) -> ( + ( match id with + | `PR_ID card_id -> + GitHub_mutations.add_card_to_project ~bot_info ~card_id ~project_id + | `Card_ID card_id -> + Lwt.return_ok card_id ) + >>= fun result -> + match result with + | Ok card_id -> + GitHub_mutations.update_field_value ~bot_info ~card_id ~project_id + ~field_id ~field_value_id + | Error err -> + Lwt_io.printf "Error while adding card to project: %s\n" err ) + | Error err -> + Lwt_io.printl err let coq_push_action ~bot_info ~base_ref ~commits_msg = let* () = Lwt_io.printl "Merge and backport commit messages:" in let commit_action commit_msg = - if string_match ~regexp:"^Merge PR #\\([0-9]*\\):" commit_msg then - let pr_number = Str.matched_group 1 commit_msg |> Int.of_string in + if + string_match ~regexp:"^Merge \\(PR\\|pull request\\) #\\([0-9]*\\)" + commit_msg + then + let pr_number = Str.matched_group 2 commit_msg |> Int.of_string in Lwt_io.printf "%s\nPR #%d was merged.\n" commit_msg pr_number >>= fun () -> GitHub_queries.get_pull_request_id_and_milestone ~bot_info ~owner:"coq" ~repo:"coq" ~number:pr_number >>= fun pr_info -> match pr_info with - | Ok (Some (_, pr_id, {backport_info})) -> + | Ok (pr_id, backport_info) -> backport_info - |> Lwt_list.iter_p - (fun {backport_to; request_inclusion_column; backported_column} - -> + |> Lwt_list.iter_p (fun {backport_to} -> if "refs/heads/" ^ backport_to |> String.equal base_ref then Lwt_io.printf - "PR was merged into the backportig branch directly.\n" + "PR was merged into the backporting branch directly.\n" >>= fun () -> - GitHub_mutations.add_pr_to_column ~pr_id - ~column_id:backported_column ~bot_info + add_to_column ~bot_info ~backport_to (`PR_ID pr_id) "Shipped" else if String.equal base_ref "refs/heads/master" then (* For now, we hard code that PRs are only backported from master. In the future, we could make this @@ -2652,29 +2721,41 @@ let coq_push_action ~bot_info ~base_ref ~commits_msg = Lwt_io.printf "Backporting to %s was requested.\n" backport_to >>= fun () -> - GitHub_mutations.add_pr_to_column ~pr_id - ~column_id:request_inclusion_column ~bot_info + add_to_column ~bot_info ~backport_to (`PR_ID pr_id) + "Request inclusion" else Lwt_io.printf "PR was merged into a branch that is not the backporting \ branch nor the master branch.\n" ) - | Ok None -> - Lwt_io.printf "Did not get any backporting info.\n" | Error err -> Lwt_io.printf "Error: %s\n" err else if string_match ~regexp:"^Backport PR #\\([0-9]*\\):" commit_msg then let pr_number = Str.matched_group 1 commit_msg |> Int.of_string in Lwt_io.printf "%s\nPR #%d was backported.\n" commit_msg pr_number >>= fun () -> - GitHub_queries.get_backported_pr_info ~bot_info pr_number base_ref + GitHub_queries.get_pull_request_cards ~bot_info ~owner:"coq" ~repo:"coq" + ~number:pr_number >>= function - | Ok (Some ({card_id; column_id} as input)) -> - Lwt_io.printf "Moving card %s to column %s.\n" - (GitHub_ID.to_string card_id) - (GitHub_ID.to_string column_id) - >>= fun () -> GitHub_mutations.mv_card_to_column ~bot_info input - | Ok None -> - Lwt_io.printf "Could not find backporting info for backported PR.\n" + | Ok items -> ( + let backport_to = + String.chop_prefix_if_exists ~prefix:"refs/heads/" base_ref + in + let card_id = + items |> List.find_map ~f:(function id, 11 -> Some id | _ -> None) + in + match card_id with + | Some card_id -> + Lwt_io.printlf + "Pull request coq/coq#%d found in project 11. Updating its \ + fields." + pr_number + >>= fun () -> + add_to_column ~bot_info ~backport_to (`Card_ID card_id) "Shipped" + | None -> + (* We could do something in this case, like post a comment to + the PR and add the PR to the project. *) + Lwt_io.printlf "Pull request coq/coq#%d not found in project 11." + pr_number ) | Error e -> Lwt_io.printf "%s\n" e else Lwt.return_unit diff --git a/src/actions.mli b/src/actions.mli index b2a897f0..7630d62f 100644 --- a/src/actions.mli +++ b/src/actions.mli @@ -74,7 +74,11 @@ val adjust_milestone : -> unit Lwt.t val project_action : - bot_info:Bot_info.t -> issue:GitHub_types.issue -> column_id:int -> unit Lwt.t + bot_info:Bot_info.t + -> pr_id:GitHub_ID.t + -> backport_to:string + -> unit + -> unit Lwt.t val coq_push_action : bot_info:Bot_info.t diff --git a/src/bot.ml b/src/bot.ml index b2f3b884..95e7ed28 100644 --- a/src/bot.ml +++ b/src/bot.ml @@ -162,9 +162,9 @@ let callback _conn req body = | Error error_msg -> (fun () -> Lwt_io.printl error_msg) |> Lwt.async ; Server.respond_string ~status:`Bad_request ~body:error_msg () - | Ok (owner, repo) -> + | Ok (owner, _) -> (fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner ~repo + action_as_github_app ~bot_info ~key ~app_id ~owner (job_action ~gitlab_mapping job_info) ) |> Lwt.async ; Server.respond_string ~status:`OK ~body:"Job event." () ) @@ -174,9 +174,9 @@ let callback _conn req body = | Error error_msg -> (fun () -> Lwt_io.printl error_msg) |> Lwt.async ; Server.respond_string ~status:`Bad_request ~body:error_msg () - | Ok (owner, repo) -> + | Ok (owner, _) -> (fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner ~repo + action_as_github_app ~bot_info ~key ~app_id ~owner (pipeline_action ~gitlab_mapping pipeline_info) ) |> Lwt.async ; Server.respond_string ~status:`OK ~body:"Pipeline event." () ) @@ -199,16 +199,17 @@ let callback _conn req body = (Request.headers req) body with | Ok - ( true + ( Some install_id , PushEvent {owner= "coq"; repo= "coq"; base_ref; head_sha; commits_msg} ) -> (fun () -> init_git_bare_repository ~bot_info >>= fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner:"coq" ~repo:"coq" + action_as_github_app_from_install_id ~bot_info ~key ~app_id + ~install_id (coq_push_action ~base_ref ~commits_msg) - <&> action_as_github_app ~bot_info ~key ~app_id ~owner:"coq" - ~repo:"coq" + <&> action_as_github_app_from_install_id ~bot_info ~key ~app_id + ~install_id (mirror_action ~gitlab_domain:"gitlab.inria.fr" ~owner:"coq" ~repo:"coq" ~base_ref ~head_sha () ) ) |> Lwt.async ; @@ -217,13 +218,15 @@ let callback _conn req body = "Processing push event on Coq repository: analyzing merge / \ backporting info." () - | Ok (true, PushEvent {owner; repo; base_ref; head_sha; _}) -> ( + | Ok (Some install_id, PushEvent {owner; repo; base_ref; head_sha; _}) + -> ( match (owner, repo) with | "coq-community", ("docker-base" | "docker-coq") -> (fun () -> init_git_bare_repository ~bot_info >>= fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner ~repo + action_as_github_app_from_install_id ~bot_info ~key ~app_id + ~install_id (mirror_action ~gitlab_domain:"gitlab.com" ~owner ~repo ~base_ref ~head_sha () ) ) |> Lwt.async ; @@ -238,7 +241,8 @@ let callback _conn req body = (fun () -> init_git_bare_repository ~bot_info >>= fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner ~repo + action_as_github_app_from_install_id ~bot_info ~key ~app_id + ~install_id (mirror_action ~gitlab_domain:"gitlab.inria.fr" ~owner ~repo ~base_ref ~head_sha () ) ) |> Lwt.async ; @@ -256,7 +260,7 @@ let callback _conn req body = init_git_bare_repository ~bot_info >>= fun () -> action_as_github_app ~bot_info ~key ~app_id - ~owner:pr_info.issue.issue.owner ~repo:pr_info.issue.issue.repo + ~owner:pr_info.issue.issue.owner (pull_request_closed_action ~gitlab_mapping ~github_mapping pr_info ) ) |> Lwt.async ; @@ -272,14 +276,13 @@ let callback _conn req body = init_git_bare_repository ~bot_info >>= fun () -> action_as_github_app ~bot_info ~key ~app_id - ~owner:pr_info.issue.issue.owner ~repo:pr_info.issue.issue.repo + ~owner:pr_info.issue.issue.owner (pull_request_updated_action ~action ~pr_info ~gitlab_mapping ~github_mapping ) | Ok (_, IssueClosed {issue}) -> (* TODO: only for projects that requested this feature *) (fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:issue.owner - ~repo:issue.repo (adjust_milestone ~issue ~sleep_time:5.) ) |> Lwt.async ; Server.respond_string ~status:`OK @@ -287,22 +290,31 @@ let callback _conn req body = (f "Issue %s/%s#%d was closed: checking its milestone." issue.owner issue.repo issue.number ) () - | Ok (_, RemovedFromProject ({issue= Some issue; column_id} as card)) -> + | Ok + ( Some (1062161 as install_id) (* Coq's installation number *) + , PullRequestCardEdited + { project_number= 11 (* Coq's backporting project number *) + ; pr_id + ; field + ; old_value= "Request inclusion" + ; new_value= "Rejected" } ) + when String.is_suffix ~suffix:" status" field -> + let backport_to = String.drop_suffix field 7 in (fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner:issue.owner - ~repo:issue.repo - (project_action ~issue ~column_id) ) + action_as_github_app_from_install_id ~bot_info ~key ~app_id + ~install_id + (project_action ~pr_id ~backport_to ()) ) |> Lwt.async ; Server.respond_string ~status:`OK ~body: (f - "Issue or PR %s/%s#%d was removed from project column %d: \ - checking if this was a backporting column." - issue.owner issue.repo issue.number card.column_id ) + "PR proposed for backporting was rejected from inclusion in \ + %s. Updating the milestone." + backport_to ) () - | Ok (_, RemovedFromProject _) -> + | Ok (_, PullRequestCardEdited _) -> Server.respond_string ~status:`OK - ~body:"Note card removed from project: nothing to do." () + ~body:"Unsupported pull request card edition." () | Ok (_, IssueOpened ({body= Some body} as issue_info)) -> ( let body = body |> trim_comments |> strip_quoted_bot_name ~github_bot_name @@ -313,7 +325,7 @@ let callback _conn req body = init_git_bare_repository ~bot_info >>= fun () -> action_as_github_app ~bot_info ~key ~app_id - ~owner:issue_info.issue.owner ~repo:issue_info.issue.repo + ~owner:issue_info.issue.owner (run_coq_minimizer ~script ~comment_thread_id:issue_info.id ~comment_author:issue_info.user ~owner:issue_info.issue.owner ~repo:issue_info.issue.repo @@ -325,7 +337,7 @@ let callback _conn req body = Server.respond_string ~status:`OK ~body:(f "Unhandled new issue: %s" body) () ) - | Ok (signed, CommentCreated comment_info) -> ( + | Ok (install_id, CommentCreated comment_info) -> ( let body = comment_info.body |> trim_comments |> strip_quoted_bot_name ~github_bot_name @@ -337,7 +349,6 @@ let callback _conn req body = >>= fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:comment_info.issue.issue.owner - ~repo:comment_info.issue.issue.repo (run_coq_minimizer ~script ~comment_thread_id:comment_info.issue.id ~comment_author:comment_info.author @@ -358,7 +369,6 @@ let callback _conn req body = >>= fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:comment_info.issue.issue.owner - ~repo:comment_info.issue.issue.repo (ci_minimize ~comment_info ~requests ~comment_on_error:true ~options ~bug_file_contents:(Some bug_file_contents) ) ) |> Lwt.async ; @@ -372,7 +382,6 @@ let callback _conn req body = >>= fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:comment_info.issue.issue.owner - ~repo:comment_info.issue.issue.repo (ci_minimize ~comment_info ~requests ~comment_on_error:true ~options ~bug_file_contents:None ) ) @@ -389,7 +398,7 @@ let callback _conn req body = && comment_info.issue.pull_request && String.equal comment_info.issue.issue.owner "coq" && String.equal comment_info.issue.issue.repo "coq" - && signed + && Option.is_some install_id then let full_ci = match Str.matched_group 1 body with @@ -406,7 +415,6 @@ let callback _conn req body = >>= fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:comment_info.issue.issue.owner - ~repo:comment_info.issue.issue.repo (run_ci_action ~comment_info ?full_ci ~gitlab_mapping ~github_mapping () ) else if @@ -417,12 +425,11 @@ let callback _conn req body = && comment_info.issue.pull_request && String.equal comment_info.issue.issue.owner "coq" && String.equal comment_info.issue.issue.repo "coq" - && signed + && Option.is_some install_id then ( (fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:comment_info.issue.issue.owner - ~repo:comment_info.issue.issue.repo (merge_pull_request_action comment_info) ) |> Lwt.async ; Server.respond_string ~status:`OK @@ -436,12 +443,11 @@ let callback _conn req body = && comment_info.issue.pull_request && String.equal comment_info.issue.issue.owner "coq" && String.equal comment_info.issue.issue.repo "coq" - && signed + && Option.is_some install_id then ( (fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:comment_info.issue.issue.owner - ~repo:comment_info.issue.issue.repo (run_bench ~key_value_pairs:[("coq_native", "yes")] comment_info ) ) @@ -456,12 +462,11 @@ let callback _conn req body = && comment_info.issue.pull_request && String.equal comment_info.issue.issue.owner "coq" && String.equal comment_info.issue.issue.repo "coq" - && signed + && Option.is_some install_id then ( (fun () -> action_as_github_app ~bot_info ~key ~app_id ~owner:comment_info.issue.issue.owner - ~repo:comment_info.issue.issue.repo (run_bench comment_info) ) |> Lwt.async ; Server.respond_string ~status:`OK @@ -471,11 +476,11 @@ let callback _conn req body = Server.respond_string ~status:`OK ~body:(f "Unhandled comment: %s" body) () ) ) ) - | Ok (signed, CheckRunReRequested {external_id}) -> ( - if not signed then - Server.respond_string ~status:(Code.status_of_code 401) - ~body:"Request to rerun check run must be signed." () - else if String.is_empty external_id then + | Ok (None, CheckRunReRequested _) -> + Server.respond_string ~status:(Code.status_of_code 401) + ~body:"Request to rerun check run must be signed." () + | Ok (Some _, CheckRunReRequested {external_id}) -> ( + if String.is_empty external_id then Server.respond_string ~status:(Code.status_of_code 400) ~body:"Request to rerun check run but empty external ID." () else @@ -548,11 +553,11 @@ let callback _conn req body = let warn_after = 30 in let close_after = 30 in (fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner ~repo + action_as_github_app ~bot_info ~key ~app_id ~owner (coq_check_needs_rebase_pr ~owner ~repo ~warn_after ~close_after ~throttle:6 ) >>= fun () -> - action_as_github_app ~bot_info ~key ~app_id ~owner ~repo + action_as_github_app ~bot_info ~key ~app_id ~owner (coq_check_stale_pr ~owner ~repo ~after:close_after ~throttle:4) ) |> Lwt.async ; diff --git a/src/github_installations.ml b/src/github_installations.ml index 59b04a75..69e67769 100644 --- a/src/github_installations.ml +++ b/src/github_installations.ml @@ -1,51 +1,80 @@ open Base open Bot_components +open Helpers open Lwt -let installation_tokens : (string, string * float) Base.Hashtbl.t = +let installation_ids : (string, int) Base.Hashtbl.t = Hashtbl.create (module String) -let action_with_new_installation_token ~bot_info ~key ~app_id ~owner ~repo - action = +let installation_tokens : (int, string * float) Base.Hashtbl.t = + Hashtbl.create (module Int) + +let action_with_new_installation_token ~bot_info ~key ~app_id ~install_id action + = (* Installation tokens expire after one hour, we stop using them after 40 minutes *) - GitHub_app.get_installation_token ~bot_info ~key ~app_id ~owner ~repo + GitHub_app.get_installation_token ~bot_info ~key ~app_id ~install_id >>= function | Ok (install_token, expiration_date) -> let _ = - Hashtbl.add installation_tokens ~key:owner + Hashtbl.add installation_tokens ~key:install_id ~data:(install_token, expiration_date) in let bot_info : Bot_info.t = {bot_info with github_install_token= Some install_token} in action ~bot_info - | Error _ -> - (* If we cannot retrieve an installation token for the repository - repo owned by owner, we execute the action with the github access token. *) - action ~bot_info + | Error err -> + failwith + (f + "We did not manage to get an installation token for installation \ + %d: %s" + install_id err ) -let action_as_github_app ~bot_info ~key ~app_id ~owner ~repo action = +let action_as_github_app_from_install_id ~bot_info ~key ~app_id ~install_id + action = (* Executes an action with an installation token if the repository has the GitHub app installed. Generates a new installation token if the existing one has expired. *) - match Hashtbl.find installation_tokens owner with + match Hashtbl.find installation_tokens install_id with | Some (install_token, expiration_date) -> if Float.(expiration_date < Unix.time ()) then ( - Hashtbl.remove installation_tokens owner ; - action_with_new_installation_token ~bot_info ~key ~app_id ~owner ~repo + Hashtbl.remove installation_tokens install_id ; + action_with_new_installation_token ~bot_info ~key ~app_id ~install_id action ) else let bot_info : Bot_info.t = {bot_info with github_install_token= Some install_token} in action ~bot_info + | None -> + action_with_new_installation_token ~bot_info ~key ~app_id ~install_id + action + +let action_as_github_app ~bot_info ~key ~app_id ~owner action = + (* Executes an action with an installation token if the repository has + the GitHub app installed. + Generates a new installation token if the existing one has expired. *) + match Hashtbl.find installation_ids owner with + | Some install_id -> + action_as_github_app_from_install_id ~bot_info ~key ~app_id ~install_id + action | None -> ( GitHub_app.get_installations ~bot_info ~key ~app_id >>= function - | Ok installs -> - if List.exists installs ~f:(String.equal owner) then - action_with_new_installation_token ~bot_info ~key ~app_id ~owner - ~repo action - else action ~bot_info - | Error _ -> - action ~bot_info ) + | Ok installs -> ( + match + installs + |> List.find_map ~f:(fun (owner', install_id) -> + if String.equal owner owner' then Some install_id else None ) + with + | Some install_id -> + let _ = Hashtbl.add installation_ids ~key:owner ~data:install_id in + action_as_github_app_from_install_id ~bot_info ~key ~app_id + ~install_id action + | None -> + (* If the owner does not have the GitHub app installed, + we execute the action with the github access token. *) + action ~bot_info ) + | Error err -> + failwith + (f "We did not manage to get the list of installations: %s" err) ) diff --git a/src/github_installations.mli b/src/github_installations.mli index 118b519b..5ec7d1df 100644 --- a/src/github_installations.mli +++ b/src/github_installations.mli @@ -1,12 +1,21 @@ open Bot_components -val installation_tokens : (string, string * float) Base.Hashtbl.t +val installation_ids : (string, int) Base.Hashtbl.t + +val installation_tokens : (int, string * float) Base.Hashtbl.t + +val action_as_github_app_from_install_id : + bot_info:Bot_info.t + -> key:Mirage_crypto_pk.Rsa.priv + -> app_id:int + -> install_id:int + -> (bot_info:Bot_info.t -> 'a Lwt.t) + -> 'a Lwt.t val action_as_github_app : bot_info:Bot_info.t -> key:Mirage_crypto_pk.Rsa.priv -> app_id:int -> owner:string - -> repo:string -> (bot_info:Bot_info.t -> 'a Lwt.t) -> 'a Lwt.t