api/merge_request.go (334 lines of code) (raw):

package api import ( "errors" "net/http" "sort" gitlab "gitlab.com/gitlab-org/api/client-go" ) var ErrTodoExists = errors.New("To-do already exists.") var ApproveMR = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.ApproveMergeRequestOptions) (*gitlab.MergeRequestApprovals, error) { if client == nil { client = apiClient.Lab() } mr, _, err := client.MergeRequestApprovals.ApproveMergeRequest(projectID, mrID, opts) if err != nil { return nil, err } return mr, nil } var GetMRApprovalState = func(client *gitlab.Client, projectID any, mrID int, opts ...gitlab.RequestOptionFunc) (*gitlab.MergeRequestApprovalState, error) { if client == nil { client = apiClient.Lab() } mrApprovals, _, err := client.MergeRequestApprovals.GetApprovalState(projectID, mrID, opts...) if err != nil { return nil, err } return mrApprovals, nil } var GetMR = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.GetMergeRequestsOptions) (*gitlab.MergeRequest, error) { if client == nil { client = apiClient.Lab() } mr, _, err := client.MergeRequests.GetMergeRequest(projectID, mrID, opts) if err != nil { return nil, err } return mr, nil } // ListGroupMRs retrieves merge requests for a given group with optional filtering by assignees or reviewers. // // Parameters: // - client: A GitLab client instance. // - groupID: The ID or name of the group. // - opts: GitLab-specific options for listing group merge requests. // - listOpts: Optional list of arguments to filter by assignees or reviewers. // May be any combination of api.WithMRAssignees and api.WithMRReviewers. // // Returns: // - A slice of GitLab merge request objects and an error, if any. // // Example usage: // // groupMRs, err := api.ListGroupMRs(client, "my-group", &gitlab.ListGroupMergeRequestsOptions{}, // api.WithMRAssignees([]int{123}), // api.WithMRReviewers([]int{456, 789})) var ListGroupMRs = func(client *gitlab.Client, projectID any, opts *gitlab.ListGroupMergeRequestsOptions, listOpts ...CliListMROption) ([]*gitlab.BasicMergeRequest, error) { composedListOpts := composeCliListMROptions(listOpts...) assigneeIds, reviewerIds := composedListOpts.assigneeIds, composedListOpts.reviewerIds if len(assigneeIds) > 0 || len(reviewerIds) > 0 { return listGroupMRsWithAssigneesOrReviewers(client, projectID, opts, assigneeIds, reviewerIds) } else { return listGroupMRsBase(client, projectID, opts) } } var listGroupMRsBase = func(client *gitlab.Client, groupID any, opts *gitlab.ListGroupMergeRequestsOptions) ([]*gitlab.BasicMergeRequest, error) { if client == nil { client = apiClient.Lab() } if opts.PerPage == 0 { opts.PerPage = DefaultListLimit } mrs, _, err := client.MergeRequests.ListGroupMergeRequests(groupID, opts) if err != nil { return nil, err } return mrs, nil } var listGroupMRsWithAssigneesOrReviewers = func(client *gitlab.Client, projectID any, opts *gitlab.ListGroupMergeRequestsOptions, assigneeIds []int, reviewerIds []int) ([]*gitlab.BasicMergeRequest, error) { if client == nil { client = apiClient.Lab() } if opts.PerPage == 0 { opts.PerPage = DefaultListLimit } mrMap := make(map[int]*gitlab.BasicMergeRequest) for _, id := range assigneeIds { opts.AssigneeID = gitlab.AssigneeID(id) assigneeMrs, err := listGroupMRsBase(client, projectID, opts) if err != nil { return nil, err } for _, mr := range assigneeMrs { mrMap[mr.ID] = mr } } opts.AssigneeID = nil // reset because it's Assignee OR Reviewer for _, id := range reviewerIds { opts.ReviewerID = gitlab.ReviewerID(id) reviewerMrs, err := listGroupMRsBase(client, projectID, opts) if err != nil { return nil, err } for _, mr := range reviewerMrs { mrMap[mr.ID] = mr } } mrs := make([]*gitlab.BasicMergeRequest, 0, len(mrMap)) for _, mr := range mrMap { mrs = append(mrs, mr) } sort.Slice(mrs, func(i, j int) bool { return mrs[i].CreatedAt.After(*mrs[j].CreatedAt) }) return mrs, nil } var ProjectListMROptionsToGroup = func(l *gitlab.ListProjectMergeRequestsOptions) *gitlab.ListGroupMergeRequestsOptions { return &gitlab.ListGroupMergeRequestsOptions{ ListOptions: l.ListOptions, State: l.State, OrderBy: l.OrderBy, Sort: l.Sort, Milestone: l.Milestone, View: l.View, Labels: l.Labels, NotLabels: l.NotLabels, WithLabelsDetails: l.WithLabelsDetails, WithMergeStatusRecheck: l.WithMergeStatusRecheck, CreatedAfter: l.CreatedAfter, CreatedBefore: l.CreatedBefore, UpdatedAfter: l.UpdatedAfter, UpdatedBefore: l.UpdatedBefore, Scope: l.Scope, AuthorID: l.AuthorID, AssigneeID: l.AssigneeID, ReviewerID: l.ReviewerID, ReviewerUsername: l.ReviewerUsername, MyReactionEmoji: l.MyReactionEmoji, SourceBranch: l.SourceBranch, TargetBranch: l.TargetBranch, Search: l.Search, WIP: l.WIP, } } // ListMRs retrieves merge requests for a given project with optional filtering by assignees or reviewers. // // Parameters: // - client: A GitLab client instance. // - projectID: The ID or name of the project. // - opts: GitLab-specific options for listing merge requests. // - listOpts: Optional list of arguments to filter by assignees or reviewers. // May be any combination of api.WithMRAssignees and api.WithMRReviewers. // // Returns: // - A slice of GitLab merge request objects and an error, if any. // // Example usage: // // mrs, err := api.ListMRs(client, "my-group", &gitlab.ListProjectMergeRequestsOptions{}, // api.WithMRAssignees([]int{123, 456}), // api.WithMRReviewers([]int{789})) var ListMRs = func(client *gitlab.Client, projectID any, opts *gitlab.ListProjectMergeRequestsOptions, listOpts ...CliListMROption) ([]*gitlab.BasicMergeRequest, error) { composedListOpts := composeCliListMROptions(listOpts...) assigneeIds, reviewerIds := composedListOpts.assigneeIds, composedListOpts.reviewerIds if len(assigneeIds) > 0 || len(reviewerIds) > 0 { return listMRsWithAssigneesOrReviewers(client, projectID, opts, assigneeIds, reviewerIds) } else { return listMRsBase(client, projectID, opts) } } var listMRsBase = func(client *gitlab.Client, projectID any, opts *gitlab.ListProjectMergeRequestsOptions) ([]*gitlab.BasicMergeRequest, error) { if client == nil { client = apiClient.Lab() } if opts.PerPage == 0 { opts.PerPage = DefaultListLimit } mrs, _, err := client.MergeRequests.ListProjectMergeRequests(projectID, opts) if err != nil { return nil, err } return mrs, nil } var listMRsWithAssigneesOrReviewers = func(client *gitlab.Client, projectID any, opts *gitlab.ListProjectMergeRequestsOptions, assigneeIds []int, reviewerIds []int) ([]*gitlab.BasicMergeRequest, error) { if client == nil { client = apiClient.Lab() } if opts.PerPage == 0 { opts.PerPage = DefaultListLimit } mrMap := make(map[int]*gitlab.BasicMergeRequest) for _, id := range assigneeIds { opts.AssigneeID = gitlab.AssigneeID(id) assigneeMrs, err := listMRsBase(client, projectID, opts) if err != nil { return nil, err } for _, mr := range assigneeMrs { mrMap[mr.ID] = mr } } opts.AssigneeID = nil // reset because it's Assignee OR Reviewer for _, id := range reviewerIds { opts.ReviewerID = gitlab.ReviewerID(id) reviewerMrs, err := listMRsBase(client, projectID, opts) if err != nil { return nil, err } for _, mr := range reviewerMrs { mrMap[mr.ID] = mr } } mrs := make([]*gitlab.BasicMergeRequest, 0, len(mrMap)) for _, mr := range mrMap { mrs = append(mrs, mr) } sort.Slice(mrs, func(i, j int) bool { return mrs[i].CreatedAt.After(*mrs[j].CreatedAt) }) return mrs, nil } var UpdateMR = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.UpdateMergeRequestOptions) (*gitlab.MergeRequest, error) { if client == nil { client = apiClient.Lab() } mr, _, err := client.MergeRequests.UpdateMergeRequest(projectID, mrID, opts) if err != nil { return nil, err } return mr, nil } var DeleteMR = func(client *gitlab.Client, projectID any, mrID int) error { if client == nil { client = apiClient.Lab() } _, err := client.MergeRequests.DeleteMergeRequest(projectID, mrID) if err != nil { return err } return nil } var MergeMR = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.AcceptMergeRequestOptions) (*gitlab.MergeRequest, *gitlab.Response, error) { if client == nil { client = apiClient.Lab() } mrs, resp, err := client.MergeRequests.AcceptMergeRequest(projectID, mrID, opts) if err != nil { return nil, resp, err } return mrs, resp, nil } var CreateMR = func(client *gitlab.Client, projectID any, opts *gitlab.CreateMergeRequestOptions) (*gitlab.MergeRequest, error) { if client == nil { client = apiClient.Lab() } mr, _, err := client.MergeRequests.CreateMergeRequest(projectID, opts) if err != nil { return nil, err } return mr, nil } var GetMRLinkedIssues = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.GetIssuesClosedOnMergeOptions) ([]*gitlab.Issue, error) { if client == nil { client = apiClient.Lab() } mrIssues, _, err := client.MergeRequests.GetIssuesClosedOnMerge(projectID, mrID, opts) if err != nil { return nil, err } return mrIssues, nil } var CreateMRNote = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.CreateMergeRequestNoteOptions) (*gitlab.Note, error) { if client == nil { client = apiClient.Lab() } note, _, err := client.Notes.CreateMergeRequestNote(projectID, mrID, opts) if err != nil { return note, err } return note, nil } var ListMRNotes = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.ListMergeRequestNotesOptions) ([]*gitlab.Note, error) { if client == nil { client = apiClient.Lab() } if opts.PerPage == 0 { opts.PerPage = DefaultListLimit } notes, _, err := client.Notes.ListMergeRequestNotes(projectID, mrID, opts) if err != nil { return notes, err } return notes, nil } var RebaseMR = func(client *gitlab.Client, projectID any, mrID int, opts *gitlab.RebaseMergeRequestOptions) error { if client == nil { client = apiClient.Lab() } _, err := client.MergeRequests.RebaseMergeRequest(projectID, mrID, opts) if err != nil { return err } return nil } var UnapproveMR = func(client *gitlab.Client, projectID any, mrID int) error { if client == nil { client = apiClient.Lab() } _, err := client.MergeRequestApprovals.UnapproveMergeRequest(projectID, mrID) if err != nil { return err } return nil } var SubscribeToMR = func(client *gitlab.Client, projectID any, mrID int, opts gitlab.RequestOptionFunc) (*gitlab.MergeRequest, error) { if client == nil { client = apiClient.Lab() } mr, _, err := client.MergeRequests.SubscribeToMergeRequest(projectID, mrID, opts) if err != nil { return nil, err } return mr, nil } var UnsubscribeFromMR = func(client *gitlab.Client, projectID any, mrID int, opts gitlab.RequestOptionFunc) (*gitlab.MergeRequest, error) { if client == nil { client = apiClient.Lab() } mr, _, err := client.MergeRequests.UnsubscribeFromMergeRequest(projectID, mrID, opts) if err != nil { return nil, err } return mr, nil } var MRTodo = func(client *gitlab.Client, projectID any, mrID int, opts gitlab.RequestOptionFunc) (*gitlab.Todo, error) { if client == nil { client = apiClient.Lab() } mr, resp, err := client.MergeRequests.CreateTodo(projectID, mrID, opts) if resp.StatusCode == http.StatusNotModified { return nil, ErrTodoExists } if err != nil { return nil, err } return mr, nil } type cliListMROptions struct { assigneeIds []int reviewerIds []int } type CliListMROption func(*cliListMROptions) func WithMRAssignees(assigneeIds []int) CliListMROption { return func(c *cliListMROptions) { c.assigneeIds = assigneeIds } } func WithMRReviewers(reviewerIds []int) CliListMROption { return func(c *cliListMROptions) { c.reviewerIds = reviewerIds } } func composeCliListMROptions(optionSetters ...CliListMROption) *cliListMROptions { opts := &cliListMROptions{} for _, setter := range optionSetters { setter(opts) } return opts }