Skip to content

Commit

Permalink
Automatically create project v2 field when it does not exist.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zimmi48 committed Jul 1, 2024
1 parent e700575 commit b32fd45
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 39 deletions.
4 changes: 2 additions & 2 deletions bot-components/GitHub_GraphQL.ml
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,8 @@ module UpdateFieldValue =
module CreateNewReleaseManagementField =
[%graphql
{|
mutation createNewField($project_id: ID!, $name: String!) {
createProjectV2Field(input: {projectId: $project_id, dataType: SINGLE_SELECT, name: $name, 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."}]}) {
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
Expand Down
24 changes: 19 additions & 5 deletions bot-components/GitHub_mutations.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,31 @@ let update_field_value ~bot_info ~card_id ~project_id ~field_id ~field_value_id
| Error err ->
Lwt_io.printlf "Error while updating field value: %s" err

let create_new_release_management_field ~bot_info ~project_id ~name =
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) ~name ()
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 _ ->
Lwt.return_unit
| 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_io.printlf "Error while creating new field: %s" 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
Expand Down
5 changes: 4 additions & 1 deletion bot-components/GitHub_mutations.mli
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ val update_field_value :
-> unit Lwt.t

val create_new_release_management_field :
bot_info:Bot_info.t -> project_id:GitHub_ID.t -> name:string -> unit Lwt.t
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
Expand Down
9 changes: 6 additions & 3 deletions bot-components/GitHub_queries.ml
Original file line number Diff line number Diff line change
Expand Up @@ -960,12 +960,15 @@ let get_project_field_values ~bot_info ~organization ~project ~field ~options =
let options = field.options |> Array.to_list in
Lwt.return_ok
( GitHub_ID.of_string project.id
, GitHub_ID.of_string field.id
, List.map ~f:(fun {name; id} -> (name, id)) options )
, 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 ->
Lwt.return_error (f "Field %s does not exist." field) )
(* 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) )
Expand Down
2 changes: 1 addition & 1 deletion bot-components/GitHub_queries.mli
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,4 @@ val get_project_field_values :
-> project:int
-> field:string
-> options:string array
-> (GitHub_ID.t * GitHub_ID.t * (string * string) list, string) result Lwt.t
-> (GitHub_ID.t * (GitHub_ID.t * (string * string) list) option, string) result Lwt.t
162 changes: 135 additions & 27 deletions src/actions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2646,13 +2646,15 @@ let coq_push_action ~bot_info ~base_ref ~commits_msg =
Lwt_io.printf
"PR was merged into the backporting branch directly.\n"
>>= fun () ->
let field = backport_to ^ " status" in
GitHub_queries.get_project_field_values ~bot_info
~organization:"coq" ~project:11
~field:(backport_to ^ " status") ~options:[|"Shipped"|]
~organization:"coq" ~project:11 ~field
~options:[|"Shipped"|]
>>= fun project_info ->
match project_info with
| Ok (project_id, field_id, [("Shipped", field_value_id)])
-> (
| Ok
( project_id
, Some (field_id, [("Shipped", field_value_id)]) ) -> (
GitHub_mutations.add_card_to_project ~bot_info ~card_id
~project_id
>>= fun result ->
Expand All @@ -2663,15 +2665,54 @@ let coq_push_action ~bot_info ~base_ref ~commits_msg =
| Error err ->
Lwt_io.printf
"Error while adding card to project: %s\n" err )
| Ok (_, _, []) ->
| Ok (_, Some (_, [])) ->
Lwt_io.printf
"Error: Could not find 'Shipped' option in the field.\n"
| Ok (_, _, _) ->
| Ok (_, Some _) ->
Lwt_io.printf
"Error: Unexpected result when looking for 'Shipped'.\n"
| Ok (project_id, None) -> (
Lwt_io.printf
"Required backporting field '%s' does not exist yet. \
Creating it..."
field
>>= fun () ->
GitHub_mutations.create_new_release_management_field
~bot_info ~project_id ~field
>>= function
| Ok (field_id, options) -> (
match
List.find_map options ~f:(function
| "Shipped", field_value_id ->
Some field_value_id
| _ ->
None )
with
| Some field_value_id -> (
(* duplicated code: not ideal *)
GitHub_mutations.add_card_to_project ~bot_info
~card_id ~project_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 )
| None ->
Lwt_io.printlf
"Error new field '%s status' was created, but \
does not have a 'Shipped' option."
field )
| Error err ->
Lwt_io.printlf
"Error while creating new backporting field '%s': \
%s"
field err )
| Error err ->
(* TODO: we could treat the case where the field does not
exist yet and create it. *)
Lwt_io.printf
"Error while getting project field values: %s\n" err
else if String.equal base_ref "refs/heads/master" then
Expand All @@ -2682,16 +2723,16 @@ let coq_push_action ~bot_info ~base_ref ~commits_msg =
Lwt_io.printf "Backporting to %s was requested.\n"
backport_to
>>= fun () ->
let field = backport_to ^ " status" in
GitHub_queries.get_project_field_values ~bot_info
~organization:"coq" ~project:11
~field:(backport_to ^ " status")
~organization:"coq" ~project:11 ~field
~options:[|"Request inclusion"|]
>>= fun project_info ->
match project_info with
| Ok
( project_id
, field_id
, [("Request inclusion", field_value_id)] ) -> (
, Some (field_id, [("Request inclusion", field_value_id)])
) -> (
GitHub_mutations.add_card_to_project ~bot_info ~card_id
~project_id
>>= fun result ->
Expand All @@ -2702,17 +2743,56 @@ let coq_push_action ~bot_info ~base_ref ~commits_msg =
| Error err ->
Lwt_io.printf
"Error while adding card to project: %s\n" err )
| Ok (_, _, []) ->
| Ok (_, Some (_, [])) ->
Lwt_io.printf
"Error: Could not find 'Request inclusion' option in \
the field.\n"
| Ok (_, _, _) ->
| Ok (_, Some _) ->
Lwt_io.printf
"Error: Unexpected result when looking for 'Request \
inclusion'.\n"
| Ok (project_id, None) -> (
Lwt_io.printf
"Required backporting field '%s' does not exist yet. \
Creating it..."
field
>>= fun () ->
GitHub_mutations.create_new_release_management_field
~bot_info ~project_id ~field
>>= function
| Ok (field_id, options) -> (
match
List.find_map options ~f:(function
| "Request inclusion", field_value_id ->
Some field_value_id
| _ ->
None )
with
| Some field_value_id -> (
(* duplicated code: not ideal *)
GitHub_mutations.add_card_to_project ~bot_info
~card_id ~project_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 )
| None ->
Lwt_io.printlf
"Error new field '%s status' was created, but \
does not have a 'Request inclusion' option."
field )
| Error err ->
Lwt_io.printlf
"Error while creating new backporting field '%s': \
%s"
field err )
| Error err ->
(* TODO: we could treat the case where the field does not
exist yet and create it. *)
Lwt_io.printf
"Error while getting project field values: %s\n" err
else
Expand Down Expand Up @@ -2744,27 +2824,55 @@ let coq_push_action ~bot_info ~base_ref ~commits_msg =
>>= fun () ->
(* We could avoid this query by looking for this field in the
previous query to GitHub. *)
let field = backport_to ^ " status" in
GitHub_queries.get_project_field_values ~bot_info
~organization:"coq" ~project:11 ~field:(backport_to ^ " status")
~options:[|"Shipped"|]
~organization:"coq" ~project:11 ~field ~options:[|"Shipped"|]
>>= fun project_info ->
match project_info with
| Ok (project_id, field_id, [("Shipped", field_value_id)]) ->
| Ok (project_id, Some (field_id, [("Shipped", field_value_id)]))
->
GitHub_mutations.update_field_value ~bot_info ~card_id
~project_id ~field_id ~field_value_id
| Ok (_, _, []) ->
| Ok (_, Some (_, [])) ->
Lwt_io.printf
"Error: Could not find 'Shipped' option in the field named \
'%s status'.\n"
"Error: Field '%s status' exists but does not have a \
'Shipped' option.\n"
backport_to
| Ok (_, _, _) ->
| Ok (_, Some _) ->
Lwt_io.printf
"Error: Unexpected result when looking for 'Shipped' \
option in the field named '%s status'.\n"
backport_to
option in the field named '%s'.\n"
field
| Ok (project_id, None) -> (
Lwt_io.printf
"Required backporting field '%s' does not exist yet. \
Creating it..."
field
>>= fun () ->
GitHub_mutations.create_new_release_management_field ~bot_info
~project_id ~field
>>= function
| Ok (field_id, options) -> (
match
List.find_map options ~f:(function
| "Shipped", field_value_id ->
Some field_value_id
| _ ->
None )
with
| Some field_value_id ->
GitHub_mutations.update_field_value ~bot_info ~card_id
~project_id ~field_id ~field_value_id
| None ->
Lwt_io.printlf
"Error new field '%s status' was created, but does \
not have a 'Shipped' option."
field )
| Error err ->
Lwt_io.printlf
"Error while creating new backporting field '%s': %s"
field err )
| Error err ->
(* TODO: we could treat the case where the field does not
exist yet and create it. *)
Lwt_io.printf "Error while getting project field values: %s\n"
err )
| None ->
Expand Down

0 comments on commit b32fd45

Please sign in to comment.