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
}