BatchUpdateIssuesStatus batch updates issues status.
(ctx context.Context, req *connect.Request[v1pb.BatchUpdateIssuesStatusRequest])
| 1111 | |
| 1112 | // BatchUpdateIssuesStatus batch updates issues status. |
| 1113 | func (s *IssueService) BatchUpdateIssuesStatus(ctx context.Context, req *connect.Request[v1pb.BatchUpdateIssuesStatusRequest]) (*connect.Response[v1pb.BatchUpdateIssuesStatusResponse], error) { |
| 1114 | user, ok := GetUserFromContext(ctx) |
| 1115 | if !ok { |
| 1116 | return nil, connect.NewError(connect.CodeInternal, errors.Errorf("user not found")) |
| 1117 | } |
| 1118 | |
| 1119 | if len(req.Msg.Issues) == 0 { |
| 1120 | return connect.NewResponse(&v1pb.BatchUpdateIssuesStatusResponse{}), nil |
| 1121 | } |
| 1122 | |
| 1123 | newStatus, err := convertToAPIIssueStatus(req.Msg.Status) |
| 1124 | if err != nil { |
| 1125 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("failed to convert to issue status, err: %v", err)) |
| 1126 | } |
| 1127 | |
| 1128 | // Parse issue names and validate all issues belong to the same project. |
| 1129 | var projectID string |
| 1130 | issueUIDs := make([]int64, 0, len(req.Msg.Issues)) |
| 1131 | for i, issueName := range req.Msg.Issues { |
| 1132 | issueProjectID, issueUID, err := common.GetProjectIDIssueUID(issueName) |
| 1133 | if err != nil { |
| 1134 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("invalid issue name %q: %v", issueName, err)) |
| 1135 | } |
| 1136 | |
| 1137 | // Ensure all issues belong to the same project. |
| 1138 | if i == 0 { |
| 1139 | projectID = issueProjectID |
| 1140 | } else if issueProjectID != projectID { |
| 1141 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("all issues must belong to the same project, found %q and %q", projectID, issueProjectID)) |
| 1142 | } |
| 1143 | |
| 1144 | issueUIDs = append(issueUIDs, issueUID) |
| 1145 | } |
| 1146 | |
| 1147 | // Get project early for webhooks. |
| 1148 | project, err := s.store.GetProject(ctx, &store.FindProjectMessage{Workspace: common.GetWorkspaceIDFromContext(ctx), ResourceID: &projectID}) |
| 1149 | if err != nil { |
| 1150 | return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to get project: %v", err)) |
| 1151 | } |
| 1152 | if project == nil { |
| 1153 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("project %q not found", projectID)) |
| 1154 | } |
| 1155 | |
| 1156 | // Batch update issue statuses. This validates project membership, DONE status, and returns old statuses. |
| 1157 | oldIssueStatuses, err := s.store.BatchUpdateIssueStatuses(ctx, projectID, issueUIDs, newStatus) |
| 1158 | if err != nil { |
| 1159 | if common.ErrorCode(err) == common.Invalid { |
| 1160 | return nil, connect.NewError(connect.CodeFailedPrecondition, err) |
| 1161 | } |
| 1162 | return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to batch update issues, err: %v", err)) |
| 1163 | } |
| 1164 | |
| 1165 | // Batch create issue comments. |
| 1166 | issueComments := make([]*store.IssueCommentMessage, 0, len(issueUIDs)) |
| 1167 | for _, issueUID := range issueUIDs { |
| 1168 | issueComments = append(issueComments, &store.IssueCommentMessage{ |
| 1169 | ProjectID: projectID, |
| 1170 | IssueUID: issueUID, |
nothing calls this directly
no test coverage detected